Shadowrun: Awakened Forums
Welcome, Guest
 
  Site Forums   Wiki   Bugs Tasks Code Docs Help Register Login  
    Page   Discussion         View source History  

QT

From Shadowrun: Awakened

Jump to: navigation, search

QT is a cross-platform application development framework. For Shadowrun Awakened, it is used as our GUI toolkit for applications requiring a standard window-based user interface, such as our content tools.

Contents

How will we use QT?

QT is an expansive set of libraries that provide support for front-end windows & widgets, concurrency, networking, and databases. While this is a great sign of maturity that should not be ignored, we will primarily be using QT for its GUI capabilities. Consequently, we currently only use three libraries from QT: QtCore, QtGui, and QtOpenGL.

Using QT's flexibility, it is possible to directly embed an OGRE render window into a running QT application. This allows us to bring in all the functionality from our libraries (include PhysX), meaning QT can easily integrate as a direct window into our system with all the features of a standalone OGRE application. QT's system of widgets will offer a means to manipulate our system using standard user-interface paradigms, increasing usability and minimizing the dependence on in-game quality GUI components.

QT is available as either a commercial product or GPL open source version. We are using the Open Source edition. Regrettably, there are no compiled binaries distributed by TrollTech for this version. This means that if you are using a system not support by the binaries already present in the SVN, you must download the Open Source Edition of QT and compile your own binaries. This process is esoteric, but not difficult, please patiently read the QT website as it answers most every question.

Using QT

As all libraries, QT has some concepts a programmer must be conversant with before they can build and interact with the code. QT does have a rather peculiar reliance on code generation that can be esoteric; however, the minimal use of QT in our applications means that the average programmer needs only awareness, not complete understanding.

QT Classes

QT's libraries provide a myriad of classes for performing various types of work. Primarily, the classes used in our applications encapsulate the duties of single widgets or their actions. Any programmer with previous experience in UI toolkits will recognize the object-oriented approach to describing interface components.

Much of the functionality in QT can be modified by overriding functions in child classes. For instance, the mouse input to a widget can be acted upon by overriding corresponding functions and providing your own behavior.

Signals & Slots

One not so immediate concept is the idea of signals and slots. The concept is used to encapsulate the idea of event-driven callback in the user-interface (EG translating a menu click into calling a function of a class). In this case, a "signal" is an event that is sent out from an object. A "slot" is a function that is called when that event is emitted. Slots are connected to signals during initialization to link the functionality.

Programmers familiar with .Net forms might understand it through this analogy: signals are like event members of a class and slots are the delegates that hook up to events. Like .Net, QT has some support for multi-casting and support type-safety.

Meta-Object Compilation

To support the system of signals & slots described above, QT provides a mechanism of introspection/reflection through an outside tool it calls the "Meta-Object Compiler" (or MOC). This "compiler" is really a code generator that can read C++ code files (primarily header files) and generate code that provides a meta-data available to QT at runtime.

The Meta-Object Compiler is dependent upon the programmer using certain Macros in their code that provide information to the MOC. All classes run through the MOC must contain the "QOBJECT" Macro. Signals & slots each use their own "Q_SLOTS" and "Q_SIGNALS" macros to indicate the block of signal and slot declarations in a class. NOTE: The QT documentation sometimes provides these as looking like standard language text (EG instead of using "protected Q_SIGNALS:" they use "protected signals:". Examination of the QT header files shows the conventional method of using the macros, which the C++ compiler appreciates as well.

Again, this system of using Macros and the MOC is best viewed through the lens of .Net which already implements reflection. QT's MOC is providing the code and information that .Net assemblies provide, except they are doing it entirely in native C++ without any language changes. Code decorated with QT macros and generated from the MOC are treated the same as standard C++ code because they ARE standard C++ code.

The meta-data system is, on the surface, somewhat intimidating; however, just remember it is a means of generating new code that describes your existing code. It can be very educational of anyone who has wondered how .Net reflection works as this is a working example.

Memory Management

QT applications have a special means of managing the memory of their components. The client application need only manage the allocation and deletion of the parent-most GUI container in the application (EG a QMainWindow instance). During initialization, the GUI is constructed by creating instances of classes with the "new" operator; however, in the case of GUI components derived from QWidget and added into the GUI as children of existing components, it is not necessary to ever call "delete". When the parent-most object is deleted by your application, its child objects will be recursively deleted, meaning you only ever need to manage the parent-most object in your application.

This quality means that if you DO try to manage the memory of an object that is a child of a QWidget object, you can cause runtime errors and crashes. This even goes for objects managed by scoping (EG declaring a variable that is a QWidget child then adding it as a child, then relying upon the variable's scope to clean it up). The QWidget parent will still try to call "delete" on it during cleanup. This means that while the parent-most object of the application can be memory-managed using scope, ALL CHILD OBJECTS MUST BE ALLOCATED BY A "NEW" STATEMENT OR THE APP MAY CRASH WHEN IT TRIES TO CLEAN UP RESOURCES.

NOTE: Instances of classes like "QIcon" or "QString", which are used to set properties but are NOT children of QWidget and are never made into children of any QWidget objects still need to have their memory managed by your code.

Using QT in our project

In our project, a limited number of applications will be using QT. In those applications, only a limited number of classes will need to use the Meta-Object Compiler. For all classes using the MOC, they do so using the following procedure:

  • The header files must contain ONLY declarations; all working code must go into a corresponding .cpp (that file is NOT used by the MOC)
  • The class must include the "QOBJECT" macro within the class definition, within the header file
  • The class may use other macros, such as "Q_SLOTS" & "Q_SIGNALS" in the header file
  • The class is then run through the MOC using a pre-build step
    • This is done by running the following command line: moc "<filename>" -o "<outputfilename>"
    • The output file type should be .cpp
    • The output file name should be the same as the header with the letter "MOC" after it (EG "Editor.h" will create an MOC file named "EditorMOC.cpp". This is to indicate it is a generated file, it is not a strict technical requirement of the process.
    • The output file should be kept in the project's "Src" directory along with all other .cpp files for the project
  • The resulting .cpp file is added to the project along with all other source code (so it will be compiled alongside the class declaration and definition; the pre-build step will regenerate it at build time)

After the above guidelines have been adhered to, the class's meta-data will become available to QT when you run your application and you will be able to perform such tasks as utilize signals and slots.

External Links

Sponsored Links