Qt: Enable JSON no duplicate keys options from the GUI

Enable access to the JSON "no-duplicate-keys" option available in
tshark in the GUI as well. Continue to default to it off, same as
in tshark.

As part of this, have the Export Dissections dialog packet format
group box be a stacked widget, allowing different per format
options. Note the current options are only valid for text (and
PostScript, but Export Dissections doesn't do that.) This could allow
support for CSV options, e.g. see #14260.

Have the different format group boxes be responsible for checking
validity and setting the print arguments, to reduce duplicate code
between Export Dissections and Print, and keep those widgets from
having to understand details of the group boxes.

Note that the current "no duplicate keys" format has limitations of
its own, because it doesn't preserve order in cases where there
are multiple siblings of the same field at the same tree level but
not consecutive (i.e., with other fields between them.) They will
be placed together. A different strategy, that involves even more
use of arrays, would be necessary to preserve order. (See also
issue #12958.)

Ping #13904, #19295, #19329
This commit is contained in:
John Thacker 2025-03-01 20:27:46 -05:00 committed by AndersBroman
parent e50432f8bf
commit 070a394402
15 changed files with 335 additions and 93 deletions

View File

@ -159,6 +159,11 @@ The following features are either new or have been significantly updated since v
text with aligned columns along with an ability to select a copy format to be text with aligned columns along with an ability to select a copy format to be
used when copied via keyboard shortcut. used when copied via keyboard shortcut.
* The "no duplicate keys" version of JSON output that tshark has supported
since 2.6.0 is available through the GUI Export Dissections Dialog.
Note that this format does not necessarily preserve the ordering of all
children in a tree, if sibling with identical keys are not consecutive.
=== Removed Features and Support === Removed Features and Support
Wireshark no longer supports AirPcap and WinPcap. Wireshark no longer supports AirPcap and WinPcap.

5
file.c
View File

@ -3100,7 +3100,10 @@ write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
/* Write out the information in that tree. */ /* Write out the information in that tree. */
write_json_proto_tree(NULL, args->print_args->print_dissections, write_json_proto_tree(NULL, args->print_args->print_dissections,
args->print_args->print_hex, args->print_args->print_hex,
&args->edt, &cf->cinfo, proto_node_group_children_by_unique, &args->edt, &cf->cinfo,
args->print_args->no_duplicate_keys ?
proto_node_group_children_by_json_key :
proto_node_group_children_by_unique,
&args->jdumper); &args->jdumper);
epan_dissect_reset(&args->edt); epan_dissect_reset(&args->edt);

3
file.h
View File

@ -448,6 +448,9 @@ typedef struct {
unsigned hexdump_options; /* Hexdump options if print_hex is true. */ unsigned hexdump_options; /* Hexdump options if print_hex is true. */
bool print_formfeed; /* true if a formfeed should be printed before bool print_formfeed; /* true if a formfeed should be printed before
* each new packet */ * each new packet */
/* JSON related option */
bool no_duplicate_keys;
} print_args_t; } print_args_t;
/** /**

View File

@ -219,6 +219,7 @@ set(WIRESHARK_QT_HEADERS
packet_diagram.h packet_diagram.h
packet_dialog.h packet_dialog.h
packet_format_group_box.h packet_format_group_box.h
packet_format_stack.h
packet_list.h packet_list.h
packet_range_group_box.h packet_range_group_box.h
preference_editor_frame.h preference_editor_frame.h
@ -478,6 +479,7 @@ set(WIRESHARK_QT_SRC
packet_diagram.cpp packet_diagram.cpp
packet_dialog.cpp packet_dialog.cpp
packet_format_group_box.cpp packet_format_group_box.cpp
packet_format_stack.cpp
packet_list.cpp packet_list.cpp
packet_range_group_box.cpp packet_range_group_box.cpp
preference_editor_frame.cpp preference_editor_frame.cpp
@ -625,6 +627,7 @@ set(WIRESHARK_QT_UI
packet_comment_dialog.ui packet_comment_dialog.ui
packet_dialog.ui packet_dialog.ui
packet_format_group_box.ui packet_format_group_box.ui
packet_format_json_group_box.ui
packet_range_group_box.ui packet_range_group_box.ui
preference_editor_frame.ui preference_editor_frame.ui
preferences_dialog.ui preferences_dialog.ui

View File

@ -18,7 +18,7 @@
#include <ui/qt/utils/qt_ui_utils.h> #include <ui/qt/utils/qt_ui_utils.h>
#include <QStackedWidget>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QGridLayout> #include <QGridLayout>
#include <QPushButton> #include <QPushButton>
@ -55,6 +55,8 @@ ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *ca
setAcceptMode(QFileDialog::AcceptSave); setAcceptMode(QFileDialog::AcceptSave);
setLabelText(FileType, tr("Export As:")); setLabelText(FileType, tr("Export As:"));
packet_format_stack_ = new PacketFormatStack(this);
// export_type_map_keys() sorts alphabetically. We don't want that. // export_type_map_keys() sorts alphabetically. We don't want that.
name_filters name_filters
<< tr("Plain text (*.txt)") << tr("Plain text (*.txt)")
@ -84,9 +86,10 @@ ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *ca
print_args_.range.process_filtered = true; print_args_.range.process_filtered = true;
packet_range_group_box_.initRange(&print_args_.range, selRange); packet_range_group_box_.initRange(&print_args_.range, selRange);
h_box->addWidget(&packet_range_group_box_); h_box->addWidget(&packet_range_group_box_);
h_box->addWidget(&packet_format_group_box_, 0, Qt::AlignTop); h_box->addWidget(packet_format_stack_, 0, Qt::AlignTop);
if (button_box) { if (button_box) {
button_box->addButton(QDialogButtonBox::Help); button_box->addButton(QDialogButtonBox::Help);
@ -98,7 +101,7 @@ ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *ca
if (save_bt_) { if (save_bt_) {
connect(&packet_range_group_box_, &PacketRangeGroupBox::validityChanged, connect(&packet_range_group_box_, &PacketRangeGroupBox::validityChanged,
this, &ExportDissectionDialog::checkValidity); this, &ExportDissectionDialog::checkValidity);
connect(&packet_format_group_box_, &PacketFormatGroupBox::formatChanged, connect(packet_format_stack_, &PacketFormatStack::formatChanged,
this, &ExportDissectionDialog::checkValidity); this, &ExportDissectionDialog::checkValidity);
save_bt_->installEventFilter(this); save_bt_->installEventFilter(this);
} }
@ -146,22 +149,12 @@ void ExportDissectionDialog::dialogAccepted(const QStringList &selected)
print_args_.print_dissections = print_dissections_as_displayed; print_args_.print_dissections = print_dissections_as_displayed;
print_args_.print_hex = false; print_args_.print_hex = false;
print_args_.print_formfeed = false; print_args_.print_formfeed = false;
print_args_.no_duplicate_keys = false;
packet_format_stack_->updatePrintArgs(print_args_);
switch (export_type_) { switch (export_type_) {
case export_type_text: /* Text */ case export_type_text: /* Text */
print_args_.print_summary = packet_format_group_box_.summaryEnabled();
print_args_.print_col_headings = packet_format_group_box_.includeColumnHeadingsEnabled();
print_args_.print_dissections = print_dissections_none;
if (packet_format_group_box_.detailsEnabled()) {
if (packet_format_group_box_.allCollapsedEnabled())
print_args_.print_dissections = print_dissections_collapsed;
else if (packet_format_group_box_.asDisplayedEnabled())
print_args_.print_dissections = print_dissections_as_displayed;
else if (packet_format_group_box_.allExpandedEnabled())
print_args_.print_dissections = print_dissections_expanded;
}
print_args_.print_hex = packet_format_group_box_.bytesEnabled();
print_args_.hexdump_options = packet_format_group_box_.getHexdumpOptions();
print_args_.stream = print_stream_text_new(true, print_args_.file); print_args_.stream = print_stream_text_new(true, print_args_.file);
if (print_args_.stream == NULL) { if (print_args_.stream == NULL) {
open_failure_alert_box(print_args_.file, errno, true); open_failure_alert_box(print_args_.file, errno, true);
@ -209,12 +202,7 @@ void ExportDissectionDialog::dialogAccepted(const QStringList &selected)
void ExportDissectionDialog::exportTypeChanged(QString name_filter) void ExportDissectionDialog::exportTypeChanged(QString name_filter)
{ {
export_type_ = export_type_map_.value(name_filter); export_type_ = export_type_map_.value(name_filter);
if (export_type_ == export_type_text) { packet_format_stack_->setExportType(export_type_);
packet_format_group_box_.setEnabled(true);
print_args_.format = PR_FMT_TEXT;
} else {
packet_format_group_box_.setEnabled(false);
}
checkValidity(); checkValidity();
setDefaultSuffix(export_extensions[export_type_]); setDefaultSuffix(export_extensions[export_type_]);
@ -226,14 +214,7 @@ bool ExportDissectionDialog::isValid()
if (!packet_range_group_box_.isValid()) valid = false; if (!packet_range_group_box_.isValid()) valid = false;
if (export_type_ == export_type_text) { if (!packet_format_stack_->isValid()) valid = false;
if (! packet_format_group_box_.summaryEnabled() &&
! packet_format_group_box_.detailsEnabled() &&
! packet_format_group_box_.bytesEnabled())
{
valid = false;
}
}
return valid; return valid;
} }

View File

@ -19,7 +19,7 @@
#include <ui/qt/widgets/wireshark_file_dialog.h> #include <ui/qt/widgets/wireshark_file_dialog.h>
#include "packet_range_group_box.h" #include "packet_range_group_box.h"
#include "packet_format_group_box.h" #include "packet_format_stack.h"
#include <QMap> #include <QMap>
@ -51,7 +51,7 @@ private:
QMap<QString, export_type_e> export_type_map_; QMap<QString, export_type_e> export_type_map_;
PacketRangeGroupBox packet_range_group_box_; PacketRangeGroupBox packet_range_group_box_;
PacketFormatGroupBox packet_format_group_box_; PacketFormatStack *packet_format_stack_;
QPushButton *save_bt_; QPushButton *save_bt_;

View File

@ -9,18 +9,45 @@
#include "packet_format_group_box.h" #include "packet_format_group_box.h"
#include <ui_packet_format_group_box.h> #include <ui_packet_format_group_box.h>
#include <ui_packet_format_json_group_box.h>
#include <epan/print.h> #include <epan/print.h>
#include <QLabel>
#include <QStyle> #include <QStyle>
#include <QStyleOption> #include <QStyleOption>
PacketFormatGroupBox::PacketFormatGroupBox(QWidget *parent) : PacketFormatGroupBox::PacketFormatGroupBox(QWidget *parent) :
QGroupBox(parent), QGroupBox("Packet Format", parent)
pf_ui_(new Ui::PacketFormatGroupBox) {
setFlat(true);
}
bool PacketFormatGroupBox::isValid() const
{
return true;
}
PacketFormatBlankGroupBox::PacketFormatBlankGroupBox(QWidget *parent) :
PacketFormatGroupBox(parent)
{
QVBoxLayout *vbox = new QVBoxLayout;
QLabel *label = new QLabel((tr("The selected format has no options")));
label->setWordWrap(true);
vbox->addWidget(label);
vbox->addStretch(1);
setLayout(vbox);
}
void PacketFormatBlankGroupBox::updatePrintArgs(print_args_t&)
{
}
PacketFormatTextGroupBox::PacketFormatTextGroupBox(QWidget *parent) :
PacketFormatGroupBox(parent),
pf_ui_(new Ui::PacketFormatTextGroupBox)
{ {
pf_ui_->setupUi(this); pf_ui_->setupUi(this);
setFlat(true);
QStyleOption style_opt; QStyleOption style_opt;
int cb_label_offset = pf_ui_->detailsCheckBox->style()->subElementRect(QStyle::SE_CheckBoxContents, &style_opt).left(); int cb_label_offset = pf_ui_->detailsCheckBox->style()->subElementRect(QStyle::SE_CheckBoxContents, &style_opt).left();
@ -63,58 +90,85 @@ PacketFormatGroupBox::PacketFormatGroupBox(QWidget *parent) :
).arg(cb_label_offset)); ).arg(cb_label_offset));
} }
PacketFormatGroupBox::~PacketFormatGroupBox() PacketFormatTextGroupBox::~PacketFormatTextGroupBox()
{ {
delete pf_ui_; delete pf_ui_;
} }
bool PacketFormatGroupBox::summaryEnabled() bool PacketFormatTextGroupBox::summaryEnabled() const
{ {
return pf_ui_->summaryCheckBox->isChecked(); return pf_ui_->summaryCheckBox->isChecked();
} }
bool PacketFormatGroupBox::detailsEnabled() bool PacketFormatTextGroupBox::detailsEnabled() const
{ {
return pf_ui_->detailsCheckBox->isChecked(); return pf_ui_->detailsCheckBox->isChecked();
} }
bool PacketFormatGroupBox::bytesEnabled() bool PacketFormatTextGroupBox::bytesEnabled() const
{ {
return pf_ui_->bytesCheckBox->isChecked(); return pf_ui_->bytesCheckBox->isChecked();
} }
bool PacketFormatGroupBox::includeColumnHeadingsEnabled() bool PacketFormatTextGroupBox::includeColumnHeadingsEnabled() const
{ {
return pf_ui_->includeColumnHeadingsCheckBox->isChecked(); return pf_ui_->includeColumnHeadingsCheckBox->isChecked();
} }
bool PacketFormatGroupBox::allCollapsedEnabled() bool PacketFormatTextGroupBox::allCollapsedEnabled() const
{ {
return pf_ui_->allCollapsedButton->isChecked(); return pf_ui_->allCollapsedButton->isChecked();
} }
bool PacketFormatGroupBox::asDisplayedEnabled() bool PacketFormatTextGroupBox::asDisplayedEnabled() const
{ {
return pf_ui_->asDisplayedButton->isChecked(); return pf_ui_->asDisplayedButton->isChecked();
} }
bool PacketFormatGroupBox::allExpandedEnabled() bool PacketFormatTextGroupBox::allExpandedEnabled() const
{ {
return pf_ui_->allExpandedButton->isChecked(); return pf_ui_->allExpandedButton->isChecked();
} }
uint PacketFormatGroupBox::getHexdumpOptions() uint PacketFormatTextGroupBox::getHexdumpOptions() const
{ {
return (pf_ui_->includeDataSourcesCheckBox->isChecked() ? HEXDUMP_SOURCE_MULTI : HEXDUMP_SOURCE_PRIMARY) | (pf_ui_->timestampCheckBox->isChecked() ? HEXDUMP_TIMESTAMP : HEXDUMP_TIMESTAMP_NONE); return (pf_ui_->includeDataSourcesCheckBox->isChecked() ? HEXDUMP_SOURCE_MULTI : HEXDUMP_SOURCE_PRIMARY) | (pf_ui_->timestampCheckBox->isChecked() ? HEXDUMP_TIMESTAMP : HEXDUMP_TIMESTAMP_NONE);
} }
void PacketFormatGroupBox::on_summaryCheckBox_toggled(bool checked) bool PacketFormatTextGroupBox::isValid() const
{
if (!summaryEnabled() && !detailsEnabled() && !bytesEnabled()) {
return false;
}
return true;
}
void PacketFormatTextGroupBox::updatePrintArgs(print_args_t& print_args)
{
print_args.format = PR_FMT_TEXT;
print_args.print_summary = summaryEnabled();
print_args.print_col_headings = includeColumnHeadingsEnabled();
print_args.print_dissections = print_dissections_none;
if (detailsEnabled()) {
if (allCollapsedEnabled())
print_args.print_dissections = print_dissections_collapsed;
else if (asDisplayedEnabled())
print_args.print_dissections = print_dissections_as_displayed;
else if (allExpandedEnabled())
print_args.print_dissections = print_dissections_expanded;
}
print_args.print_hex = bytesEnabled();
print_args.hexdump_options = getHexdumpOptions();
}
void PacketFormatTextGroupBox::on_summaryCheckBox_toggled(bool checked)
{ {
pf_ui_->includeColumnHeadingsCheckBox->setEnabled(checked); pf_ui_->includeColumnHeadingsCheckBox->setEnabled(checked);
emit formatChanged(); emit formatChanged();
} }
void PacketFormatGroupBox::on_detailsCheckBox_toggled(bool checked) void PacketFormatTextGroupBox::on_detailsCheckBox_toggled(bool checked)
{ {
pf_ui_->allCollapsedButton->setEnabled(checked); pf_ui_->allCollapsedButton->setEnabled(checked);
pf_ui_->asDisplayedButton->setEnabled(checked); pf_ui_->asDisplayedButton->setEnabled(checked);
@ -122,39 +176,63 @@ void PacketFormatGroupBox::on_detailsCheckBox_toggled(bool checked)
emit formatChanged(); emit formatChanged();
} }
void PacketFormatGroupBox::on_bytesCheckBox_toggled(bool checked) void PacketFormatTextGroupBox::on_bytesCheckBox_toggled(bool checked)
{ {
pf_ui_->includeDataSourcesCheckBox->setEnabled(checked); pf_ui_->includeDataSourcesCheckBox->setEnabled(checked);
pf_ui_->timestampCheckBox->setEnabled(checked); pf_ui_->timestampCheckBox->setEnabled(checked);
emit formatChanged(); emit formatChanged();
} }
void PacketFormatGroupBox::on_includeColumnHeadingsCheckBox_toggled(bool) void PacketFormatTextGroupBox::on_includeColumnHeadingsCheckBox_toggled(bool)
{ {
emit formatChanged(); emit formatChanged();
} }
void PacketFormatGroupBox::on_allCollapsedButton_toggled(bool checked) void PacketFormatTextGroupBox::on_allCollapsedButton_toggled(bool checked)
{ {
if (checked) emit formatChanged(); if (checked) emit formatChanged();
} }
void PacketFormatGroupBox::on_asDisplayedButton_toggled(bool checked) void PacketFormatTextGroupBox::on_asDisplayedButton_toggled(bool checked)
{ {
if (checked) emit formatChanged(); if (checked) emit formatChanged();
} }
void PacketFormatGroupBox::on_allExpandedButton_toggled(bool checked) void PacketFormatTextGroupBox::on_allExpandedButton_toggled(bool checked)
{ {
if (checked) emit formatChanged(); if (checked) emit formatChanged();
} }
void PacketFormatGroupBox::on_includeDataSourcesCheckBox_toggled(bool) void PacketFormatTextGroupBox::on_includeDataSourcesCheckBox_toggled(bool)
{ {
emit formatChanged(); emit formatChanged();
} }
void PacketFormatGroupBox::on_timestampCheckBox_toggled(bool) void PacketFormatTextGroupBox::on_timestampCheckBox_toggled(bool)
{ {
emit formatChanged(); emit formatChanged();
} }
PacketFormatJSONGroupBox::PacketFormatJSONGroupBox(QWidget *parent) :
PacketFormatGroupBox(parent),
pf_ui_(new Ui::PacketFormatJSONGroupBox)
{
pf_ui_->setupUi(this);
connect(pf_ui_->dupKeysCheckBox, &QCheckBox::toggled, this, &PacketFormatGroupBox::formatChanged);
}
PacketFormatJSONGroupBox::~PacketFormatJSONGroupBox()
{
delete pf_ui_;
}
bool PacketFormatJSONGroupBox::noDuplicateKeys()
{
return pf_ui_->dupKeysCheckBox->isChecked();
}
void PacketFormatJSONGroupBox::updatePrintArgs(print_args_t& print_args)
{
print_args.no_duplicate_keys = noDuplicateKeys();
}

