Friday, November 30, 2012

Qt GUI Files and CMake

Previously, new header or source files were added to the list of header and source files in the CMake build file CMakeLists.txt.  Qt form files (with the .ui extension) and header files containing the Q_OBJECT macro are handled differently.

The Q_OBJECT macro is added to any class definition that contains Qt's C++ extensions for defining signals and slots, which are class sections in additional to the normal private, public and protected sections.  These are handled by Qt's Meta-Object Compiler (moc), which produces a special MOC source file from the header file.  For mainwindow.h, the special source file produced is moc_mainwindow.cxx, which then gets compiled and linked into the program.

In the CMake build file, this is handled by the qt4_wrap_cpp command that is added as part of the Qt4 CMake module.  It is given a list of MOC source files and produces a list of MOC output source files.  This output list is then specified as a dependency to the output executable.  When a header file is included in the MOC sources list, it does not also need to be specified in the list of [normal] header files.

Qt form files are generated as an XML like language.  This file needs to be converted into a class definition (within a header file) so that it can be used by the C++ code.  These conversions are handled by Qt's User Interface Compiler (uic), which produces a special header file from the form file.  For mainwindow.ui, the special header file produced is ui_mainwindow.h, which contains the Ui_MainWindow class.  This source file is then included by the mainwinow.h header file.

In the CMake build file, this is handled by the qt4_wrap_ui command.  It is given a list of form UI files and produces a list of user interface header files.  This output list is then specified as a dependency to the output executive.

All of the generated files are placed in the CMake build directory, the same directory where the auto-generated header files (from the awk scripts) are placed.  This directory (the project binary directory) is specified in the include_directories command, so that the C++ compiler can find all of these generated files.  It is also no longer necessary to specifically check for an in-source build to not add this directory because the conflict no long exists between the system string.h header file (not used) and project string.h header file (removed).

[commit f4a35bbab6] [commit 266022803b]

Initial Main Window Implementation

The instance and running of the CommandLine class was moved from the main function to the constructor of MainWindow.  A flag was added to the MainWindow class to indicate when the GUI is active (along with an access function).  If the command line instance reports that the arguments have been processed, this flag is set to false.  Otherwise (later), the GUI is setup and this flag is set to true.

In the main function, after the MainWindow is instanced (as a local variable), if the GUI is not active, a value of 0 (indicating no error) is returned.  It is not necessary to have a single shot timer to force the event processing loop to exist immediately - simply returning before starting the event loop is sufficient.

The MainWindow class definition starts with the Q_OBJECT macro.  Essentially this allows the use of signals and slots, which is a mechanism used by Qt to allow classes to communicate with each other.  More on this later when these get implemented, but for now, the MainWindow class does not contain any of these, but will as the GUI is developed.  Details about how these Qt GUI files are built with CMake in the next post.