The Book C++ GUI Programming with Qt 4 by Jasmin Blanchette and Mark Summerfield was the definitive book on Qt back when it was published in 2006. It was an update to the earlier C++ GUI Programming with Qt 3 by the same authors that came out in 2004. The book contains many Qt example programs, mostly focusing on desktop platforms although there was some coverage of Qt on embedded (which at the time was called Qtopia) and of course this all predated the introduction of QML a few years later.
Back when Qt 5 came out, I spent some time porting the examples to Qt 5 as an exercise in learning. This turned out to be quite straightforward, and I wrote a blog post on the topic in 2013. With Qt 6 now out and at feature parity with Qt 5, I revisited this and looked at what was needed to port the examples to Qt 6.
The examples include about 60 applications totaling about 14,000 lines of C++ code.
To start, I used the recommended approach of trying to build the code with Qt 5.15 (I used 5.15.7) and fixing any deprecation warnings. For the most part, APIs that were removed or changed in Qt 6 are flagged in Qt 5.15 as being deprecated. Because this code was originally ported to quite an early version of Qt 5, there were some changes needed to address deprecation warnings. In most cases the compiler warnings made it clear what needed to be done. Here are a couple of examples (this was on desktop Linux using the gcc compiler):
main.cpp:25:73: warning: ‘QStringList QString::split(QChar, QString::SplitBehavior, Qt::CaseSensitivity) const’ is deprecated: Use split(QChar sep, Qt::SplitBehavior ...) variant instead
plotter.cpp:223:26: warning: ‘void QPainter::initFrom(const QPaintDevice*)’ is deprecated: Use begin(QPaintDevice*) instead
In cases where it was not obvious from the compiler warning what needed to change, a quick look at the Qt documentation usually clarified what the issue was. Some changes were more involved but still not difficult, such as converting any use of the QRegExp class to the newer QRegularExpression class.
Once it built cleanly under Qt 5.15.7, I switched to Qt 6.2.2, and made a few more changes to get the code to successfully build and the examples to run. Some of the highlights of areas where I needed to make changes were:
- QVariant type() is now typeId() and returns different values, e.g. QMetaType::QString rather than QVariant::String.
- QMessageBox methods like warning() now use methods which take QMessageBox::StandardButtons parameters (these were originally added in Qt 4.2, so it is not a recent change).
- Some OpenGL class changes: glClearColor() takes different arguments, updateGL() is now update().
- QMouseEvent x() and y() now use position().x() and position().y().
- QDrag uses exec() rather than start().
- QRegExp had support for wildcard (globbing) and fixed string matching. While these features were probably not often used, the QRegularExpression class does not directly support them.
- Some (strange) code was using operator+ on a QMap to simulated indexing. I used an iterator to get to specific elements instead.
- QDirModel should use QFileSystemModel instead.
- QTreeWidget sortByColumn() takes different arguments.
- endl should explicitly use Qt::endl.
- QString split() takes different parameters, e.g. Qt::SkipEmptyParts rather than QString:SkipEmptyParts.
One example used the QXmlSimpleReader class, which was removed in Qt 6. The alternative class is QXmlStreamReader, but there wasn't much point in porting to it since the purpose of the program was to illustrate how to use QXmlSimpleReader. Another XML example used the class QXmlDefaultHandler which is not in Qt 6 proper but is available in the Qt 5 Core Compat (compatibility) module which is provided with Qt 6 to facilitate moving code from Qt 5 to 6. Using this class provided a quick way to get the application running under Qt 6.
While you are working on the code to fix compile errors and warnings, it can also be a good opportunity to review and fix any warnings in Qt Creator from the Clang-Tidy and Clazy static code analyzers to ensure you are following C++ and Qt best practices.
In Qt 6, the process of building Qt itself now uses CMake. Using qmake is still supported, but CMake has become an industry standard, offers a number of advantages, and is recommended for new Qt projects. For bonus points I created project files to build the examples with CMake. It was a straightforward, but manual, process. I essentially copied a typical Qt CMakeLists.txt file and edited it to set the project name and list of source files for each project.
If you need to convert qmake projects to CMake, you may want to explore the pro2cmake.py conversion script that is part of the Qt 6 source release. See this link for more details.
While these code examples were mostly aimed at desktop applications and don't include QML, porting them to Qt 6 was quite straightforward and validated the claim that Qt 6 is almost fully source code compatible with Qt 5.15 if you avoid the use of deprecated classes and methods. Maybe your New Year's resolution for 2022 can be to port all your code to Qt 6!
If you liked this blog, you may be interested in How to Build Qt6.2.0 from Source on Ubuntu Linux.