Bug Summary

File:builds/wireshark/wireshark/ui/qt/main_application.cpp
Warning:line 645, column 13
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main_application.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/build/ui/qt -isystem /builds/wireshark/wireshark/ui/qt -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore5Compat -isystem /usr/include/x86_64-linux-gnu/qt6/QtConcurrent -isystem /usr/include/x86_64-linux-gnu/qt6/QtPrintSupport -isystem /usr/include/x86_64-linux-gnu/qt6/QtMultimedia -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/x86_64-linux-gnu/qt6/QtDBus -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D QT_CONCURRENT_LIB -D QT_CORE5COMPAT_LIB -D QT_CORE_LIB -D QT_DBUS_LIB -D QT_GUI_LIB -D QT_MULTIMEDIA_LIB -D QT_NETWORK_LIB -D QT_PRINTSUPPORT_LIB -D QT_WIDGETS_LIB -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build/ui/qt/qtui_autogen/include -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=c++17 -fdeprecated-macro -ferror-limit 19 -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-02-09-100342-3623-1 -x c++ /builds/wireshark/wireshark/ui/qt/main_application.cpp
1/* main_application.cpp
2 *
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10// warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data
11#ifdef _MSC_VER
12#pragma warning(push)
13#pragma warning(disable : 4267)
14#endif
15
16#define WS_LOG_DOMAIN"Main" LOG_DOMAIN_MAIN"Main"
17
18#include "main_application.h"
19
20#include <algorithm>
21#include <errno(*__errno_location ()).h>
22
23#include "wsutil/filesystem.h"
24#include "app/application_flavor.h"
25
26#include "epan/addr_resolv.h"
27#include "epan/column-utils.h"
28#include "epan/disabled_protos.h"
29#include "epan/ftypes/ftypes.h"
30#include "epan/prefs.h"
31#include "epan/proto.h"
32#include "epan/tap.h"
33#include "epan/timestamp.h"
34#include "epan/decode_as.h"
35#include "epan/dfilter/dfilter-macro.h"
36
37#include "ui/commandline.h"
38#include "ui/decode_as_utils.h"
39#include "ui/preference_utils.h"
40#include "ui/iface_lists.h"
41#include "ui/language.h"
42#include "ui/recent.h"
43#include "ui/simple_dialog.h"
44#include "ui/util.h"
45
46#include <ui/qt/utils/qt_ui_utils.h>
47#include <ui/qt/utils/color_utils.h>
48#include "coloring_rules_dialog.h"
49
50#include "epan/color_filters.h"
51
52#include "extcap.h"
53#ifdef HAVE_LIBPCAP1
54#include <capture/iface_monitor.h>
55#endif
56
57#include "wsutil/filter_files.h"
58#include "ui/capture_globals.h"
59#include "ui/software_update.h"
60#include "ui/file_dialog.h"
61#include "ui/recent_utils.h"
62
63#ifdef HAVE_LIBPCAP1
64#include "ui/capture.h"
65#endif
66
67#include "wsutil/utf8_entities.h"
68
69#ifdef _WIN32
70# include "wsutil/file_util.h"
71# include <QMessageBox>
72# include <QSettings>
73#endif /* _WIN32 */
74
75#include <ui/qt/capture_file.h>
76
77#include <ui/qt/main_window.h>
78#include <ui/qt/main_status_bar.h>
79#include <ui/qt/utils/workspace_state.h>
80
81#include <QAction>
82#include <QApplication>
83#include <QColorDialog>
84#include <QDesktopServices>
85#include <QDir>
86#include <QEvent>
87#include <QFileOpenEvent>
88#include <QFontInfo>
89#include <QFontMetrics>
90#include <QLibraryInfo>
91#include <QLocale>
92#include <QMainWindow>
93#include <QMutableListIterator>
94#include <QProxyStyle>
95#include <QSocketNotifier>
96#include <QThreadPool>
97#include <QUrl>
98#include <qmath.h>
99
100#if (QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
101#include <QFontDatabase>
102#endif
103#include <QMimeDatabase>
104
105#include <QStyleHints>
106
107#if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 5, 0)((6<<16)|(5<<8)|(0)) && defined(Q_OS_WIN)
108#include <QStyleFactory>
109#endif
110
111#ifdef _MSC_VER
112#pragma warning(pop)
113#endif
114
115MainApplication *mainApp;
116
117// XXX - Copied from ui/gtk/file_dlg.c
118
119static QHash<int, QList<QAction *> > dynamic_menu_groups_;
120static QHash<int, QList<QAction *> > added_menu_groups_;
121static QHash<int, QList<QAction *> > removed_menu_groups_;
122
123QString MainApplication::window_title_separator_ = QString::fromUtf8(" " UTF8_MIDDLE_DOT"\u00b7" " ");
124
125// QMimeDatabase parses a large-ish XML file and can be slow to initialize.
126// Do so in a worker thread as early as possible.
127// https://github.com/lxde/pcmanfm-qt/issues/415
128class MimeDatabaseInitThread : public QRunnable
129{
130private:
131 void run()
132 {
133 QMimeDatabase mime_db;
134 mime_db.mimeTypeForData(QByteArray());
135 }
136};
137
138#if (QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
139// Populating the font database can be slow as well.
140class FontDatabaseInitThread : public QRunnable
141{
142private:
143 void run()
144 {
145 QFontDatabase font_db;
146 }
147};
148#endif
149
150void
151topic_action(topic_action_e action)
152{
153 if (mainApp) mainApp->helpTopicAction(action);
154}
155
156/* write all capture filenames of the menu to the user's recent file */
157extern "C" void menu_recent_file_write_all(FILE *rf) {
158
159 const QList<RecentFileInfo>& recentFiles = WorkspaceState::instance()->recentCaptureFiles();
160 int rFSize = static_cast<int>(recentFiles.size());
161 for (int i = 0; i < rFSize; i++) {
162 const RecentFileInfo& rfi = recentFiles.at(i);
163
164 QString cf_name = rfi.filename;
165 if (!cf_name.isNull()) {
166 fprintf (rf, RECENT_KEY_CAPTURE_FILE"recent.capture_file" ": %s\n", qUtf8Printable(cf_name)QtPrivate::asString(cf_name).toUtf8().constData());
167 }
168 }
169}
170
171#if defined(HAVE_SOFTWARE_UPDATE) && defined(Q_OS_WIN)
172/** Check to see if Wireshark can shut down safely (e.g. offer to save the
173 * current capture).
174 */
175extern "C" int software_update_can_shutdown_callback(void) {
176 return mainApp->softwareUpdateCanShutdown();
177}
178
179/** Shut down Wireshark in preparation for an upgrade.
180 */
181extern "C" void software_update_shutdown_request_callback(void) {
182 mainApp->softwareUpdateShutdownRequest();
183}
184#endif // HAVE_SOFTWARE_UPDATE && Q_OS_WIN
185
186void MainApplication::refreshPacketData()
187{
188 if (host_name_lookup_process()) {
189 emit addressResolutionChanged();
190 } else if (col_data_changed()) {
191 emit columnDataChanged();
192 }
193}
194
195// The Fusion style, and the Mac style, allow QMessageBox text to be
196// selectable by the mouse. The various Windows styles do not. On
197// Windows we switch between the Fusion style and Windows style depending
198// on dark mode, so to make things consistent on Windows (and between
199// Windows and other platforms) alllow it on all styles.
200class MsgBoxTextStyle : public QProxyStyle
201{
202public:
203 MsgBoxTextStyle(QStyle *style = nullptr) : QProxyStyle(style) {}
204 MsgBoxTextStyle(const QString &key) : QProxyStyle(key) {}
205 int styleHint(StyleHint hint, const QStyleOption *option = nullptr,
206 const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
207 {
208 if (hint == QStyle::SH_MessageBox_TextInteractionFlags)
209 return QProxyStyle::styleHint(hint, option, widget, returnData) | Qt::TextSelectableByMouse;
210 return QProxyStyle::styleHint(hint, option, widget, returnData);
211 }
212};
213
214#if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 5, 0)((6<<16)|(5<<8)|(0)) && defined(Q_OS_WIN)
215void MainApplication::colorSchemeChanged() {
216 // TODO - Supposedly the windows11 style handles dark mode better.
217 if (ColorUtils::themeIsDark()) {
218 setStyle(QStyleFactory::create("fusion"));
219 } else {
220 setStyle(new MsgBoxTextStyle("windowsvista"));
221 }
222}
223#endif
224
225void MainApplication::updateTaps()
226{
227 draw_tap_listeners(false);
228}
229
230QDir MainApplication::openDialogInitialDir() {
231 return QDir(get_open_dialog_initial_dir());
232}
233
234void MainApplication::setLastOpenDirFromFilename(const QString file_name)
235{
236 /* XXX - Use canonicalPath() instead of absolutePath()? */
237 QString directory = QDir::toNativeSeparators(QFileInfo(file_name).absolutePath());
238 /* XXX - printable? */
239 set_last_open_dir(qUtf8Printable(directory)QtPrivate::asString(directory).toUtf8().constData());
240}
241
242void MainApplication::helpTopicAction(topic_action_e action)
243{
244 QString url = gchar_free_to_qstring(topic_action_url(action));
245
246 if (!url.isEmpty()) {
247 QDesktopServices::openUrl(QUrl(QDir::fromNativeSeparators(url)));
248 }
249}
250
251const QFont MainApplication::monospaceFont(bool zoomed) const
252{
253 if (zoomed) {
254 return zoomed_font_;
255 }
256 return mono_font_;
257}
258
259void MainApplication::setMonospaceFont(const char *font_string) {
260
261 if (font_string && strlen(font_string) > 0) {
262#if (QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
263 // Qt 6's QFont::toString returns a value with 16 or 17 fields, e.g.
264 // Consolas,11,-1,5,400,0,0,0,0,0,0,0,0,0,0,1
265 // Corbel,10,-1,5,400,0,0,0,0,0,0,0,0,0,0,1,Regular
266 // Qt 5's QFont::fromString expects a value with 10 or 11 fields, e.g.
267 // Consolas,10,-1,5,50,0,0,0,0,0
268 // Corbel,10,-1,5,50,0,0,0,0,0,Regular
269 // It looks like Qt6's QFont::fromString can read both forms:
270 // https://github.com/qt/qtbase/blob/6.0/src/gui/text/qfont.cpp#L2146
271 // but Qt5's cannot:
272 // https://github.com/qt/qtbase/blob/5.15/src/gui/text/qfont.cpp#L2151
273 const char *fs_ptr = font_string;
274 int field_count = 1;
275 while ((fs_ptr = strchr(fs_ptr, ',')) != NULL__null) {
276 fs_ptr++;
277 field_count++;
278 }
279 if (field_count <= 11) {
280#endif
281 mono_font_.fromString(font_string);
282
283 // Only accept the font name if it actually exists.
284 if (mono_font_.family() == QFontInfo(mono_font_).family()) {
285 return;
286 } else {
287 ws_warning("Monospace font family %s differs from its fontinfo: %s",do { if (true) { ws_log_full("Main", LOG_LEVEL_WARNING, "ui/qt/main_application.cpp"
, 288, __func__, "Monospace font family %s differs from its fontinfo: %s"
, QtPrivate::asString(mono_font_.family()).toUtf8().constData
(), QtPrivate::asString(QFontInfo(mono_font_).family()).toUtf8
().constData()); } } while (0)
288 qUtf8Printable(mono_font_.family()), qUtf8Printable(QFontInfo(mono_font_).family()))do { if (true) { ws_log_full("Main", LOG_LEVEL_WARNING, "ui/qt/main_application.cpp"
, 288, __func__, "Monospace font family %s differs from its fontinfo: %s"
, QtPrivate::asString(mono_font_.family()).toUtf8().constData
(), QtPrivate::asString(QFontInfo(mono_font_).family()).toUtf8
().constData()); } } while (0)
;
289 }
290#if (QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
291 } else {
292 ws_warning("Monospace font %s appears to be from Qt6 and we're running Qt5.", font_string)do { if (true) { ws_log_full("Main", LOG_LEVEL_WARNING, "ui/qt/main_application.cpp"
, 292, __func__, "Monospace font %s appears to be from Qt6 and we're running Qt5."
, font_string); } } while (0)
;
293 }
294#endif
295 }
296
297 // https://en.wikipedia.org/wiki/Category:Monospaced_typefaces
298 const char *win_default_font = "Consolas";
299 const char *win_alt_font = "Lucida Console";
300 // SF Mono might be a system font someday. Right now (Oct 2016) it appears
301 // to be limited to Xcode and Terminal.
302 // http://www.openradar.me/26790072
303 // http://www.openradar.me/26862220
304 const char *osx_default_font = "SF Mono";
305 const QStringList osx_alt_fonts = QStringList() << "Menlo" << "Monaco";
306 // XXX Detect Ubuntu systems (e.g. via /etc/os-release and/or
307 // /etc/lsb_release) and add "Ubuntu Mono Regular" there.
308 // https://design.ubuntu.com/font/
309 const char *x11_default_font = "Liberation Mono";
310 const QStringList x11_alt_fonts = QStringList() << "DejaVu Sans Mono" << "Bitstream Vera Sans Mono";
311 const QStringList fallback_fonts = QStringList() << "Lucida Sans Typewriter" << "Inconsolata" << "Droid Sans Mono" << "Andale Mono" << "Courier New" << "monospace";
312 QStringList substitutes;
313 int font_size_adjust = 0;
314
315 // Try to pick the latest, shiniest fixed-width font for our OS.
316#if defined(Q_OS_WIN)
317 const char *default_font = win_default_font;
318 substitutes << win_alt_font << osx_default_font << osx_alt_fonts << x11_default_font << x11_alt_fonts << fallback_fonts;
319# if (QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
320 font_size_adjust = 1;
321# else // QT_VERSION
322 font_size_adjust = 2;
323# endif // QT_VERSION
324#elif defined(Q_OS_MAC)
325 const char *default_font = osx_default_font;
326 substitutes << osx_alt_fonts << win_default_font << win_alt_font << x11_default_font << x11_alt_fonts << fallback_fonts;
327#else // Q_OS
328 const char *default_font = x11_default_font;
329 substitutes << x11_alt_fonts << win_default_font << win_alt_font << osx_default_font << osx_alt_fonts << fallback_fonts;
330#endif // Q_OS
331
332 mono_font_ = QFont(default_font, mainApp->font().pointSize() + font_size_adjust);
333 mono_font_.insertSubstitutions(default_font, substitutes);
334 mono_font_.setBold(false);
335
336 // Retrieve the effective font and apply it.
337 mono_font_.setFamily(QFontInfo(mono_font_).family());
338
339 wmem_free(wmem_epan_scope(), prefs.gui_font_name);
340 prefs.gui_font_name = wmem_strdup(wmem_epan_scope(), mono_font_.toString().toUtf8().constData());
341}
342
343int MainApplication::monospaceTextSize(const char *str)
344{
345 return QFontMetrics(mono_font_).horizontalAdvance(str);
346}
347
348void MainApplication::setConfigurationProfile(const char *profile_name, bool write_recent_file)
349{
350 char *rf_path;
351 int rf_open_errno;
352 char *err_msg = NULL__null;
353 const char* env_prefix = application_configuration_environment_prefix();
354
355 bool prev_capture_no_interface_load;
356 bool prev_capture_no_extcap;
357
358 /* First check if profile exists */
359 if (!profile_exists(env_prefix, profile_name, false)) {
360 if (profile_exists(env_prefix, profile_name, true)) {
361 char *pf_dir_path, *pf_dir_path2, *pf_filename;
362 /* Copy from global profile */
363 if (create_persconffile_profile(env_prefix, profile_name, &pf_dir_path) == -1) {
364 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK0x01,
365 "Can't create directory\n\"%s\":\n%s.",
366 pf_dir_path, g_strerror(errno(*__errno_location ())));
367
368 g_free(pf_dir_path);
369 }
370
371 if (copy_persconffile_profile(env_prefix, profile_name, profile_name, true, &pf_filename,
372 &pf_dir_path, &pf_dir_path2) == -1) {
373 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK0x01,
374 "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
375 pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno(*__errno_location ())));
376
377 g_free(pf_filename);
378 g_free(pf_dir_path);
379 g_free(pf_dir_path2);
380 }
381 } else {
382 /* No personal and no global profile exists */
383 return;
384 }
385 }
386
387 /* Then check if changing to another profile */
388 if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
389 return;
390 }
391
392 prev_capture_no_interface_load = prefs.capture_no_interface_load;
393 prev_capture_no_extcap = prefs.capture_no_extcap;
394
395 /* Get the current geometry, before writing it to disk */
396 emit profileChanging();
397
398 if (write_recent_file && profile_exists(env_prefix, get_profile_name(), false))
399 {
400 /* Write recent file for profile we are leaving, if it still exists */
401 write_profile_recent();
402 }
403
404 // Freeze the packet list early to avoid updating column data before doing a
405 // full redissection. The packet list will be thawed when redissection is done.
406 emit freezePacketList(true);
407
408 /* Set profile name and update the status bar */
409 set_profile_name (profile_name);
410 emit profileNameChanged(profile_name);
411
412 /* Apply new preferences */
413 readConfigurationFiles(true);
414
415 /* Apply command-line preferences */
416 commandline_options_reapply();
417 extcap_register_preferences();
418
419 /* Switching profile requires reloading the macro list. */
420 reloadDisplayFilterMacros();
421
422 if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
423 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK0x01,
424 "Could not open common recent file\n\"%s\": %s.",
425 rf_path, g_strerror(rf_open_errno));
426 g_free(rf_path);
427 }
428 if (recent.gui_fileopen_remembered_dir &&
429 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR21) {
430 set_last_open_dir(recent.gui_fileopen_remembered_dir);
431 }
432 timestamp_set_type(recent.gui_time_format);
433 timestamp_set_precision(recent.gui_time_precision);
434 timestamp_set_seconds_type (recent.gui_seconds_format);
435
436 prefs_to_capture_opts(&global_capture_opts);
437 prefs_apply_all();
438#ifdef HAVE_LIBPCAP1
439 update_local_interfaces(&global_capture_opts);
440#endif
441
442 emit columnsChanged();
443 emit colorsChanged();
444 emit preferencesChanged();
445 emit recentPreferencesRead();
446 emit filterExpressionsChanged();
447 emit checkDisplayFilter();
448 emit captureFilterListChanged();
449 emit displayFilterListChanged();
450
451 /* Reload color filters */
452 if (!color_filters_reload(&err_msg, color_filter_add_cb, application_configuration_environment_prefix())) {
453 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK0x01, "%s", err_msg);
454 g_free(err_msg);
455 }
456
457 /* Load interfaces if settings have changed */
458 if (!prefs.capture_no_interface_load &&
459 ((prefs.capture_no_interface_load != prev_capture_no_interface_load) ||
460 (prefs.capture_no_extcap != prev_capture_no_extcap))) {
461 refreshLocalInterfaces();
462 }
463
464 emit localInterfaceListChanged();
465 emit packetDissectionChanged();
466
467 /* Write recent_common file to ensure last used profile setting is stored. */
468 write_recent();
469}
470
471void MainApplication::reloadLuaPluginsDelayed()
472{
473 QTimer::singleShot(0, this, &MainApplication::reloadLuaPlugins);
474}
475
476const QIcon &MainApplication::normalIcon()
477{
478 if (normal_icon_.isNull()) {
479 initializeIcons();
480 }
481 return normal_icon_;
482}
483
484const QIcon &MainApplication::captureIcon()
485{
486 if (capture_icon_.isNull()) {
487 initializeIcons();
488 }
489 return capture_icon_;
490}
491
492const QString MainApplication::windowTitleString(QStringList title_parts)
493{
494 QMutableStringListIterator tii(title_parts);
495 while (tii.hasNext()) {
496 QString ti = tii.next();
497 if (ti.isEmpty()) tii.remove();
498 }
499 title_parts.prepend(applicationName());
500 return title_parts.join(window_title_separator_);
501}
502
503void MainApplication::applyCustomColorsFromRecent()
504{
505 int i = 0;
506 bool ok;
507 for (GList *custom_color = recent.custom_colors; custom_color; custom_color = custom_color->next) {
508 QRgb rgb = QString((const char *)custom_color->data).toUInt(&ok, 16);
509 if (ok) {
510 QColorDialog::setCustomColor(i++, QColor(rgb));
511 }
512 }
513}
514
515// Return the first top-level MainWindow.
516MainWindow *MainApplication::mainWindow()
517{
518 foreach (QWidget *tlw, topLevelWidgets())for (auto _container_518 = QtPrivate::qMakeForeachContainer(topLevelWidgets
()); _container_518.i != _container_518.e; ++_container_518.i
) if (QWidget *tlw = *_container_518.i; false) {} else
{
519 MainWindow *tlmw = qobject_cast<MainWindow *>(tlw);
520 if (tlmw && tlmw->isVisible()) {
521 return tlmw;
522 }
523 }
524 return nullptr;
525}
526
527void MainApplication::storeCustomColorsInRecent()
528{
529 if (QColorDialog::customCount()) {
530 prefs_clear_string_list(recent.custom_colors);
531 recent.custom_colors = NULL__null;
532 for (int i = 0; i < QColorDialog::customCount(); i++) {
533 QRgb rgb = QColorDialog::customColor(i).rgb();
534 recent.custom_colors = g_list_append(recent.custom_colors, ws_strdup_printf("%08x", rgb)wmem_strdup_printf(__null, "%08x", rgb));
535 }
536 }
537}
538
539bool MainApplication::event(QEvent *event)
540{
541 QString display_filter = NULL__null;
542 if (event->type() == QEvent::FileOpen) {
543 QFileOpenEvent *foe = static_cast<QFileOpenEvent *>(event);
544 if (foe && foe->file().length() > 0) {
545 QString cf_path(foe->file());
546 if (initialized_) {
547 emit openCaptureFile(cf_path, display_filter, WTAP_TYPE_AUTO0);
548 } else {
549 pending_open_files_.append(cf_path);
550 }
551 }
552 return true;
553 }
554 return QApplication::event(event);
555}
556
557void MainApplication::cleanup()
558{
559 software_update_cleanup();
560 storeCustomColorsInRecent();
561 // Write the user's recent file(s) to disk.
562 write_profile_recent();
563 write_recent();
564
565 // We might end up here via exit_application.
566 QThreadPool::globalInstance()->waitForDone();
567}
568
569MainApplication::MainApplication(int &argc, char **argv) :
570 QApplication(argc, argv),
571 initialized_(false),
572 is_reloading_lua_(false),
573 if_notifier_(NULL__null),
574 active_captures_(0),
575 refresh_interfaces_pending_(false)
576#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
577 , normal_icon_(windowIcon())
578#endif
579#ifdef HAVE_LIBPCAP1
580 , cached_if_list_(NULL__null)
581#endif
582{
583 mainApp = this;
584
585 MimeDatabaseInitThread *mime_db_init_thread = new(MimeDatabaseInitThread);
586 QThreadPool::globalInstance()->start(mime_db_init_thread);
587#if (QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
588 FontDatabaseInitThread *font_db_init_thread = new (FontDatabaseInitThread);
589 QThreadPool::globalInstance()->start(font_db_init_thread);
590#endif
591
592 Q_INIT_RESOURCE(about)do { extern int qInitResources_about (); qInitResources_about
(); } while (false)
;
1
Loop condition is false. Exiting loop
593 Q_INIT_RESOURCE(i18n)do { extern int qInitResources_i18n (); qInitResources_i18n (
); } while (false)
;
2
Loop condition is false. Exiting loop
594 Q_INIT_RESOURCE(layout)do { extern int qInitResources_layout (); qInitResources_layout
(); } while (false)
;
3
Loop condition is false. Exiting loop
595 Q_INIT_RESOURCE(stock_icons)do { extern int qInitResources_stock_icons (); qInitResources_stock_icons
(); } while (false)
;
4
Loop condition is false. Exiting loop
596 Q_INIT_RESOURCE(languages)do { extern int qInitResources_languages (); qInitResources_languages
(); } while (false)
;
5
Loop condition is false. Exiting loop
597
598#ifdef Q_OS_WIN
599 /* RichEd20.DLL is needed for native file dialog filter entries. */
600 ws_load_library("riched20.dll");
601#endif // Q_OS_WIN
602
603#if (QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
604 setAttribute(Qt::AA_UseHighDpiPixmaps);
605#endif
606
607#if QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0))
608 setAttribute(Qt::AA_DisableWindowContextHelpButton);
609#endif
610
611 // We use a lot of style sheets that base their colors on the main
612 // application palette, so this works better.
613 setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles, true);
614
615 // Throw various settings at the wall with the hope that one of them will
616 // enable context menu shortcuts QTBUG-69452, QTBUG-109590
617 setAttribute(Qt::AA_DontShowShortcutsInContextMenus, false);
618 styleHints()->setShowShortcutsInContextMenus(true);
619
620 packet_data_timer_.setParent(this);
621 connect(&packet_data_timer_, &QTimer::timeout, this, &MainApplication::refreshPacketData);
622 packet_data_timer_.start(1000);
623
624 tap_update_timer_.setParent(this);
625 // tap_update_timer interval is set when preferences are set before init
626 connect(this, &MainApplication::appInitialized, &tap_update_timer_, [&]() { tap_update_timer_.start(); });
627 connect(this, &MainApplication::appInitialized, [this] { emit aggregationVisiblity(); });
628 connect(&tap_update_timer_, &QTimer::timeout, this, &MainApplication::updateTaps);
629
630
631 // If our window text is lighter than the window background, assume the theme is dark.
632 prefs_set_gui_theme_is_dark(ColorUtils::themeIsDark());
633
634#if defined(HAVE_SOFTWARE_UPDATE) && defined(Q_OS_WIN)
635 connect(this, &MainApplication::softwareUpdateQuit, this, &MainApplication::quit, Qt::QueuedConnection);
636#endif
637
638#if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 5, 0)((6<<16)|(5<<8)|(0)) && defined(Q_OS_WIN)
639 colorSchemeChanged();
640 connect(styleHints(), &QStyleHints::colorSchemeChanged, this, &MainApplication::colorSchemeChanged);
641#else
642 setStyle(new MsgBoxTextStyle);
6
Memory is allocated
643#endif
644
645 connect(qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
, &QApplication::aboutToQuit, this, &MainApplication::cleanup);
7
Potential memory leak
646}
647
648MainApplication::~MainApplication()
649{
650 mainApp = NULL__null;
651#ifdef HAVE_LIBPCAP1
652 free_interface_list(cached_if_list_);
653#endif
654 clearDynamicMenuGroupItems();
655}
656
657void MainApplication::registerUpdate(register_action_e action, const char *message)
658{
659 emit splashUpdate(action, message);
660}
661
662void MainApplication::emitAppSignal(AppSignal signal)
663{
664 switch (signal) {
665 case ColumnsChanged:
666 emit columnsChanged();
667 break;
668 case CaptureFilterListChanged:
669 emit captureFilterListChanged();
670 break;
671 case DisplayFilterListChanged:
672 emit displayFilterListChanged();
673 break;
674 case FilterExpressionsChanged:
675 emit filterExpressionsChanged();
676 break;
677 case LocalInterfacesChanged:
678 emit localInterfaceListChanged();
679 break;
680 case NameResolutionChanged:
681 emit addressResolutionChanged();
682 break;
683 case PreferencesChanged:
684 tap_update_timer_.setInterval(prefs.tap_update_interval);
685 setMonospaceFont(prefs.gui_font_name);
686 emit preferencesChanged();
687 break;
688 case PacketDissectionChanged:
689 emit packetDissectionChanged();
690 break;
691 case ProfileChanging:
692 emit profileChanging();
693 break;
694 case RecentPreferencesRead:
695 emit recentPreferencesRead();
696 break;
697 case FieldsChanged:
698 emit fieldsChanged();
699 break;
700 case ColorsChanged:
701 ColorUtils::setScheme(prefs.gui_color_scheme);
702 emit colorsChanged();
703 break;
704 case FreezePacketList:
705 emit freezePacketList(false);
706 break;
707 case AggregationVisiblity:
708 emit aggregationVisiblity();
709 break;
710 case AggregationChanged:
711 emit aggregationChanged();
712 break;
713 default:
714 break;
715 }
716}
717
718// Flush any collected app signals.
719//
720// On macOS emitting PacketDissectionChanged from a dialog can
721// render the application unusable:
722// https://gitlab.com/wireshark/wireshark/-/issues/11361
723// https://gitlab.com/wireshark/wireshark/-/issues/11448
724// Work around the problem by queueing up app signals and emitting them
725// after the dialog is closed.
726//
727// The following bugs might be related although they don't describe the
728// exact behavior we're working around here:
729// https://bugreports.qt.io/browse/QTBUG-38512
730// https://bugreports.qt.io/browse/QTBUG-38600
731void MainApplication::flushAppSignals()
732{
733 while (!app_signals_.isEmpty()) {
734 mainApp->emitAppSignal(app_signals_.takeFirst());
735 }
736}
737
738void MainApplication::emitStatCommandSignal(const QString &menu_path, const char *arg, void *userdata)
739{
740 emit openStatCommandDialog(menu_path, arg, userdata);
741}
742
743void MainApplication::emitTapParameterSignal(const QString cfg_abbr, const QString arg, void *userdata)
744{
745 emit openTapParameterDialog(cfg_abbr, arg, userdata);
746}
747
748// XXX Combine statistics and funnel routines into addGroupItem + groupItems?
749void MainApplication::addDynamicMenuGroupItem(int group, QAction *sg_action)
750{
751 if (!dynamic_menu_groups_.contains(group)) {
752 dynamic_menu_groups_[group] = QList<QAction *>();
753 }
754 dynamic_menu_groups_[group] << sg_action;
755}
756
757void MainApplication::appendDynamicMenuGroupItem(int group, QAction *sg_action)
758{
759 if (!added_menu_groups_.contains(group)) {
760 added_menu_groups_[group] = QList<QAction *>();
761 }
762 added_menu_groups_[group] << sg_action;
763 addDynamicMenuGroupItem(group, sg_action);
764}
765
766void MainApplication::removeDynamicMenuGroupItem(int group, QAction *sg_action)
767{
768 if (!removed_menu_groups_.contains(group)) {
769 removed_menu_groups_[group] = QList<QAction *>();
770 }
771 removed_menu_groups_[group] << sg_action;
772 dynamic_menu_groups_[group].removeAll(sg_action);
773}
774
775void MainApplication::clearDynamicMenuGroupItems()
776{
777 foreach (int group, dynamic_menu_groups_.keys())for (auto _container_777 = QtPrivate::qMakeForeachContainer(dynamic_menu_groups_
.keys()); _container_777.i != _container_777.e; ++_container_777
.i) if (int group = *_container_777.i; false) {} else
{
778 dynamic_menu_groups_[group].clear();
779 }
780}
781
782QList<QAction *> MainApplication::dynamicMenuGroupItems(int group)
783{
784 if (!dynamic_menu_groups_.contains(group)) {
785 return QList<QAction *>();
786 }
787
788 QList<QAction *> sgi_list = dynamic_menu_groups_[group];
789 std::sort(sgi_list.begin(), sgi_list.end(), qActionLessThan);
790 return sgi_list;
791}
792
793QList<QAction *> MainApplication::addedMenuGroupItems(int group)
794{
795 if (!added_menu_groups_.contains(group)) {
796 return QList<QAction *>();
797 }
798
799 QList<QAction *> sgi_list = added_menu_groups_[group];
800 std::sort(sgi_list.begin(), sgi_list.end(), qActionLessThan);
801 return sgi_list;
802}
803
804QList<QAction *> MainApplication::removedMenuGroupItems(int group)
805{
806 if (!removed_menu_groups_.contains(group)) {
807 return QList<QAction *>();
808 }
809
810 QList<QAction *> sgi_list = removed_menu_groups_[group];
811 std::sort(sgi_list.begin(), sgi_list.end(), qActionLessThan);
812 return sgi_list;
813}
814
815void MainApplication::clearAddedMenuGroupItems()
816{
817 foreach (int group, added_menu_groups_.keys())for (auto _container_817 = QtPrivate::qMakeForeachContainer(added_menu_groups_
.keys()); _container_817.i != _container_817.e; ++_container_817
.i) if (int group = *_container_817.i; false) {} else
{
818 added_menu_groups_[group].clear();
819 }
820}
821
822void MainApplication::clearRemovedMenuGroupItems()
823{
824 foreach (int group, removed_menu_groups_.keys())for (auto _container_824 = QtPrivate::qMakeForeachContainer(removed_menu_groups_
.keys()); _container_824.i != _container_824.e; ++_container_824
.i) if (int group = *_container_824.i; false) {} else
{
825 foreach (QAction *action, removed_menu_groups_[group])for (auto _container_825 = QtPrivate::qMakeForeachContainer(removed_menu_groups_
[group]); _container_825.i != _container_825.e; ++_container_825
.i) if (QAction *action = *_container_825.i; false) {} else
{
826 delete action;
827 }
828 removed_menu_groups_[group].clear();
829 }
830}
831
832#ifdef HAVE_LIBPCAP1
833
834static void
835iface_mon_event_cb(const char *iface, int added, int up)
836{
837 int present = 0;
838 unsigned ifs, j;
839 interface_t *device;
840 interface_options *interface_opts;
841
842 for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) {
843 device = &g_array_index(global_capture_opts.all_ifaces, interface_t, ifs)(((interface_t*) (void *) (global_capture_opts.all_ifaces)->
data) [(ifs)])
;
844 if (strcmp(device->name, iface) == 0) {
845 present = 1;
846 if (!up) {
847 /*
848 * Interface went down or disappeared; remove all instances
849 * of it from the current list of interfaces selected
850 * for capturing.
851 */
852 for (j = 0; j < global_capture_opts.ifaces->len; j++) {
853 interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, j)(((interface_options*) (void *) (global_capture_opts.ifaces)->
data) [(j)])
;
854 if (strcmp(interface_opts->name, device->name) == 0) {
855 capture_opts_del_iface(&global_capture_opts, j);
856 }
857 }
858 }
859 }
860 }
861
862 mainApp->emitLocalInterfaceEvent(iface, added, up);
863 if (present != up) {
864 /*
865 * We've been told that there's a new interface or that an old
866 * interface is gone; reload the local interface list.
867 *
868 * XXX: We also want to reload the local interface list if [what
869 * we can retrieve about] the capabilities of the device have changed.
870 * Ideally we'd update the capabilities of just the one device in
871 * the cache and signal that the list has been updated, instead of
872 * freeing the entire cache and scanning again - but some extcaps
873 * depend on other interfaces being up; e.g. by default androiddump
874 * tries to connect to the loopback interface to look for adb running,
875 * so if the loopback interface changes so does the status of
876 * androiddump.
877 *
878 * On Linux, at least, you can't get the capabilities from a down
879 * interface, but it's still present in all_ifaces - dumpcap returns
880 * it in the list, and we show it so the user can get a status / error
881 * message when trying to capture on it instead of it vanishing.
882 * So if both present and up are true, then we still want to refresh
883 * to update the capabilities and restart the stats.
884 *
885 * We also store the address in all_ifaces and show them to the user,
886 * so we probably should monitor those events as well and update
887 * the interface list appropriately when those change.
888 */
889 mainApp->refreshLocalInterfaces();
890 }
891}
892
893#endif
894
895void MainApplication::ifChangeEventsAvailable()
896{
897#ifdef HAVE_LIBPCAP1
898 /*
899 * Something's readable from the descriptor for interface
900 * monitoring.
901 *
902 * Have the interface-monitoring code Read whatever interface-change
903 * events are available, and call the callback for them.
904 */
905 iface_mon_event();
906#endif
907}
908
909void MainApplication::emitLocalInterfaceEvent(const char *ifname, int added, int up)
910{
911 emit localInterfaceEvent(ifname, added, up);
912}
913
914void MainApplication::refreshLocalInterfaces()
915{
916 if (active_captures_ > 0) {
917 refresh_interfaces_pending_ = true;
918 return;
919 }
920
921 refresh_interfaces_pending_ = false;
922 extcap_clear_interfaces();
923
924#ifdef HAVE_LIBPCAP1
925 emit scanLocalInterfaces(nullptr);
926#endif
927}
928
929#ifdef HAVE_LIBPCAP1
930GList* MainApplication::getInterfaceList() const
931{
932 return interface_list_copy(cached_if_list_);
933}
934
935void MainApplication::setInterfaceList(GList *if_list)
936{
937 free_interface_list(cached_if_list_);
938 cached_if_list_ = interface_list_copy(if_list);
939}
940#endif
941
942void MainApplication::allSystemsGo(const char* name_proper, const char* version)
943{
944 QString display_filter = NULL__null;
945 initialized_ = true;
946 emit appInitialized();
947 while (pending_open_files_.length() > 0) {
948 emit openCaptureFile(pending_open_files_.front(), display_filter, WTAP_TYPE_AUTO0);
949 pending_open_files_.pop_front();
950 }
951 software_update_init(name_proper, version);
952
953#ifdef HAVE_LIBPCAP1
954 int err;
955 err = iface_mon_start(&iface_mon_event_cb);
956 if (err == 0) {
957 if_notifier_ = new QSocketNotifier(iface_mon_get_sock(),
958 QSocketNotifier::Read, this);
959 connect(if_notifier_, &QSocketNotifier::activated, this, &MainApplication::ifChangeEventsAvailable);
960 }
961#endif
962}
963
964_e_prefs *MainApplication::readConfigurationFiles(bool reset)
965{
966 e_prefs *prefs_p;
967
968 if (reset) {
969 //
970 // Reset current preferences and enabled/disabled protocols and
971 // heuristic dissectors before reading.
972 // (Needed except when this is called at startup.)
973 //
974 prefs_reset(application_configuration_environment_prefix(), application_columns(), application_num_columns());
975 proto_reenable_all();
976 }
977
978 /* Load libwireshark settings from the current profile. */
979 prefs_p = epan_load_settings();
980
981 return prefs_p;
982}
983
984static void switchTranslator(QTranslator& myTranslator, const QString& filename,
985 const QString& searchPath)
986{
987 mainApp->removeTranslator(&myTranslator);
988
989 if (myTranslator.load(filename, searchPath))
990 mainApp->installTranslator(&myTranslator);
991}
992
993void MainApplication::loadLanguage(const QString newLanguage)
994{
995 QLocale locale;
996 QString localeLanguage;
997 const char* env_prefix = application_configuration_environment_prefix();
998
999 if (newLanguage.isEmpty() || newLanguage == USE_SYSTEM_LANGUAGE"system") {
1000 locale = QLocale::system();
1001 localeLanguage = locale.name();
1002 } else {
1003 localeLanguage = newLanguage;
1004 locale = QLocale(localeLanguage);
1005 }
1006
1007 QLocale::setDefault(locale);
1008 switchTranslator(mainApp->translator,
1009 QStringLiteral("wireshark_%1.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "wireshark_%1.qm")
))
.arg(localeLanguage), QStringLiteral(":/i18n/")(QString(QtPrivate::qMakeStringPrivate(u"" ":/i18n/"))));
1010 if (QFile::exists(QStringLiteral("%1/%2/wireshark_%3.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "%1/%2/wireshark_%3.qm"
)))
1011 .arg(get_datafile_dir(env_prefix)).arg("languages").arg(localeLanguage)))
1012 switchTranslator(mainApp->translator,
1013 QStringLiteral("wireshark_%1.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "wireshark_%1.qm")
))
.arg(localeLanguage), QStringLiteral("%1/languages")(QString(QtPrivate::qMakeStringPrivate(u"" "%1/languages"))).arg(get_datafile_dir(env_prefix)));
1014 if (QFile::exists(QStringLiteral("%1/wireshark_%3.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "%1/wireshark_%3.qm"
)))
1015 .arg(gchar_free_to_qstring(get_persconffile_path("languages", false, env_prefix))).arg(localeLanguage)))
1016 switchTranslator(mainApp->translator,
1017 QStringLiteral("wireshark_%1.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "wireshark_%1.qm")
))
.arg(localeLanguage), gchar_free_to_qstring(get_persconffile_path("languages", false, env_prefix)));
1018 if (QFile::exists(QStringLiteral("%1/qt_%2.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "%1/qt_%2.qm")))
1019 .arg(get_datafile_dir(env_prefix)).arg(localeLanguage))) {
1020 switchTranslator(mainApp->translatorQt,
1021 QStringLiteral("qt_%1.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "qt_%1.qm"))).arg(localeLanguage), QString(get_datafile_dir(env_prefix)));
1022 } else if (QFile::exists(QStringLiteral("%1/qt_%2.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "%1/qt_%2.qm")))
1023 .arg(get_datafile_dir(env_prefix)).arg(localeLanguage.left(localeLanguage.lastIndexOf('_'))))) {
1024 switchTranslator(mainApp->translatorQt,
1025 QStringLiteral("qt_%1.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "qt_%1.qm"))).arg(localeLanguage.left(localeLanguage.lastIndexOf('_'))), QString(get_datafile_dir(env_prefix)));
1026 } else {
1027#if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0))
1028 QString translationPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
1029#else
1030 QString translationPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
1031#endif
1032 switchTranslator(mainApp->translatorQt, QStringLiteral("qt_%1.qm")(QString(QtPrivate::qMakeStringPrivate(u"" "qt_%1.qm"))).arg(localeLanguage), translationPath);
1033 }
1034}
1035
1036void MainApplication::doTriggerMenuItem(MainMenuItem menuItem)
1037{
1038 switch (menuItem)
1039 {
1040 case FileOpenDialog:
1041 emit openCaptureFile(QString(), QString(), WTAP_TYPE_AUTO0);
1042 break;
1043 case CaptureOptionsDialog:
1044 emit openCaptureOptions();
1045 break;
1046 }
1047}
1048
1049void MainApplication::zoomTextFont(int zoomLevel)
1050{
1051 // Scale by 10%, rounding to nearest half point, minimum 1 point.
1052 // XXX Small sizes repeat. It might just be easier to create a map of multipliers.
1053 qreal zoom_size = mono_font_.pointSize() * 2 * qPow(qreal(1.1), zoomLevel);
1054 zoom_size = qRound(zoom_size) / qreal(2.0);
1055 zoom_size = qMax(zoom_size, qreal(1.0));
1056
1057 zoomed_font_ = mono_font_;
1058 zoomed_font_.setPointSizeF(zoom_size);
1059 emit zoomMonospaceFont(zoomed_font_);
1060
1061 QFont zoomed_application_font = font();
1062 zoomed_application_font.setPointSizeF(zoom_size);
1063 emit zoomRegularFont(zoomed_application_font);
1064}
1065
1066#if defined(HAVE_SOFTWARE_UPDATE) && defined(Q_OS_WIN)
1067bool MainApplication::softwareUpdateCanShutdown() {
1068 software_update_ok_ = true;
1069 // At this point the update is ready to install, but WinSparkle has
1070 // not yet run the installer. We need to close our "Wireshark is
1071 // running" mutexes since the IsWiresharkRunning NSIS macro checks
1072 // for them.
1073 //
1074 // We must not exit the Qt main event loop here, which means we must
1075 // not close the main window.
1076
1077 // Step 1: See if we have any open files.
1078 emit softwareUpdateRequested();
1079 if (software_update_ok_ == true) {
1080
1081 // Step 2: Close the "running" mutexes.
1082 close_app_running_mutex();
1083 }
1084 return software_update_ok_;
1085}
1086
1087void MainApplication::softwareUpdateShutdownRequest() {
1088 // At this point the installer has been launched. Neither Wireshark nor
1089 // its children should have any "Wireshark is running" mutexes open.
1090 // The main window should still be open as noted above in
1091 // softwareUpdateCanShutdown and it's safe to exit the Qt main
1092 // event loop.
1093
1094 // Step 3: Quit.
1095 emit softwareUpdateQuit();
1096}
1097#endif
1098
1099void MainApplication::captureEventHandler(CaptureEvent ev)
1100{
1101 switch(ev.captureContext())
1102 {
1103#ifdef HAVE_LIBPCAP1
1104 case CaptureEvent::Update:
1105 case CaptureEvent::Fixed:
1106 switch (ev.eventType())
1107 {
1108 case CaptureEvent::Prepared:
1109 iface_mon_enable(true);
1110 break;
1111 case CaptureEvent::Started:
1112 active_captures_++;
1113 emit captureActive(active_captures_);
1114 break;
1115 case CaptureEvent::Finished:
1116 active_captures_--;
1117 emit captureActive(active_captures_);
1118 if (refresh_interfaces_pending_ && !global_capture_opts.restart) {
1119 refreshLocalInterfaces();
1120 }
1121 break;
1122 default:
1123 break;
1124 }
1125 break;
1126#endif
1127 case CaptureEvent::File:
1128 case CaptureEvent::Reload:
1129 case CaptureEvent::Rescan:
1130 switch (ev.eventType())
1131 {
1132 case CaptureEvent::Started:
1133 QTimer::singleShot(TAP_UPDATE_DEFAULT_INTERVAL3000 / 5, this, SLOT(updateTaps())qFlagLocation("1" "updateTaps()" "\0" "ui/qt/main_application.cpp"
":" "1133")
);
1134 QTimer::singleShot(TAP_UPDATE_DEFAULT_INTERVAL3000 / 2, this, SLOT(updateTaps())qFlagLocation("1" "updateTaps()" "\0" "ui/qt/main_application.cpp"
":" "1134")
);
1135 break;
1136 case CaptureEvent::Finished:
1137 updateTaps();
1138 break;
1139 default:
1140 break;
1141 }
1142 break;
1143 default:
1144 break;
1145 }
1146}
1147
1148void MainApplication::pushStatus(StatusInfo status, const QString &message, const QString &messagetip)
1149{
1150 MainWindow * mw = mainWindow();
1151 if (! mw) {
1152 return;
1153 }
1154
1155 MainStatusBar * bar = mw->statusBar();
1156 if (! bar) {
1157 return;
1158 }
1159
1160 switch(status)
1161 {
1162 case FilterSyntax:
1163 bar->pushGenericStatus(MainStatusBar::STATUS_CTX_FILTER, message);
1164 break;
1165 case FieldStatus:
1166 bar->pushGenericStatus(MainStatusBar::STATUS_CTX_FIELD, message);
1167 break;
1168 case FileStatus:
1169 bar->pushGenericStatus(MainStatusBar::STATUS_CTX_FILE, message, messagetip);
1170 break;
1171 case ByteStatus:
1172 bar->pushGenericStatus(MainStatusBar::STATUS_CTX_BYTE, message);
1173 break;
1174 case BusyStatus:
1175 bar->pushGenericStatus(MainStatusBar::STATUS_CTX_PROGRESS, message, messagetip);
1176 break;
1177 case TemporaryStatus:
1178 bar->pushGenericStatus(MainStatusBar::STATUS_CTX_TEMPORARY, message);
1179 break;
1180 }
1181}
1182
1183void MainApplication::popStatus(StatusInfo status)
1184{
1185 MainWindow * mw = mainWindow();
1186 if (! mw) {
1187 return;
1188 }
1189
1190 MainStatusBar * bar = mw->statusBar();
1191 if (! bar) {
1192 return;
1193 }
1194
1195 switch(status)
1196 {
1197 case FilterSyntax:
1198 bar->popGenericStatus(MainStatusBar::STATUS_CTX_FILTER);
1199 break;
1200 case FieldStatus:
1201 bar->popGenericStatus(MainStatusBar::STATUS_CTX_FIELD);
1202 break;
1203 case FileStatus:
1204 bar->popGenericStatus(MainStatusBar::STATUS_CTX_FILE);
1205 break;
1206 case ByteStatus:
1207 bar->popGenericStatus(MainStatusBar::STATUS_CTX_BYTE);
1208 break;
1209 case BusyStatus:
1210 bar->popGenericStatus(MainStatusBar::STATUS_CTX_PROGRESS);
1211 break;
1212 case TemporaryStatus:
1213 bar->popGenericStatus(MainStatusBar::STATUS_CTX_TEMPORARY);
1214 break;
1215 }
1216}
1217
1218void MainApplication::gotoFrame(int frame)
1219{
1220 MainWindow * mw = mainWindow();
1221 if (! mw) {
1222 return;
1223 }
1224
1225 mw->gotoFrame(frame);
1226}
1227
1228void MainApplication::reloadDisplayFilterMacros()
1229{
1230 dfilter_macro_reload(application_configuration_environment_prefix());
1231 // The signal is needed when the display filter grammar changes for
1232 // any reason (not just "fields".)
1233 mainApp->emitAppSignal(MainApplication::FieldsChanged);
1234}