12.2. The Qt Application Framework

Qt is a cross-platform application development framework. While we mainly use the core (QtCore) and user interface (QtWidgets) modules, it also supports a number of other modules for specialized application development, such as networking (QtNetwork) and web browsing (QtWebKit).

At the time of this writing (September 2016) most of the main Wireshark application has been ported to Qt. The sections below provide an overview of the application and tips for Qt development in our environment.

12.2.1. User Experience Considerations

When creating or modifying Wireshark try to make sure that it will work well on Windows, macOS, and Linux. See Section 12.3, “Human Interface Reference Documents” for details. Additionally, try to keep the following in mind:

Workflow. Excessive navigation and gratuitous dialogs should be avoided or reduced. For example, compared to the legacy UI many alert dialogs have been replaced with status bar messages. Statistics dialogs are displayed immediately instead of requiring that options be specified.

Discoverability and feedback. Most users don’t like to read documentation and instead prefer to learn an application as they use it. Providing feedback increases your sense of control and awareness, and makes the application more enjoyable to use. Most of the Qt dialogs provide a “hint” area near the bottom which shows useful information. For example, the “Follow Stream” dialog shows the packet corresponding to the text under the mouse. The profile management dialog shows a clickable path to the current profile. The main welcome screen shows live interface traffic. Most dialogs have a context menu that shows keyboard shortcuts.

12.2.2. Qt Creator

Qt Creator is a full-featured IDE and user interface editor. It makes adding new UI features much easier. It doesn’t work well on Windows at the present time, so it’s recommended that you use it on macOS or Linux.

To edit and build Wireshark using Qt Creator, open the top-level CMakeLists.txt within Qt Creator. It should ask you to choose a build location. Do so. It should then ask you to run CMake. Fill in any desired build arguments (e.g. -D CMAKE_BUILD_TYPE=Debug or -D ENABLE_CCACHE=ON) and click the Run CMake button. When that completes select BuildOpen Build and Run Kit Selector…​ and make sure wireshark is selected.

Note that Qt Creator uses output created by CMake’s “CodeBlocks” generator. If you run CMake outside of Qt Creator you should use the “CodeBlocks - Unix Makefiles” generator, otherwise Qt Creator will prompt you to re-run CMake.

12.2.3. Source Code Overview

Wireshark’s main entry point is in ui/qt/main.cpp. Command-line arguments are processed there and the main application class (WiresharkApplication) instance is created there along with the main window.

The main window along with the rest of the application resides in ui/qt. Due to its size the main window code is split into several modules, main_window.cpp, wireshark_main_window.cpp and wireshark_main_window_slots.cpp.

Most of the modules in ui/qt are dialogs. Although we follow Qt naming conventions for class names, we follow our own conventions by separating file name components with underscores. For example, ColoringRulesDialog is defined in coloring_rules_dialog.cpp, coloring_rules_dialog.h, and coloring_rules_dialog.ui.

General-purpose dialogs are subclasses of QDialog. Dialogs that rely on the current capture file can subclass WiresharkDialog, which provides methods and members that make it easier to access the capture file and to keep the dialog open when the capture file closes.

12.2.4. Coding Practices and Naming Conventions

12.2.4.1. Names

The code in ui/qt directory uses three APIs: Qt (which uses upper camel case), GLib (which uses snake_case), and the Wireshark API (which also uses snake_case).

As a general rule, for names, Wireshark’s Qt code:

  • uses upper camel case, in which words in the name are not separated by underscores, and the first letter of each word is capitalized, for classes, for example, PacketList;
  • uses lower camel case, in which words in the name are not separated by underscores, and the first letter of each word other than the first word is capitalized, for methods, for example, resetColumns;
  • uses snake case, in which words in the name are separated by underscores, and the first letter of the word is not capitalized, for variables, with a trailing underscore used for member variables, for example, packet_list_model_.

12.2.4.2. Dialogs

Dialogs that work with capture file information shouldn’t close just because the capture file closes. Subclassing WiresharkDialog as described above can make it easier to persist across capture files.

When you create a window with a row of standard “OK” and “Close” buttons at the bottom using Qt Creator you will end up with a subclass of QDialog. This is fine for traditional modal dialogs, but many times the “dialog” needs to behave like a QWindow instead.

Modal dialogs should be constructed with QDialog(parent). Modeless dialogs (windows) should be constructed with QDialog(NULL, Qt::Window). Other combinations (particularly QDialog(parent, Qt::Window)) can lead to odd and inconsistent behavior. Again, subclassing WiresharkDialog will take care of this for you.

Most of the dialogs in ui/qt share many similarities, including method names, widget names, and behavior. Most dialogs should have the following, although it’s not strictly required:

  • An updateWidgets() method, which enables and disables widgets depending on the current state and constraints of the dialog. For example, the Coloring Rules dialog disables the Save button if the user has entered an invalid display filter.
  • A hintLabel() widget subclassed from QLabel or ElidedLabel, placed just above the dialog button box. The hint label provides guidance and feedback to the user.
  • A context menu (ctx_menu_) for additional actions not present in the button box.
  • If the dialog box contains a QTreeWidget you might want to add your own QTreeWidgetItem subclass with the following methods:

    drawData()
    Draws column data with any needed formatting.
    colData()
    Returns the data for each column as a QVariant. Used for copying as CSV, YAML, etc.
    operator<()
    Allows sorting columns based on their raw data.

