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 (February 2015) we are in the process of porting the main Wireshark application to Qt. The sections below provide an overview of the application and tips for Qt development in our environment.

12.2.1. Source Code Overview

Wireshark’s main entry point is in wireshark-qt.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 two modules, main_window.cpp and 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 sublcass 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.2. Coding Practices and Naming Conventions

12.2.2.1. Names

The code in ui/qt directory uses three APIs: Qt (which uses InterCapConvention), GLib (which uses underscore_convention), and the Wireshark API (which also uses underscore_convention). As a general rule Wireshark’s Qt code uses InterCapConvention for class names, interCapConvention for methods, and underscore_convention for variables, with a trailing_underscore_ for member variables.

12.2.2.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.2.3. Strings

If you’re using GLib string functions or plain old C character array idioms in Qt-only code you’re probably doing something wrong. 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/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.2.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.2.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 summary_dialog.[ch] 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 to use tr().

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

12.2.3. Other Issues

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