View File

@ -11,11 +11,9 @@
#ifndef PACKET_FORMAT_GROUP_BOX_H #ifndef PACKET_FORMAT_GROUP_BOX_H
#define PACKET_FORMAT_GROUP_BOX_H #define PACKET_FORMAT_GROUP_BOX_H
#include <QGroupBox> #include "file.h"
namespace Ui { #include <QGroupBox>
class PacketFormatGroupBox;
}
class PacketFormatGroupBox : public QGroupBox class PacketFormatGroupBox : public QGroupBox
{ {
@ -23,23 +21,52 @@ class PacketFormatGroupBox : public QGroupBox
public: public:
explicit PacketFormatGroupBox(QWidget *parent = 0); explicit PacketFormatGroupBox(QWidget *parent = 0);
~PacketFormatGroupBox();
bool summaryEnabled(); virtual bool isValid() const;
bool detailsEnabled(); virtual void updatePrintArgs(print_args_t& print_args) = 0;
bool bytesEnabled();
bool includeColumnHeadingsEnabled();
bool allCollapsedEnabled();
bool asDisplayedEnabled();
bool allExpandedEnabled();
uint getHexdumpOptions();
signals: signals:
void formatChanged(); void formatChanged();
};
class PacketFormatBlankGroupBox : public PacketFormatGroupBox
{
Q_OBJECT
public:
explicit PacketFormatBlankGroupBox(QWidget *parent = 0);
void updatePrintArgs(print_args_t& print_args) override;
};
namespace Ui {
class PacketFormatTextGroupBox;
}
class PacketFormatTextGroupBox : public PacketFormatGroupBox
{
Q_OBJECT
public:
explicit PacketFormatTextGroupBox(QWidget *parent = 0);
~PacketFormatTextGroupBox();
bool isValid() const override;
void updatePrintArgs(print_args_t& print_args) override;
bool summaryEnabled() const;
bool detailsEnabled() const;
bool bytesEnabled() const;
bool includeColumnHeadingsEnabled() const;
bool allCollapsedEnabled() const;
bool asDisplayedEnabled() const;
bool allExpandedEnabled() const;
uint getHexdumpOptions() const;
private slots: private slots:
void on_summaryCheckBox_toggled(bool checked); void on_summaryCheckBox_toggled(bool checked);
void on_detailsCheckBox_toggled(bool checked); void on_detailsCheckBox_toggled(bool checked);
@ -55,7 +82,26 @@ private slots:
void on_timestampCheckBox_toggled(bool checked); void on_timestampCheckBox_toggled(bool checked);
private: private:
Ui::PacketFormatGroupBox *pf_ui_; Ui::PacketFormatTextGroupBox *pf_ui_;
};
namespace Ui {
class PacketFormatJSONGroupBox;
}
class PacketFormatJSONGroupBox : public PacketFormatGroupBox
{
Q_OBJECT
public:
explicit PacketFormatJSONGroupBox(QWidget *parent = 0);
~PacketFormatJSONGroupBox();
void updatePrintArgs(print_args_t& print_args) override;
bool noDuplicateKeys();
private:
Ui::PacketFormatJSONGroupBox *pf_ui_;
}; };
#endif // PACKET_FORMAT_GROUP_BOX_H #endif // PACKET_FORMAT_GROUP_BOX_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>PacketFormatGroupBox</class> <class>PacketFormatTextGroupBox</class>
<widget class="QGroupBox" name="PacketFormatGroupBox"> <widget class="QGroupBox" name="PacketFormatTextGroupBox">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PacketFormatJSONGroupBox</class>
<widget class="QGroupBox" name="PacketFormatJSONGroupBox">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>199</height>
</rect>
</property>
<property name="windowTitle">
<string>GroupBox</string>
</property>
<property name="title">
<string>Packet Format</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="dupKeysCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Avoid duplicate keys in the JSON by using a list for sibling fields with the same key&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>No duplicate keys</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
</layout>
</widget>
<connections/>
</ui>