12.2.4.3. Strings

Wireshark’s C code and GLib use UTF-8 encoded character arrays. Qt (specifically QString) uses UTF-16. You can convert a char * to a QString using simple assignment. You can convert a QString to a const char * using qUtf8Printable.

If you’re using GLib string functions or plain old C character array idioms in Qt-only code you’re probably doing something wrong, particularly if you’re manually allocating and releasing memory. QStrings are generally much safer and easier to use. They also make translations easier.

If you need to pass strings between Qt and GLib you can use a number of convenience routines which are defined in ui/qt/utils/qt_ui_utils.h.

If you’re calling a function that returns wmem-allocated memory it might make more sense to add a wrapper function to qt_ui_utils than to call wmem_free in your code.

12.2.4.4. Mixing C and C++

Sometimes we have to call C++ functions from one of Wireshark’s C callbacks and pass C++ objects to or from C. Tap listeners are a common example. The C++ FAQ describes how to do this safely.

Tapping usually involves declaring static methods for callbacks, passing this as the tap data.

12.2.4.5. Internationalization and Translation

Qt provides a convenient method for translating text: Qobject::tr(), usually available as tr().

However, please avoid using tr() for static strings and define them in *.ui files instead. tr() on manually created objects like QMenu are not automatically retranslated and must instead be manually translated using changeEvent() and retranslateUi(). See ui/qt/wireshark_main_window.cpp for an example of this.

[Note]Note

If your object life is short and your components are (re)created dynamically then it is ok to use tr().

In most cases you should handle the changeEvent in order to catch QEvent::LanguageChange.

Qt makes translating the Wireshark UI into different languages easy. To add a new translation, do the following:

  • Run the following to generate/update your translation files:
lupdate -I. $(find ui/qt -name '*.cpp' -o -name '*.h' -o -name '*.ui') -ts ui/qt/wireshark_XX.ts
msginit --no-translator --input packaging/debian/po/templates.pot --output packaging/debian/po/hu.po
  • Add ui/qt/wireshark_XX.ts to ui/qt/CMakeLists.txt.
  • Add ui/qt/wireshark_XX.ts to .tx/config.
  • Translate with Qt Linguist: linguist ui/qt/wireshark_XX.ts.
  • Do a test build and make sure the generated wireshark_XX.qm binary file is included.
  • Push your changes to GitLab for review. See Section 3.10, “Contribute Your Changes” for details.

Alternatively you can put your QM and flag files in the languages directory in the Wireshark user configuration directory ($XDG_CONFIG_HOME/wireshark/languages/ or $HOME/.wireshark/languages/ on UNIX).

For more information about Qt Linguist see its manual.

You can also manage translations online with Transifex. Translation resources are organized by type of translation and development branch:

master
Qt Linguist resources in the ui/qt in the master branch.
debian
GNU gettext resources in the debian directory in the master branch.
qt-XY, master-XY
Qt Linguist resources in the ui/qt in the X.Y release branch. For example, qt-34 matches the Wireshark 3.2 release branch.
po-XY, debian-XY
GNU gettext (.po) resources in the debian directory in the X.Y release branch. For example, po-34 matches the Wireshark 3.4 release branch.

Each week translations are automatically synchronized with the source code through the following steps:

  • Pull changes from Transifex by running tx pull -f.
  • Run lupdate on the ts files.
  • Push and commit on GitLab.
  • Push changes to Transifex by running tx push.

12.2.4.6. Colors And Themes

Qt provides a number of colors via the QPalette class. Use this class when you need a standard color provided by the underlying operating system.

Wireshark uses an extended version of the Tango Color Palette for many interface elements that require custom colors. This includes the I/O graphs, sequence diagrams, and RTP streams. Please use this palette (defined in tango_colors.h and the ColorUtils class) if QPalette doesn’t meet your needs.

Wireshark supports dark themes (aka “dark mode”) on some platforms. We leverage Qt’s dark theme support when possible, but have implemented our own support and workarounds in some cases. You can ensure that your code includes proper dark theme support by doing the following:

  • You can use a macOS-style template icon by creating a monochrome SVG document with “.template” appended to the name, e.g. resources/stock_icons/24x24/edit-find.template.svg.
  • Qt draws unvisited links Qt::blue no matter what. You can work around this by using ColorUtils::themeLinkBrush() and ColorUtils::themeLinkStyle().
  • You can catch dark and light mode changes by handling QEvent::ApplicationPaletteChange.

12.2.5. Other Issues and Information

The main window has many QActions which are shared with child widgets. See ui/qt/proto_tree.cpp for an example of this.

To demonstrate the functionality of the plugin interface options, a demonstration plugin exists (pluginifdemo). See doc/README.plugins and plugins/epan/pluginifdemo.

GammaRay lets you inspect the internals of a running Qt application similar to Spy++ on Windows.