1 /* capture_file_properties_dialog.cpp
2 *
3 * GSoC 2013 - QtShark
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "capture_file_properties_dialog.h"
13 #include <ui_capture_file_properties_dialog.h>
14
15 #include "ui/summary.h"
16
17 #include "wsutil/str_util.h"
18 #include "wsutil/utf8_entities.h"
19 #include "ui/version_info.h"
20
21 #include <ui/qt/utils/qt_ui_utils.h>
22 #include "wireshark_application.h"
23
24 #include <QPushButton>
25 #include <QScrollBar>
26 #include <QTextStream>
27
28 // To do:
29 // - Add file hashes
30 // - Add formats (HTML, plain text, YAML)?
31
CaptureFilePropertiesDialog(QWidget & parent,CaptureFile & capture_file)32 CaptureFilePropertiesDialog::CaptureFilePropertiesDialog(QWidget &parent, CaptureFile &capture_file) :
33 WiresharkDialog(parent, capture_file),
34 ui(new Ui::CaptureFilePropertiesDialog)
35 {
36 ui->setupUi(this);
37 loadGeometry(parent.width() * 2 / 3, parent.height());
38
39 ui->detailsTextEdit->setAcceptRichText(true);
40
41 // make the details box larger than the comments
42 ui->splitter->setStretchFactor(0, 6);
43 ui->splitter->setStretchFactor(1, 1);
44
45 QPushButton *button = ui->buttonBox->button(QDialogButtonBox::Reset);
46 if (button) {
47 button->setText(tr("Refresh"));
48 }
49
50 button = ui->buttonBox->button(QDialogButtonBox::Apply);
51 if (button) {
52 button->setText(tr("Copy To Clipboard"));
53 }
54
55 button = ui->buttonBox->button(QDialogButtonBox::Save);
56 if (button) {
57 button->setText(tr("Save Comments"));
58 }
59
60 button = ui->buttonBox->button(QDialogButtonBox::Close);
61 if (button) {
62 button->setDefault(true);
63 }
64
65 setWindowSubtitle(tr("Capture File Properties"));
66 QTimer::singleShot(0, this, SLOT(updateWidgets()));
67 }
68
69 /*
70 * Slots
71 */
72
~CaptureFilePropertiesDialog()73 CaptureFilePropertiesDialog::~CaptureFilePropertiesDialog()
74 {
75 delete ui;
76 }
77
78 /**/
79
updateWidgets()80 void CaptureFilePropertiesDialog::updateWidgets()
81 {
82 QPushButton *refresh_bt = ui->buttonBox->button(QDialogButtonBox::Reset);
83 QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
84
85 if (file_closed_ || !cap_file_.isValid()) {
86 if (refresh_bt) {
87 refresh_bt->setEnabled(false);
88 }
89 ui->commentsTextEdit->setReadOnly(true);
90 if (save_bt) {
91 save_bt->setEnabled(false);
92 }
93 WiresharkDialog::updateWidgets();
94 return;
95 }
96
97 bool enable = wtap_dump_can_write(cap_file_.capFile()->linktypes, WTAP_COMMENT_PER_SECTION);
98 save_bt->setEnabled(enable);
99 ui->commentsTextEdit->setEnabled(enable);
100
101 fillDetails();
102 // XXX - this just handles the first comment in the first section;
103 // add support for multiple sections with multiple comments.
104 wtap_block_t shb = wtap_file_get_shb(cap_file_.capFile()->provider.wth, 0);
105 char *shb_comment;
106 if (wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, 0,
107 &shb_comment) == WTAP_OPTTYPE_SUCCESS)
108 ui->commentsTextEdit->setText(shb_comment);
109 else
110 ui->commentsTextEdit->setText(NULL);
111
112 WiresharkDialog::updateWidgets();
113 }
114
115 static const QString section_tmpl_ = "<p><strong>%1</strong></p>\n";
116 static const QString para_tmpl_ = "<p>%1</p>\n";
117
summaryToHtml()118 QString CaptureFilePropertiesDialog::summaryToHtml()
119 {
120 summary_tally summary;
121 double seconds = 0.0;
122 double disp_seconds = 0.0;
123 double marked_seconds = 0.0;
124
125 memset(&summary, 0, sizeof(summary_tally));
126
127 QString table_begin, table_end;
128 QString table_row_begin, table_ul_row_begin, table_row_end;
129 QString table_vheader_tmpl, table_hheader20_tmpl, table_hheader25_tmpl;
130 QString table_data_tmpl;
131
132 table_begin = "<p><table>\n";
133 table_end = "</table></p>\n";
134 table_row_begin = "<tr>\n";
135 table_ul_row_begin = "<tr style=\"border-bottom: 1px solid gray;\">\n";
136 table_row_end = "</tr>\n";
137 table_vheader_tmpl = "<td width=\"20%\">%1:</td>"; // <th align="left"> looked odd
138 table_hheader20_tmpl = "<td width=\"20%\"><u>%1</u></td>";
139 table_hheader25_tmpl = "<td width=\"25%\"><u>%1</u></td>";
140 table_data_tmpl = "<td>%1</td>";
141
142 if (!file_closed_) {
143 /* initial computations */
144 summary_fill_in(cap_file_.capFile(), &summary);
145 #ifdef HAVE_LIBPCAP
146 summary_fill_in_capture(cap_file_.capFile(), &global_capture_opts, &summary);
147 #endif
148 }
149
150 seconds = summary.stop_time - summary.start_time;
151 disp_seconds = summary.filtered_stop - summary.filtered_start;
152 marked_seconds = summary.marked_stop - summary.marked_start;
153
154 QString summary_str;
155 QTextStream out(&summary_str);
156 QString unknown = tr("Unknown");
157
158 // File Section
159 out << section_tmpl_.arg(tr("File"));
160 out << table_begin;
161
162 out << table_row_begin
163 << table_vheader_tmpl.arg(tr("Name"))
164 << table_data_tmpl.arg(summary.filename)
165 << table_row_end;
166
167 out << table_row_begin
168 << table_vheader_tmpl.arg(tr("Length"))
169 << table_data_tmpl.arg(file_size_to_qstring(summary.file_length))
170 << table_row_end;
171
172 out << table_row_begin
173 << table_vheader_tmpl.arg(tr("Hash (SHA256)"))
174 << table_data_tmpl.arg(summary.file_sha256)
175 << table_row_end;
176
177 out << table_row_begin
178 << table_vheader_tmpl.arg(tr("Hash (RIPEMD160)"))
179 << table_data_tmpl.arg(summary.file_rmd160)
180 << table_row_end;
181
182 out << table_row_begin
183 << table_vheader_tmpl.arg(tr("Hash (SHA1)"))
184 << table_data_tmpl.arg(summary.file_sha1)
185 << table_row_end;
186
187 QString format_str = wtap_file_type_subtype_description(summary.file_type);
188 const char *compression_type_description = wtap_compression_type_description(summary.compression_type);
189 if (compression_type_description != nullptr) {
190 format_str += QString(" (%1)").arg(compression_type_description);
191 }
192 out << table_row_begin
193 << table_vheader_tmpl.arg(tr("Format"))
194 << table_data_tmpl.arg(format_str)
195 << table_row_end;
196
197 QString encaps_str;
198 if (summary.file_encap_type == WTAP_ENCAP_PER_PACKET) {
199 for (guint i = 0; i < summary.packet_encap_types->len; i++)
200 {
201 encaps_str = QString(wtap_encap_description(g_array_index(summary.packet_encap_types, int, i)));
202 }
203 } else {
204 encaps_str = QString(wtap_encap_description(summary.file_encap_type));
205 }
206 out << table_row_begin
207 << table_vheader_tmpl.arg(tr("Encapsulation"))
208 << table_data_tmpl.arg(encaps_str)
209 << table_row_end;
210
211 if (summary.snap != 0) {
212 out << table_row_begin
213 << table_vheader_tmpl.arg(tr("Snapshot length"))
214 << table_data_tmpl.arg(summary.snap)
215 << table_row_end;
216 }
217
218 out << table_end;
219
220 // Time Section
221 if (summary.packet_count_ts == summary.packet_count &&
222 summary.packet_count >= 1)
223 {
224 out << section_tmpl_.arg(tr("Time"));
225 out << table_begin;
226
227 // start time
228 out << table_row_begin
229 << table_vheader_tmpl.arg(tr("First packet"))
230 << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.start_time))
231 << table_row_end;
232
233 // stop time
234 out << table_row_begin
235 << table_vheader_tmpl.arg(tr("Last packet"))
236 << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.stop_time))
237 << table_row_end;
238
239 // elapsed seconds (capture duration)
240 if (summary.packet_count_ts >= 2)
241 {
242 /* elapsed seconds */
243 QString elapsed_str;
244 unsigned int elapsed_time = (unsigned int)summary.elapsed_time;
245 if (elapsed_time/86400)
246 {
247 elapsed_str = QString("%1 days ").arg(elapsed_time / 86400);
248 }
249
250 elapsed_str += QString("%1:%2:%3")
251 .arg(elapsed_time % 86400 / 3600, 2, 10, QChar('0'))
252 .arg(elapsed_time % 3600 / 60, 2, 10, QChar('0'))
253 .arg(elapsed_time % 60, 2, 10, QChar('0'));
254 out << table_row_begin
255 << table_vheader_tmpl.arg(tr("Elapsed"))
256 << table_data_tmpl.arg(elapsed_str)
257 << table_row_end;
258 }
259
260 out << table_end;
261 }
262
263 // Information from file sections.
264 for (guint section_number = 0;
265 section_number < wtap_file_get_num_shbs(cap_file_.capFile()->provider.wth);
266 section_number++) {
267
268 // If we have more than one section, add headers for each section.
269 if (wtap_file_get_num_shbs(cap_file_.capFile()->provider.wth) > 1)
270 out << section_tmpl_.arg(QString(tr("Section %1"))
271 .arg(section_number));
272
273 // Capture Section
274 out << section_tmpl_.arg(tr("Capture"));
275 out << table_begin;
276
277 wtap_block_t shb_inf = wtap_file_get_shb(cap_file_.capFile()->provider.wth, section_number);
278 char *str;
279
280 if (shb_inf != nullptr) {
281 QString capture_hardware(unknown);
282 if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) {
283 if (str[0] != '\0') {
284 capture_hardware = str;
285 }
286 }
287 // capture HW
288 out << table_row_begin
289 << table_vheader_tmpl.arg(tr("Hardware"))
290 << table_data_tmpl.arg(capture_hardware)
291 << table_row_end;
292
293 QString capture_os(unknown);
294 if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) {
295 if (str[0] != '\0') {
296 capture_os = str;
297 }
298 }
299 out << table_row_begin
300 << table_vheader_tmpl.arg(tr("OS"))
301 << table_data_tmpl.arg(capture_os)
302 << table_row_end;
303
304 QString capture_app(unknown);
305 if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) {
306 if (str[0] != '\0') {
307 capture_app = str;
308 }
309 }
310 out << table_row_begin
311 << table_vheader_tmpl.arg(tr("Application"))
312 << table_data_tmpl.arg(capture_app)
313 << table_row_end;
314 }
315
316 out << table_end;
317
318 // capture interfaces info
319 if (summary.ifaces->len > 0) {
320 out << section_tmpl_.arg(tr("Interfaces"));
321 out << table_begin;
322
323 out << table_ul_row_begin
324 << table_hheader20_tmpl.arg(tr("Interface"))
325 << table_hheader20_tmpl.arg(tr("Dropped packets"))
326 << table_hheader20_tmpl.arg(tr("Capture filter"))
327 << table_hheader20_tmpl.arg(tr("Link type"))
328 << table_hheader20_tmpl.arg(tr("Packet size limit (snaplen)"))
329 << table_row_end;
330 }
331
332 for (guint i = 0; i < summary.ifaces->len; i++) {
333 iface_summary_info iface;
334 iface = g_array_index(summary.ifaces, iface_summary_info, i);
335
336 /* interface */
337 QString interface_name(unknown);
338 if (iface.descr) {
339 interface_name = iface.descr;
340 } else if (iface.name) {
341 interface_name = iface.name;
342 }
343
344 /* Dropped count */
345 QString interface_drops(unknown);
346 if (iface.drops_known) {
347 interface_drops = QString("%1 (%2%)").arg(iface.drops).arg(QString::number(
348 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
349 summary.packet_count ? (100.0 * (gint64)iface.drops)/summary.packet_count : 0, 'f', 1));
350 }
351
352 /* Capture filter */
353 QString interface_cfilter(unknown);
354 if (iface.cfilter && iface.cfilter[0] != '\0') {
355 interface_cfilter = iface.cfilter;
356 } else if (iface.name) {
357 interface_cfilter = QString(tr("none"));
358 }
359
360 QString interface_snaplen = QString(tr("%1 bytes").arg(iface.snap));
361
362 out << table_row_begin
363 << table_data_tmpl.arg(interface_name)
364 << table_data_tmpl.arg(interface_drops)
365 << table_data_tmpl.arg(interface_cfilter)
366 << table_data_tmpl.arg(wtap_encap_description(iface.encap_type))
367 << table_data_tmpl.arg(interface_snaplen)
368 << table_row_end;
369 }
370 if (summary.ifaces->len > 0) {
371 out << table_end;
372 }
373 }
374
375 // Statistics Section
376 out << section_tmpl_.arg(tr("Statistics"));
377 out << table_begin;
378
379 out << table_ul_row_begin
380 << table_hheader25_tmpl.arg(tr("Measurement"))
381 << table_hheader25_tmpl.arg(tr("Captured"))
382 << table_hheader25_tmpl.arg(tr("Displayed"))
383 << table_hheader25_tmpl.arg(tr("Marked"))
384 << table_row_end;
385
386 QString n_a = UTF8_EM_DASH;
387 QString captured_str, displayed_str, marked_str;
388
389 // Packets
390 displayed_str = marked_str = n_a;
391 if (summary.filtered_count > 0 && summary.packet_count > 0) {
392 displayed_str = QString("%1 (%2%)")
393 .arg(summary.filtered_count)
394 .arg(100.0 * summary.filtered_count / summary.packet_count, 1, 'f', 1);
395 }
396 if (summary.packet_count > 0 && summary.marked_count > 0) {
397 marked_str = QString("%1 (%2%)")
398 .arg(summary.marked_count)
399 .arg(100.0 * summary.marked_count / summary.packet_count, 1, 'f', 1);
400 }
401
402 out << table_row_begin
403 << table_data_tmpl.arg(tr("Packets"))
404 << table_data_tmpl.arg(summary.packet_count)
405 << table_data_tmpl.arg(displayed_str)
406 << table_data_tmpl.arg(marked_str)
407 << table_row_end;
408
409 // Time between first and last
410 captured_str = displayed_str = marked_str = n_a;
411 if (seconds > 0) {
412 captured_str = QString("%1").arg(seconds, 1, 'f', 3);
413 }
414 if (disp_seconds > 0) {
415 displayed_str = QString("%1").arg(disp_seconds, 1, 'f', 3);
416 }
417 if (marked_seconds > 0) {
418 marked_str = QString("%1").arg(marked_seconds, 1, 'f', 3);
419 }
420 out << table_row_begin
421 << table_data_tmpl.arg(tr("Time span, s"))
422 << table_data_tmpl.arg(captured_str)
423 << table_data_tmpl.arg(displayed_str)
424 << table_data_tmpl.arg(marked_str)
425 << table_row_end;
426
427 // Average packets per second
428 captured_str = displayed_str = marked_str = n_a;
429 if (seconds > 0) {
430 captured_str = QString("%1").arg(summary.packet_count/seconds, 1, 'f', 1);
431 }
432 if (disp_seconds > 0) {
433 displayed_str = QString("%1").arg(summary.filtered_count/disp_seconds, 1, 'f', 1);
434 }
435 if (marked_seconds > 0) {
436 marked_str = QString("%1").arg(summary.marked_count/marked_seconds, 1, 'f', 1);
437 }
438 out << table_row_begin
439 << table_data_tmpl.arg(tr("Average pps"))
440 << table_data_tmpl.arg(captured_str)
441 << table_data_tmpl.arg(displayed_str)
442 << table_data_tmpl.arg(marked_str)
443 << table_row_end;
444
445 // Average packet size
446 captured_str = displayed_str = marked_str = n_a;
447 if (summary.packet_count > 0) {
448 captured_str = QString::number((guint64) ((double)summary.bytes/summary.packet_count + 0.5));
449 }
450 if (summary.filtered_count > 0) {
451 displayed_str = QString::number((guint64) ((double)summary.filtered_bytes/summary.filtered_count + 0.5));
452 }
453 if (summary.marked_count > 0) {
454 marked_str = QString::number((guint64) ((double)summary.marked_bytes/summary.marked_count + 0.5));
455 }
456 out << table_row_begin
457 << table_data_tmpl.arg(tr("Average packet size, B"))
458 << table_data_tmpl.arg(captured_str)
459 << table_data_tmpl.arg(displayed_str)
460 << table_data_tmpl.arg(marked_str)
461 << table_row_end;
462
463 // Byte count
464 displayed_str = marked_str = "0";
465 if (summary.bytes > 0 && summary.filtered_bytes > 0) {
466 displayed_str = QString("%1 (%2%)")
467 .arg(summary.filtered_bytes)
468 .arg(100.0 * summary.filtered_bytes / summary.bytes, 1, 'f', 1);
469 }
470 if (summary.bytes > 0 && summary.marked_bytes > 0) {
471 marked_str = QString("%1 (%2%)")
472 .arg(summary.marked_bytes)
473 .arg(100.0 * summary.marked_bytes / summary.bytes, 1, 'f', 1);
474 }
475 out << table_row_begin
476 << table_data_tmpl.arg(tr("Bytes"))
477 << table_data_tmpl.arg(summary.bytes)
478 << table_data_tmpl.arg(displayed_str)
479 << table_data_tmpl.arg(marked_str)
480 << table_row_end;
481
482 // Bytes per second
483 captured_str = displayed_str = marked_str = n_a;
484 if (seconds > 0) {
485 captured_str =
486 gchar_free_to_qstring(format_size(summary.bytes / seconds, format_size_unit_none|format_size_prefix_si));
487 }
488 if (disp_seconds > 0) {
489 displayed_str =
490 gchar_free_to_qstring(format_size(summary.filtered_bytes / disp_seconds, format_size_unit_none|format_size_prefix_si));
491 }
492 if (marked_seconds > 0) {
493 marked_str =
494 gchar_free_to_qstring(format_size(summary.marked_bytes / marked_seconds, format_size_unit_none|format_size_prefix_si));
495 }
496 out << table_row_begin
497 << table_data_tmpl.arg(tr("Average bytes/s"))
498 << table_data_tmpl.arg(captured_str)
499 << table_data_tmpl.arg(displayed_str)
500 << table_data_tmpl.arg(marked_str)
501 << table_row_end;
502
503 // Bits per second
504 captured_str = displayed_str = marked_str = n_a;
505 if (seconds > 0) {
506 captured_str =
507 gchar_free_to_qstring(format_size(summary.bytes * 8 / seconds, format_size_unit_none|format_size_prefix_si));
508 }
509 if (disp_seconds > 0) {
510 displayed_str =
511 gchar_free_to_qstring(format_size(summary.filtered_bytes * 8 / disp_seconds, format_size_unit_none|format_size_prefix_si));
512 }
513 if (marked_seconds > 0) {
514 marked_str =
515 gchar_free_to_qstring(format_size(summary.marked_bytes * 8 / marked_seconds, format_size_unit_none|format_size_prefix_si));
516 }
517 out << table_row_begin
518 << table_data_tmpl.arg(tr("Average bits/s"))
519 << table_data_tmpl.arg(captured_str)
520 << table_data_tmpl.arg(displayed_str)
521 << table_data_tmpl.arg(marked_str)
522 << table_row_end;
523
524 out << table_end;
525
526 return summary_str;
527 }
528
fillDetails()529 void CaptureFilePropertiesDialog::fillDetails()
530 {
531 if (!cap_file_.isValid()) return;
532
533 ui->detailsTextEdit->clear();
534
535 QTextCursor cursor = ui->detailsTextEdit->textCursor();
536 QString summary = summaryToHtml();
537 cursor.insertHtml(summary);
538 cursor.insertBlock(); // Work around rendering oddity.
539
540 // XXX - this just shows the first comment in the first section;
541 // add support for multiple sections with multiple comments.
542 wtap_block_t shb = wtap_file_get_shb(cap_file_.capFile()->provider.wth, 0);
543 char *shb_comment;
544 if (wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, 0,
545 &shb_comment) == WTAP_OPTTYPE_SUCCESS) {
546 QString section_comment = shb_comment;
547 QString section_comment_html;
548
549 if (!section_comment.isEmpty()) {
550 QString comment_escaped = html_escape(section_comment).replace('\n', "<br>");
551 section_comment_html += section_tmpl_.arg(QString(tr("Section Comment")));
552 section_comment_html += para_tmpl_.arg(comment_escaped);
553
554 cursor.insertBlock();
555 cursor.insertHtml(section_comment_html);
556 }
557 }
558
559 if (cap_file_.capFile()->packet_comment_count > 0) {
560 cursor.insertBlock();
561 cursor.insertHtml(section_tmpl_.arg(tr("Packet Comments")));
562
563 for (guint32 framenum = 1; framenum <= cap_file_.capFile()->count ; framenum++) {
564 frame_data *fdata = frame_data_sequence_find(cap_file_.capFile()->provider.frames, framenum);
565 wtap_block_t pkt_block = cf_get_packet_block(cap_file_.capFile(), fdata);
566
567 if (pkt_block) {
568 guint n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT);
569 for (guint i = 0; i < n_comments; i++) {
570 char *comment_text;
571 if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, i, &comment_text)) {
572 QString frame_comment_html = tr("<p>Frame %1: ").arg(framenum);
573 QString raw_comment = comment_text;
574
575 frame_comment_html += html_escape(raw_comment).replace('\n', "<br>");
576 frame_comment_html += "</p>\n";
577 cursor.insertBlock();
578 cursor.insertHtml(frame_comment_html);
579 }
580 }
581 }
582 wtap_block_unref(pkt_block);
583 }
584 }
585 ui->detailsTextEdit->verticalScrollBar()->setValue(0);
586 }
587
changeEvent(QEvent * event)588 void CaptureFilePropertiesDialog::changeEvent(QEvent* event)
589 {
590 if (event != nullptr)
591 {
592 switch (event->type())
593 {
594 case QEvent::LanguageChange:
595 ui->retranslateUi(this);
596 updateWidgets();
597 break;
598 default:
599 break;
600 }
601 }
602 QDialog::changeEvent(event);
603 }
604
on_buttonBox_helpRequested()605 void CaptureFilePropertiesDialog::on_buttonBox_helpRequested()
606 {
607 wsApp->helpTopicAction(HELP_STATS_SUMMARY_DIALOG);
608 }
609
on_buttonBox_accepted()610 void CaptureFilePropertiesDialog::on_buttonBox_accepted()
611 {
612 if (file_closed_ || !cap_file_.capFile()->filename) {
613 return;
614 }
615
616 if (wtap_dump_can_write(cap_file_.capFile()->linktypes, WTAP_COMMENT_PER_SECTION))
617 {
618 gchar *str = qstring_strdup(ui->commentsTextEdit->toPlainText());
619 cf_update_section_comment(cap_file_.capFile(), str);
620 emit captureCommentChanged();
621 fillDetails();
622 }
623 }
624
on_buttonBox_clicked(QAbstractButton * button)625 void CaptureFilePropertiesDialog::on_buttonBox_clicked(QAbstractButton *button)
626 {
627 if (button == ui->buttonBox->button(QDialogButtonBox::Apply)) {
628 QClipboard *clipboard = QApplication::clipboard();
629 QString details = tr("Created by Wireshark %1\n\n").arg(get_ws_vcs_version_info());
630 details.append(ui->detailsTextEdit->toPlainText());
631 clipboard->setText(details);
632 } else if (button == ui->buttonBox->button(QDialogButtonBox::Reset)) {
633 updateWidgets();
634 }
635 }
636
on_buttonBox_rejected()637 void CaptureFilePropertiesDialog::on_buttonBox_rejected()
638 {
639 reject();
640 }
641