View File

@ -0,0 +1,53 @@
/* packet_format_stack.cpp
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "packet_format_stack.h"
#include <epan/print.h>
#include "packet_format_group_box.h"
PacketFormatStack::PacketFormatStack(QWidget *parent) :
QStackedWidget(parent)
{
PacketFormatTextGroupBox *format_text_group_box = new PacketFormatTextGroupBox(this);
PacketFormatJSONGroupBox *format_json_group_box = new PacketFormatJSONGroupBox(this);
PacketFormatBlankGroupBox *blank_group_box = new PacketFormatBlankGroupBox(this);
export_type_map_[export_type_text] = addWidget(format_text_group_box);
export_type_map_[export_type_json] = addWidget(format_json_group_box);
blank_idx_ = addWidget(blank_group_box);
connect(format_text_group_box, &PacketFormatGroupBox::formatChanged, this, &PacketFormatStack::formatChanged);
connect(format_json_group_box, &PacketFormatGroupBox::formatChanged, this, &PacketFormatStack::formatChanged);
}
PacketFormatStack::~PacketFormatStack()
{
}
bool PacketFormatStack::isValid() const
{
if (PacketFormatGroupBox *group_box = qobject_cast<PacketFormatGroupBox*>(currentWidget())) {
return group_box->isValid();
}
return true;
}
void PacketFormatStack::setExportType(export_type_e type)
{
setCurrentIndex(export_type_map_.value(type, blank_idx_));
}
void PacketFormatStack::updatePrintArgs(print_args_t& print_args)
{
if (PacketFormatGroupBox *group_box = qobject_cast<PacketFormatGroupBox*>(currentWidget())) {
group_box->updatePrintArgs(print_args);
}
}

View File

@ -0,0 +1,40 @@
/** @file
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PACKET_FORMAT_STACK_H
#define PACKET_FORMAT_STACK_H
#include "file.h"
#include "ui/file_dialog.h"
#include <QStackedWidget>
#include <QMap>
class PacketFormatStack : public QStackedWidget
{
Q_OBJECT
public:
explicit PacketFormatStack(QWidget *parent = 0);
~PacketFormatStack();
void setExportType(export_type_e type);
bool isValid() const;
void updatePrintArgs(print_args_t& print_args);
signals:
void formatChanged();
private:
QMap<export_type_e, int> export_type_map_;
int blank_idx_;
};
#endif // PACKET_FORMAT_STACK_H

View File

@ -245,23 +245,9 @@ void PrintDialog::printPackets(QPrinter *printer, bool in_preview)
/* Fill in our print args */ /* Fill in our print args */
print_args_.format = PR_FMT_TEXT; pd_ui_->formatGroupBox->updatePrintArgs(print_args_);
print_args_.print_summary = pd_ui_->formatGroupBox->summaryEnabled();
print_args_.print_col_headings = pd_ui_->formatGroupBox->includeColumnHeadingsEnabled();
print_args_.print_hex = pd_ui_->formatGroupBox->bytesEnabled();
print_args_.hexdump_options = pd_ui_->formatGroupBox->getHexdumpOptions();
print_args_.print_formfeed = pd_ui_->formFeedCheckBox->isChecked(); print_args_.print_formfeed = pd_ui_->formFeedCheckBox->isChecked();
print_args_.print_dissections = print_dissections_none;
if (pd_ui_->formatGroupBox->detailsEnabled()) {
if (pd_ui_->formatGroupBox->allCollapsedEnabled())
print_args_.print_dissections = print_dissections_collapsed;
else if (pd_ui_->formatGroupBox->asDisplayedEnabled())
print_args_.print_dissections = print_dissections_as_displayed;
else if (pd_ui_->formatGroupBox->allExpandedEnabled())
print_args_.print_dissections = print_dissections_expanded;
}
// This should be identical to printer_. However, the QPrintPreviewWidget docs // This should be identical to printer_. However, the QPrintPreviewWidget docs
// tell us to draw on the printer handed to us by the paintRequested() signal. // tell us to draw on the printer handed to us by the paintRequested() signal.
cur_printer_ = printer; cur_printer_ = printer;
@ -292,9 +278,7 @@ void PrintDialog::checkValidity()
if (!pd_ui_->rangeGroupBox->isValid()) enable = false; if (!pd_ui_->rangeGroupBox->isValid()) enable = false;
if (!pd_ui_->formatGroupBox->summaryEnabled() && if (!pd_ui_->formatGroupBox->isValid())
!pd_ui_->formatGroupBox->detailsEnabled() &&
!pd_ui_->formatGroupBox->bytesEnabled())
{ {
enable = false; enable = false;
} }

