1 /* packet_comment_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
10 #include "capture_comment_dialog.h"
11 #include <ui_capture_comment_dialog.h>
15 #include "ui/simple_dialog.h"
16 #include "ui/qt/main_window.h"
17 #include "ui/qt/utils/qt_ui_utils.h"
18 #include "main_application.h"
21 #include <QPushButton>
22 #include <QPlainTextEdit>
24 class CaptureCommentTabWidget
: public QTabWidget
28 CaptureCommentTabWidget(QWidget
*parent
= nullptr) : QTabWidget(parent
)
31 setTabsClosable(true);
33 connect(this, &QTabWidget::tabCloseRequested
, this, &CaptureCommentTabWidget::closeTab
);
34 connect(tabBar(), &QTabBar::tabMoved
, this, &CaptureCommentTabWidget::setTabTitles
);
36 int addTab(QWidget
*page
);
37 void tabRemoved(int index
) override
;
38 void closeTab(int index
);
39 void setReadOnly(bool ro
);
40 char** getCommentsText();
43 void setTabTitles(int from
, int to
);
46 int CaptureCommentTabWidget::addTab(QWidget
*page
)
48 return QTabWidget::addTab(page
, tr("Comment %1").arg(count() + 1));
51 void CaptureCommentTabWidget::closeTab(int index
)
54 te
= qobject_cast
<QPlainTextEdit
*>(widget(index
));
61 void CaptureCommentTabWidget::setReadOnly(bool ro
)
63 QPlainTextEdit
*commentTextEdit
;
64 for (int index
= 0; index
< count(); index
++) {
65 commentTextEdit
= qobject_cast
<QPlainTextEdit
*>(widget(index
));
66 if (commentTextEdit
!= nullptr) {
67 commentTextEdit
->setReadOnly(ro
);
72 void CaptureCommentTabWidget::tabRemoved(int index
)
74 setTabTitles(index
, count() - 1);
77 char** CaptureCommentTabWidget::getCommentsText()
79 /* glib 2.68 and later have g_strv_builder which is slightly
83 GPtrArray
*ptr_array
= g_ptr_array_new_full(count() + 1, g_free
);
84 for (int index
= 0; index
< count(); index
++) {
85 te
= qobject_cast
<QPlainTextEdit
*>(widget(index
));
87 char *str
= qstring_strdup(te
->toPlainText());
90 * Make sure this would fit in a pcapng option.
92 * XXX - 65535 is the maximum size for an option in pcapng;
93 * what if another capture file format supports larger
96 if (strlen(str
) > 65535) {
97 /* It doesn't fit. Give up. */
98 g_ptr_array_free(ptr_array
, true);
101 g_ptr_array_add(ptr_array
, str
);
104 g_ptr_array_add(ptr_array
, nullptr);
105 return (char**)g_ptr_array_free(ptr_array
, false);
108 void CaptureCommentTabWidget::setTabTitles(int from
, int to
)
111 for (; from
<= to
; from
++) {
112 this->setTabText(from
, tr("Comment %1").arg(from
+ 1));
115 for (; from
>= to
; from
--) {
116 this->setTabText(from
, tr("Comment %1").arg(from
+ 1));
121 CaptureCommentDialog::CaptureCommentDialog(QWidget
&parent
, CaptureFile
&capture_file
) :
122 WiresharkDialog(parent
, capture_file
),
123 ui(new Ui::CaptureCommentDialog
)
128 setWindowSubtitle(tr("Edit Capture Comments"));
130 ui
->sectionTabWidget
->setTabBarAutoHide(true);
131 this->actionAddButton
= ui
->buttonBox
->addButton(tr("Add Comment"), QDialogButtonBox::ActionRole
);
132 connect(this->actionAddButton
, &QPushButton::clicked
, this, &CaptureCommentDialog::addComment
);
134 connect(this, &CaptureCommentDialog::captureCommentChanged
, mainApp
->mainWindow(), &MainWindow::updateForUnsavedChanges
);
135 QTimer::singleShot(0, this, &CaptureCommentDialog::updateWidgets
);
138 CaptureCommentDialog::~CaptureCommentDialog()
143 void CaptureCommentDialog::addComment()
145 QPlainTextEdit
*commentTextEdit
;
146 CaptureCommentTabWidget
*currentTW
= qobject_cast
<CaptureCommentTabWidget
*>(ui
->sectionTabWidget
->currentWidget());
147 if (currentTW
!= nullptr) {
148 commentTextEdit
= new QPlainTextEdit(currentTW
);
150 currentTW
->addTab(commentTextEdit
);
154 void CaptureCommentDialog::updateWidgets()
156 QPlainTextEdit
*commentTextEdit
;
157 CaptureCommentTabWidget
*shbTW
;
158 QPushButton
*save_bt
= ui
->buttonBox
->button(QDialogButtonBox::Save
);
160 if (file_closed_
|| !cap_file_
.isValid()) {
161 for (int shb
= 0; shb
< ui
->sectionTabWidget
->count(); shb
++) {
162 shbTW
= qobject_cast
<CaptureCommentTabWidget
*>(ui
->sectionTabWidget
->widget(shb
));
163 shbTW
->setReadOnly(true);
166 save_bt
->setEnabled(false);
168 actionAddButton
->setEnabled(false);
169 WiresharkDialog::updateWidgets();
173 bool enable
= wtap_dump_can_write(cap_file_
.capFile()->linktypes
, WTAP_COMMENT_PER_SECTION
);
174 save_bt
->setEnabled(enable
);
175 actionAddButton
->setEnabled(enable
);
177 unsigned num_shbs
= wtap_file_get_num_shbs(cap_file_
.capFile()->provider
.wth
);
178 for (unsigned shb_idx
= 0; shb_idx
< num_shbs
; shb_idx
++) {
179 shbTW
= qobject_cast
<CaptureCommentTabWidget
*>(ui
->sectionTabWidget
->widget(shb_idx
));
180 if (shbTW
== nullptr) {
181 shbTW
= new CaptureCommentTabWidget(ui
->sectionTabWidget
);
182 ui
->sectionTabWidget
->addTab(shbTW
, tr("Section %1").arg(shb_idx
+ 1));
184 wtap_block_t shb
= wtap_file_get_shb(cap_file_
.capFile()->provider
.wth
, shb_idx
);
185 unsigned num_comments
= wtap_block_count_option(shb
, OPT_COMMENT
);
187 for (unsigned index
= 0; index
< num_comments
; index
++) {
188 commentTextEdit
= qobject_cast
<QPlainTextEdit
*>(shbTW
->widget(index
));
189 if (commentTextEdit
== nullptr) {
190 commentTextEdit
= new QPlainTextEdit(shbTW
);
191 shbTW
->addTab(commentTextEdit
);
193 if (wtap_block_get_nth_string_option_value(shb
, OPT_COMMENT
, index
,
194 &shb_comment
) == WTAP_OPTTYPE_SUCCESS
) {
195 commentTextEdit
->setPlainText(shb_comment
);
197 // XXX: Should we warn about this failure?
198 commentTextEdit
->setPlainText("");
200 commentTextEdit
->setReadOnly(!enable
);
202 for (unsigned index
= shbTW
->count(); index
> num_comments
; index
--) {
203 shbTW
->closeTab(index
- 1);
207 WiresharkDialog::updateWidgets();
210 void CaptureCommentDialog::on_buttonBox_helpRequested()
212 // mainApp->helpTopicAction(HELP_CAPTURE_COMMENT_DIALOG);
215 void CaptureCommentDialog::on_buttonBox_accepted()
217 int ret
= QDialog::Rejected
;
219 if (file_closed_
|| !cap_file_
.capFile()->filename
) {
224 if (wtap_dump_can_write(cap_file_
.capFile()->linktypes
, WTAP_COMMENT_PER_SECTION
))
226 CaptureCommentTabWidget
*current
;
227 char** comments_text
;
228 for (int shb_idx
= 0; shb_idx
< ui
->sectionTabWidget
->count(); shb_idx
++) {
229 current
= qobject_cast
<CaptureCommentTabWidget
*>(ui
->sectionTabWidget
->widget(shb_idx
));
230 comments_text
= current
->getCommentsText();
231 if (comments_text
== nullptr) {
232 /* This is the only error we track currently, so it must be
233 * this. Tell the user and give up. */
234 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
235 "A comment is too large to save in a capture file.");
239 cf_update_section_comments(cap_file_
.capFile(), shb_idx
, comments_text
);
240 emit
captureCommentChanged();
241 ret
= QDialog::Accepted
;
247 void CaptureCommentDialog::on_buttonBox_rejected()
252 #include "capture_comment_dialog.moc"