QUIP 13: Qt Examples

by Kai Köhne Edward Welbourne

Details

  • Number: 13
  • Title: Qt Examples
  • Author: Kai Köhne Edward Welbourne
  • Status: Active
  • Type: Informational
  • Post History: 034338.html , 044467.html , 045052.html
  • Created: 11 October 2022

Overview

Examples in the Qt Framework show a particular aspect of Qt. They consist of source code and documentation.

Examples should be concise. But be aware that users often use them as a starting point, so they should avoid the use of anti-patterns.

Directory Layout

Each git repository should have an examples/ directory that contains subdirectories matching the Qt modules or tools in the repository.

For instance, qtdeclarative.git has:

examples/qml
examples/quick
...

Each subdirectory may, in turn, group examples into a directory hierarchy.

Note that installers merge the example directories from different git repositories. Therefore, the relative path of an example within the respective examples directory and the example name should be unique.

Alternatively, examples can be hosted in the examples/ directory of qtdoc.git Such examples can use all Qt modules, regardless of the build order.

Structure

The source directory of an example must be self-contained. It should be possible to build either within the source tree, or when copied out to another directory.

Each example should be documented. This is usually done in a doc/ subdirectory of the example.

Building

An example should feature a top-level CMakeLists.txt file that can be opened and built in Qt Creator without further configuration. If this is not possible, the example should prominently state the preconditions to configure and build it.

The configuration and build steps should be warning free on all supported platforms.

Examples can also feature a top-level .pro file that allows building the example with qmake, or a .qmlproject file if the example can be launched from within Qt Design Studio. This is optional though.

Launching

An example should launch from Qt Creator without any further actions necessary. In the few cases where this is not possible, the example should prominently state the steps required to try out the example.

File Naming

If the example has a C++ entry point, it should be in the file main.cpp. Try to keep this as simple as possible: Most users have understood that main() is usually dull and seldom take time to read it.

For Qt Quick examples, the .qml file that contains the QML entry point and a .qmlproject file should be named the same as the directory.

Coding Style

Example code should wrap at 80 characters because it’s often quoted in the documentation. Otherwise examples should follow the general Qt coding style, with some exceptions:

C++

C++ includes should use the camel-case class name notation, for example:

#include <QCoreApplication>

not:

#include <QtCore/QCoreApplication>
#include <qcoreapplication.h>

Rationale: Not including the module name allows easier portability between Qt major versions, where classes and API are sometimes moved to new modules. Also, failing to add a Qt module to the project file will result in a compile error, which is usually easier to understand than a linker error.

In C++, signals and slots keywords are preferred over their Q_SIGNAL, Q_SLOT variants.

CMake

Name the top level project the same as the example, but without spaces.

That is, if the example is called Coffee Machine, the project() call should be e.g.:

project(CoffeeMachine VERSION 1.0 LANGUAGES CXX)

The main target should be the same, but lowercase without spaces:

qt_add_executable(coffeemachine ...)

For macOS app bundles, this can then be tweaked to the full name:

if(APPLE)
    set_target_properties(coffeemachine PROPERTIES
        OUTPUT_NAME "Coffee Machine"
        MACOSX_BUNDLE TRUE
        ...

Comments

Keep comments in source code minimal. Documentation and explanations belong in the example’s exposition.

You can use snippet markers for documentation purposes, though.

Conditional Compilation

Use the preprocessor exclusively to protect against multiple inclusion of header files. In particular, do not use the Qt feature system to disable parts of an example because the individual features are currently not part of the public API. Instead, the build system should skip examples that do not have required dependencies.

Namespaced Qt

Qt examples need to compile also with Qt versions configured with a custom namespace (configure -qt-namespace). However, the macros that enable forward declaring Qt types - QT_BEGIN_NAMESPACE, QT_END_NAMESPACE, QT_FORWARD_DECLARE_CLASS - are internal macros that are not supposed to be used in customer code. Avoid using these, even if this means you need to include an otherwise optional Qt header file.

Application Settings

Examples should store their custom settings in a common QtProject scope so that the settings do not litter the user settings too much. This is usually done by calling:

QCoreApplication::setOrganizationName("QtProject");

in main.cpp.

Licenses and Third-Party Assets

Examples should be made available under the Commercial/BSD 3 clause license:

// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

Code or assets (including images) from third-party sources must be explicitly documented. See QUIP-4 for the details.

References