View File

@ -16,7 +16,7 @@
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="PacketFormatGroupBox" name="formatGroupBox"> <widget class="PacketFormatTextGroupBox" name="formatGroupBox">
<property name="title"> <property name="title">
<string>Packet Format</string> <string>Packet Format</string>
</property> </property>
@ -108,7 +108,7 @@
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>PacketFormatGroupBox</class> <class>PacketFormatTextGroupBox</class>
<extends>QGroupBox</extends> <extends>QGroupBox</extends>
<header>packet_format_group_box.h</header> <header>packet_format_group_box.h</header>
<container>1</container> <container>1</container>

View File

@ -198,6 +198,7 @@ set(WIRESHARK_QT_HEADERS
${CMAKE_SOURCE_DIR}/ui/qt/packet_comment_dialog.h ${CMAKE_SOURCE_DIR}/ui/qt/packet_comment_dialog.h
${CMAKE_SOURCE_DIR}/ui/qt/packet_dialog.h ${CMAKE_SOURCE_DIR}/ui/qt/packet_dialog.h
${CMAKE_SOURCE_DIR}/ui/qt/packet_format_group_box.h ${CMAKE_SOURCE_DIR}/ui/qt/packet_format_group_box.h
${CMAKE_SOURCE_DIR}/ui/qt/packet_format_stack.h
${CMAKE_SOURCE_DIR}/ui/qt/packet_list.h ${CMAKE_SOURCE_DIR}/ui/qt/packet_list.h
${CMAKE_SOURCE_DIR}/ui/qt/packet_range_group_box.h ${CMAKE_SOURCE_DIR}/ui/qt/packet_range_group_box.h
${CMAKE_SOURCE_DIR}/ui/qt/preference_editor_frame.h ${CMAKE_SOURCE_DIR}/ui/qt/preference_editor_frame.h
@ -431,6 +432,7 @@ set(WIRESHARK_QT_SRC
${CMAKE_SOURCE_DIR}/ui/qt/packet_comment_dialog.cpp ${CMAKE_SOURCE_DIR}/ui/qt/packet_comment_dialog.cpp
${CMAKE_SOURCE_DIR}/ui/qt/packet_dialog.cpp ${CMAKE_SOURCE_DIR}/ui/qt/packet_dialog.cpp
${CMAKE_SOURCE_DIR}/ui/qt/packet_format_group_box.cpp ${CMAKE_SOURCE_DIR}/ui/qt/packet_format_group_box.cpp
${CMAKE_SOURCE_DIR}/ui/qt/packet_format_stack.cpp
${CMAKE_SOURCE_DIR}/ui/qt/packet_list.cpp ${CMAKE_SOURCE_DIR}/ui/qt/packet_list.cpp
${CMAKE_SOURCE_DIR}/ui/qt/packet_range_group_box.cpp ${CMAKE_SOURCE_DIR}/ui/qt/packet_range_group_box.cpp
${CMAKE_SOURCE_DIR}/ui/qt/preference_editor_frame.cpp ${CMAKE_SOURCE_DIR}/ui/qt/preference_editor_frame.cpp
@ -544,6 +546,7 @@ set(WIRESHARK_QT_UI
${CMAKE_SOURCE_DIR}/ui/qt/packet_comment_dialog.ui ${CMAKE_SOURCE_DIR}/ui/qt/packet_comment_dialog.ui
${CMAKE_SOURCE_DIR}/ui/qt/packet_dialog.ui ${CMAKE_SOURCE_DIR}/ui/qt/packet_dialog.ui
${CMAKE_SOURCE_DIR}/ui/qt/packet_format_group_box.ui ${CMAKE_SOURCE_DIR}/ui/qt/packet_format_group_box.ui
${CMAKE_SOURCE_DIR}/ui/qt/packet_format_json_group_box.ui
${CMAKE_SOURCE_DIR}/ui/qt/packet_range_group_box.ui ${CMAKE_SOURCE_DIR}/ui/qt/packet_range_group_box.ui
${CMAKE_SOURCE_DIR}/ui/qt/preference_editor_frame.ui ${CMAKE_SOURCE_DIR}/ui/qt/preference_editor_frame.ui
${CMAKE_SOURCE_DIR}/ui/qt/preferences_dialog.ui ${CMAKE_SOURCE_DIR}/ui/qt/preferences_dialog.ui