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
12 #include "ui/preference_utils.h"
14 #include "main_window.h"
16 #include "epan/dfilter/dfilter-translator.h"
20 #include "funnel_statistics.h"
21 #include "main_application.h"
22 #include "packet_list.h"
23 #include "utils/profile_switcher.h"
24 #include "utils/qt_ui_utils.h"
25 #include "widgets/display_filter_combo.h"
27 // Packet Menu actions
28 static QList
<QAction
*> dynamic_packet_menu_actions
;
30 MainWindow::MainWindow(QWidget
*parent
) :
33 welcome_page_(nullptr),
34 cur_layout_(QVector
<unsigned>()),
35 packet_list_(nullptr),
37 byte_view_tab_(nullptr),
38 packet_diagram_(nullptr),
39 df_combo_box_(nullptr),
40 main_status_bar_(nullptr),
41 profile_switcher_(new ProfileSwitcher())
46 MainWindow::~MainWindow()
48 clearAddedPacketMenus();
51 bool MainWindow::hasSelection()
54 return packet_list_
->multiSelectActive();
59 * As hasSelection() is not looking for one single packet
60 * selection, but at least 2, this method returns true in
63 bool MainWindow::hasUniqueSelection()
66 return packet_list_
->uniqueSelectActive();
70 QList
<int> MainWindow::selectedRows(bool useFrameNum
)
73 return packet_list_
->selectedRows(useFrameNum
);
77 frame_data
* MainWindow::frameDataForRow(int row
) const
80 return packet_list_
->getFDataForRow(row
);
85 void MainWindow::insertColumn(QString name
, QString abbrev
, int pos
)
88 if (name
.length() > 0 && abbrev
.length() > 0)
90 colnr
= column_prefs_add_custom(COL_CUSTOM
, name
.toStdString().c_str(), abbrev
.toStdString().c_str(), pos
);
91 packet_list_
->columnsChanged();
92 packet_list_
->resizeColumnToContents(colnr
);
97 void MainWindow::gotoFrame(int packet_num
)
100 packet_list_
->goToPacket(packet_num
);
104 QString
MainWindow::getFilter()
106 return df_combo_box_
->currentText();
109 MainStatusBar
*MainWindow::statusBar()
111 return main_status_bar_
;
114 void MainWindow::setDisplayFilter(QString filter
, FilterAction::Action action
, FilterAction::ActionType filterType
)
116 emit
filterAction(filter
, action
, filterType
);
120 * Used for registering custom packet menus
122 * @param funnel_action a custom packet menu action
124 void MainWindow::appendPacketMenu(FunnelAction
* funnel_action
)
126 dynamic_packet_menu_actions
.append(funnel_action
);
127 connect(funnel_action
, &FunnelAction::triggered
, funnel_action
, &FunnelAction::triggerPacketCallback
);
131 * Returns the list of registered packet menu actions
133 * After ensuring that all stored custom packet menu actions
134 * are registered with the Wireshark GUI, it returns them as a list
135 * so that they can potentially be displayed to a user.
137 * @return the list of registered packet menu actions
139 QList
<QAction
*> MainWindow::getPacketMenuActions()
141 if (funnel_statistics_packet_menus_modified()) {
142 // If the packet menus were modified, we need to clear the already
143 // loaded packet menus to avoid duplicates
144 this->clearAddedPacketMenus();
145 funnel_statistics_load_packet_menus();
147 return dynamic_packet_menu_actions
;
151 * Clears the list of registered packet menu actions
153 * Clears the list of registered packet menu actions
154 * and frees all associated memory.
156 void MainWindow::clearAddedPacketMenus()
158 for( int i
=0; i
<dynamic_packet_menu_actions
.count(); ++i
)
160 delete dynamic_packet_menu_actions
[i
];
162 dynamic_packet_menu_actions
.clear();
167 * Adds the custom packet menus to the supplied QMenu
169 * This method takes in QMenu and the selected packet's data
170 * and adds all applicable custom packet menus to it.
172 * @param ctx_menu The menu to add the packet menu entries to
173 * @param finfo_array The data in the selected packet
174 * @return true if a packet menu was added to the ctx_menu
176 bool MainWindow::addPacketMenus(QMenu
* ctx_menu
, GPtrArray
*finfo_array
)
178 bool insertedPacketMenu
= false;
179 QList
<QAction
*> myPacketMenuActions
= this->getPacketMenuActions();
180 if (myPacketMenuActions
.isEmpty()) {
181 return insertedPacketMenu
;
184 // Build a set of fields present for efficient lookups
185 QSet
<QString
> fieldsPresent
= QSet
<QString
>();
186 for (unsigned fieldInfoIndex
= 0; fieldInfoIndex
< finfo_array
->len
; fieldInfoIndex
++) {
187 field_info
*fi
= (field_info
*)g_ptr_array_index (finfo_array
, fieldInfoIndex
);
188 fieldsPresent
.insert(QString(fi
->hfinfo
->abbrev
));
191 // Place actions in the relevant (sub)menu
192 // The 'root' menu is the ctx_menu, so map NULL to that
193 QHash
<QString
, QMenu
*> menuTextToMenus
;
194 menuTextToMenus
.insert(NULL
, ctx_menu
);
195 foreach (QAction
* action
, myPacketMenuActions
) {
196 if (! qobject_cast
<FunnelAction
*>(action
)) {
199 FunnelAction
* packetAction
= qobject_cast
<FunnelAction
*>(action
);
201 // Only display a menu if all required fields are present
202 if (!fieldsPresent
.contains(packetAction
->getPacketRequiredFields())) {
206 packetAction
->setPacketData(finfo_array
);
207 packetAction
->addToMenu(ctx_menu
, menuTextToMenus
);
208 insertedPacketMenu
= true;
210 return insertedPacketMenu
;
213 const char *MainWindow::translator_
= "translator";
214 const char *MainWindow::translated_filter_
= "translated filter";
216 void MainWindow::addDisplayFilterTranslationActions(QMenu
*copy_menu
) {
221 char **df_translators
= get_dfilter_translator_list();
223 if (df_translators
== NULL
|| df_translators
[0] == NULL
) {
224 g_free(df_translators
);
228 copy_menu
->addSeparator();
230 for (size_t idx
= 0; df_translators
[idx
]; idx
++) {
231 QString translator
= df_translators
[idx
];
234 action_text
= tr("Display filter as %1").arg(translator
);
236 action_text
= tr(UTF8_HORIZONTAL_ELLIPSIS
"as %1").arg(translator
);
238 QAction
*xlate_action
= copy_menu
->addAction(action_text
);
239 xlate_action
->setProperty(translator_
, QVariant::fromValue(translator
));
240 xlate_action
->setEnabled(false);
241 connect(xlate_action
, &QAction::triggered
, this, &MainWindow::copyDisplayFilterTranslation
);
242 df_translate_actions_
+= xlate_action
;
245 g_free(df_translators
);
248 void MainWindow::updateDisplayFilterTranslationActions(const QString
&df_text
)
250 for (QAction
*xlate_action
: df_translate_actions_
) {
252 QString translated_filter
;
253 if (!df_text
.isEmpty()) {
254 QString translator
= xlate_action
->property(translator_
).toString();
255 translated_filter
= gchar_free_to_qstring((char *)translate_dfilter(qUtf8Printable(translator
),
256 qUtf8Printable(df_text
)));
257 if (!translated_filter
.isEmpty()) {
261 xlate_action
->setEnabled(enable
);
262 xlate_action
->setProperty(translated_filter_
, QVariant::fromValue(translated_filter
));
266 void MainWindow::copyDisplayFilterTranslation()
268 QAction
*xlate_action
= qobject_cast
<QAction
*>(sender());
273 QString translated_filter
= xlate_action
->property(translated_filter_
).toString();
274 mainApp
->clipboard()->setText(translated_filter
);