Getting your 3D ready for Qt 6

As was previously discussed, since the 6.0.0 release of Qt, Qt 3D no longer ships as a pre-compiled module. If you need to use it on your projects, try out the new features, or just see your existing application is ready for the next chapter of Qt’s life, you need to compile Qt 3D from source.

In order to do this, you can do it the traditional way ([cq]make ...; make; make install) or use the Conan-based system that is being pioneered with the latest version of the MaintenanceTool.

Using Conan

The latest version of the MaintenanceTool (from the unified installers) will optionally install several things:

  • Conan, a package manager which can build C++ libraries and handle the dependencies
  • CMake, the meta-build system, which is required for Qt 6
  • Ninja, the lighting fast replacement for make and nmake

Additionally, you will need to select Qt 3D in the Additional libraries section so that the source code is available.

As mentioned above, these are optional. You need to find them and enable them in the MaintenanceTool’s UI.

 

Conan, being a package manager, is designed to handle all dependencies to make it easy to build libraries and applications. However, the way this is setup in the current packages installed by the MaintenanceTool is not complete.

Additional things you need for Conan

In particular, you need two other things:

  • You need to select the Qt Shader Tools module in the MaintenanceTool, if you intend to use the new RHI-based backend for Qt 3D. Without it, Qt 3D will build fine but only the original (and more feature rich) backend will be available.
  • Since Qt 3D is a Qt module, it has many of the similar requirements you need when building Qt itself. At the very least, you need a perl interpreter, so that the module header files can be generated. A full list of requirements for the various platforms is available here.

Once you have all the required bits, it’s time to open a console and run Conan. The process is platform-specific, as each platform has it’s own Conan profile. A complete example is available on the Qt wiki, but this is how it works on my mac where the Qt SDK is installed in /Users/Shared/Qt:

conan install qt3d/6.0.0@qt/final --build=missing -s build_type=Release -g cmake_paths -g=cmake -g deploy --profile=/Users/Shared/Qt/Tools/Conan/profiles/qt-6.0.0-macx-clang

and wait…it takes a while to build Qt 3D.

Notes:
  • conan, cmake and ninja need to be in your path. In particular, make sure the Qt provided version of Conan is found first, because…
  • the MaintenanceTool installs a custom version of Conan and write config files in the $HOME/.conan folder. This means, at least on multi-user systems, Conan will only properly work for the user who installed the Qt SDK, and that version is found before any platform-provided version.

 

Using QMake or CMake

Using the MaintenanceTool and Conan makes it easy to get the source and the required dependencies for building Qt 3D. As we saw in the aforementioned, there are still some rough edges. So, in particular, if you are familiar with building Qt modules already, you can just use the “old way”, i.e., download the source and use QMake, or now, CMake.

The packages for the released versions of Qt 3D (and other Additional modules) are available here.

QMake

Once extracted, you can do a shadow build of Qt 3D pretty easily (this has the same build requirements as above though, QtShaderTools module and perl interpreter).

tar zxf qt3d-everywhere-src-6.0.0.tar.xz
cd qt3d-everywhere-src-6.0.0
mkdir build
cd build
/Users/Shared/Qt/6.0.0/clang_64/bin/qmake ..
make
make install

And, again, wait 🙂.

CMake

The process is similar if you want to use CMake instead. In the build folder, do:

/Users/Shared/Qt/6.0.0/clang_64/bin/qt-cmake -G Ninja ..
ninja
ninja install

Once done, your applications should be able to find the Qt 3D modules.

You can optionally build the documentation using the docs target (but this will not be installed; you will need to register it with Creator and/or QtAssistant for it to appear).

Note:

Qt 3D will likely preserve the dual QMake/CMake build system for a while still.

Conclusion

As you see, building Qt 3D involves a bit more work than it did before. Fortunately, it needs to be done only once for each release. Going forward, we will be able to release Qt 3D on a different cycle from the rest of Qt and, as a result, introduce features and bug fixes more frequently. Please do not hesitate to get in touch with us or the Qt build system team if you have questions regarding this new setup.

 

KDAB provides a number of services around Qt 3D, including mentoring your team and embedding Qt 3D code into your application, among others. You can find out more about these services here.

 

About KDAB

If you like this blog and want to read similar articles, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post Getting your 3D ready for Qt 6 appeared first on KDAB.

Problem with Open-source Downloads

Open-source downloads are currently unavailable due to a severe hardware failure at our cloud service provider. This affects both the online installer as well as the offline packages. Commercial downloads are unaffected, because they use a different service provider. 

Simple-Mail Qt library 2.3 released

SimpleMail is a small Qt library for sending mails, this release makes sure it compiles fine with Qt6, and has some small issues fixed.

I thought this would give me a bit of work but was mostly changing CMakeLists.txt and including one header.

This week I'll start working for KDAB :) and my first task will be porting one app to Qt6, so I decided to do a little of homework and port my own stuff first as you might have noticed (Cutelyst and ASql).

https://github.com/cutelyst/simple-mail/releases/tag/v2.3.0

Cutelyst 2.14.2 and ASql 0.27 released!

Cutelyst a Qt Web Framework and ASql an asyncronous SQL library for Qt got new releases.

The Cutelyst version 2.14.0 was made in December but was a silent one, I had some issues in production but weren't related to Cutelyst, the .1 release included some contributions by Adriaan de Groot, I also did some changes for Qt 5.15 and Qt6 but for Qt6 a new major version is needed.

Besides a bunch of fixes, a major regression on the plaintext benchmarks got fixed, unfourtunately not in time for round 20, but thanks to ASql you will Cutelyst got a better scoring on SQL related benchmarks

ASql also got a bunch of bug fixes, but most importantly it's now Qt6 ready.

And speaking of Qt6 Cutelyst port is also completed now, after I port most of my own apps I'll do a v3 release which is compatible with both Qt5 and 6.

Have fun!

https://github.com/cutelyst/asql/releases/tag/v0.27.0

https://github.com/cutelyst/cutelyst/releases/tag/v2.14.2

How to customize installer UI with Qt Installer Framework

In the previous post you learned the basics of the app deployment process and installer generation. However Qt Installer Framework offers much more than that! What more can you do with this tool? For example, you can customize an installer UI in many different ways and this is what you will learn in this post. Before going any further, let’s answer one important question. Why do that?

Look and feel of the app is just as important as performance and usability. This is no secret that users pay attention to the look of the software they are using – this is why frontend developer is as important role as backend one. This is also the reason to find out how to turn generic looking tool into user-friendly eye-candy. Before we do that, let’s start with the basics.

Icons customizations 

There are few ways to customize your installer: creating component scripts, adding a control script or modifying config.xml file. You should already know the last position in this list from the previous blog post, so we will discuss it first.

Configuration file contains a set of XML tags which can modify installer behaviour and look. There are plenty of tags, so we will take a closer look only at a few of them. First, something easy – adding custom icon for the installer window and executable file.

To set window icon, all you need to do is to add InstallerWindowIcon tag containing name of the PNG file and place it in config folder. Adding custom icon for installer executable, looks almost the same, but in this case you use InstallerApplicationIcon tag. However the format of the file is system dependent, so it is a .icns for macOS and .ico in case of Windows. Sadly this tag is not supported on Unix. Name of the icon in InstallerApplicationIcon tag should omit file type, as the generator handles deciding what type of icon to use. Also remember that icons shouldn’t be too big – sometimes installer generator omits such icons. In case of Windows, 128×128 works fine for me. Using the configuration file from the previous post, after applying the mentioned changes its content should look as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Installer>
    <Name>APP NAME</Name>
    <Version>1.0.0</Version>
    <Title>INSTALLER WINDOW TITLE</Title>
    <Publisher>Scythe Studio</Publisher>
    <StartMenuDir>START_MENU_DIR</StartMenuDir>
    <TargetDir>@HomeDir@/APP_DIR</TargetDir>
    <InstallerWindowIcon>logo.png</InstallerWindowIcon>
    <InstallerApplicationIcon>installericon</InstallerApplicationIcon>
</Installer>

After generating the new installer file for Windows, we should see that everything works as expected:

Installer with custom icon

Styling 

Now you have some custom icons, but the installer still looks quite generic. What you can do with the config file to change that? The answer is – add some style sheets!

Qt Style Sheets is a tool from Qt Widgets module that is used to customize the appearance of widgets. The concepts, terminology, and syntax are heavily inspired by HTML Cascading Style Sheets (CSS) but adapted to the world of widgets. It is also very similar to QML syntax. As the Qt Installer Framework is based on the Qt Widgets module, we can also use style sheets to modify the appearance of installers.

To add style sheet to your installer, simply create style.qss file in config directory and add StyleSheet tag to config.xml. You can also add one additional tag to make things even better – WizardStyle. This tag changes the layout of the installer. I suggest going with „Modern” style, as in case of Windows it will get rid of white border around content of installer which will be annoying at this point of customization. Now config.xml should look similar to code below:

<?xml version="1.0" encoding="UTF-8"?>
<Installer>
    <Name>APP NAME</Name>
    <Version>1.0.0</Version>
    <Title>Qt Installer Tutorial</Title>
    <Publisher>Scythe Studio</Publisher>
    <StartMenuDir>START_MENU_DIR</StartMenuDir>
    <TargetDir>@HomeDir@/APP_DIR</TargetDir>
    <InstallerWindowIcon>logo.png</InstallerWindowIcon>
    <InstallerApplicationIcon>installericon</InstallerApplicationIcon>
    <WizardStyle>Modern</WizardStyle>
    <StyleSheet>style.qss</StyleSheet>
</Installer>

Style sheet provided in config directory is empty, so it won’t change anything. Open the style.qss file and you can change almost any part of the appearance – how to do that? Like in case of CSS you declare a scope (or in this case a widget) that is supposed to be customized. For example if you want to change window background, you create QWidget scope, just like that:

QWidget
{
    color: white;
    background-color: rgb(61, 56, 56);
}

What about adding some more color to installer? Let’s use our favourite green shade and radius property to make buttons stand out more.

QPushButton
{
    background-color: rgb(36, 159, 123);
    border-style: solid;
    border-width: 1px;
    border-color: rgb(61, 56, 56);
    border-radius: 5px;
}

You can also add state dependent styling. In case of button, we can change its color to some linear gradient when it is pressed or checked.

QPushButton:pressed, QPushButton:checked
{
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgba(36, 159, 123, 60%), stop:1 rgba(19, 85, 64, 60%));
}

There are plenty of ways to modify each widget, so we will not discuss every option here. If you want to learn more about style sheets see the documentation page dedicated to Qt Style Sheets and the one containing examples of customization of each item. With some other minor modifications style.qss contain following code:

QWidget
{
    color: white;
    background-color: rgb(61, 56, 56);
}

QPushButton
{
    background-color: rgb(36, 159, 123);
    border-style: solid;
    border-width: 1px;
    border-color: rgb(61, 56, 56);
    border-radius: 5px;
    min-height: 25px;
    max-height: 25px;
    min-width: 60px;
    padding-left: 15px;
    padding-right: 15px;
}

QPushButton:pressed, QPushButton:checked
{
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgba(36, 159, 123, 60%), stop:1 rgba(19, 85, 64, 60%));
}

QProgressBar
{
    text-align: center;
}

QProgressBar::chunk
{
    background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgba(36, 159, 123, 60%), stop:1 rgba(19, 85, 64, 60%));
}

With this style sheet applied installer should look like this:
Installer with customized apperanceNotice that changes in appearance don’t affect only an installer, but also maintenance tool:

Maitnance tool with customized apperance

This is already some major change, but we are not done yet. What else you can do to push things event further? What about adding some custom pages using scripts?

Scripting 

We haven’t touched the topic of Scripting API, from Qt Installer Framework yet, so at the beginning let’s explain what this is.

It is basically set of JavaSctipt objects that you can use to create scripts, which are placed in .qs files executed by QJSEngine. You can use them to interact with certain parts of the installer’s UI or its functionality. In the case of installers there are two types of scripts: controller scripts and component scripts. In this entry we will focus on component scripts, while controller type will be covered in detail in the next entry. Component scripts are used to handle behaviour for selected component in the installer, so each component can have its own script.

Before going any further with scripting you need to create your page and register the .ui file first. Now create your own widget class in .ui file. As an example we will use CustomPage class containing following code:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>CustomClass</class>
 <widget class="QWidget" name="MyPage">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>532</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Custom Page</string>
  </property>
  <layout class="QHBoxLayout" name="horizontalLayout">
   <item>
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QRadioButton" name="radioButton">
       <property name="locale">
        <locale language="English" country="UnitedStates"/>
       </property>
       <property name="text">
        <string>OptionA</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QRadioButton" name="radioButton_2">
       <property name="locale">
        <locale language="English" country="UnitedStates"/>
       </property>
       <property name="text">
        <string>Option B</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QRadioButton" name="radioButton_3">
       <property name="locale">
        <locale language="English" country="UnitedStates"/>
       </property>
       <property name="text">
        <string>Option C</string>
       </property>
      </widget>
     </item>
    </layout>
   </item>
   <item>
    <widget class="Line" name="line">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QTextBrowser" name="textBrowser">
     <property name="html">
      <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;h3 style=&quot; margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:large; font-weight:600;&quot;&gt;Who are we?&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:medium; font-weight:600;&quot;&gt;We are group of software enthusiasts for whom your satisfaction is the most important.&lt;/span&gt;&lt;/h4&gt;
&lt;h4 style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:medium; font-weight:600;&quot;&gt;Our goal is to provide only high quality software which means that we want create easily managed, well documented and effortlessly maintainable software. We work in our productive scheme which is always additionally adjusted by specification of your project. We believe that there is nothing impossible in the case of software development.&lt;/span&gt;&lt;/h4&gt;&lt;/body&gt;&lt;/html&gt;</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

Custom widget

 

For purpose of page register process we will use qtinstallertutorialx64 package, created in previous post. To add custom page inside package.xml file you have to add UserInterfaces tag containing list of UserInterface tags where each hold name of the file to register. Don’t forget to place registered .ui files inside meta folder! Such a list of files should look similar to this:

<UserInterfaces>
 <UserInterface>CustomPage.ui</UserInterface>
</UserInterfaces>

In order to add a first script to your installer you need to add Script tag, containing name of the .qs file, to package.xml file. Different scripts can be added to every package in your installer. At this point package.xml content should be following:

<?xml version="1.0" encoding="UTF-8"?>
<Package>
    <DisplayName>PACKAGE NAME 64-bit</DisplayName>
    <Description>This is going to install APP NAME on your machine</Description>
    <Version>1.0.0</Version>
    <ReleaseDate>2020-06-17</ReleaseDate>
    <Licenses>
        <License name="LICENSE TITLE" file="license.txt" />
    </Licenses>
    <Default>true</Default>
    <Script>installscript.qs</Script>
    <UserInterfaces>
        <UserInterface>CustomPage.ui</UserInterface>
    </UserInterfaces>
</Package>

Now you can begin writing the script. The script has to contain a Component object that the installer creates when it loads the script. To add a single custom page, script containing only a Component() function would be enough. To achieve this you have to use addWizardPage function called from installer global object. Take a look at the code of the final script:

function Component()
{
    installer.addWizardPage(component, "CustomPage", QInstaller.ReadyForInstallation);
}

Function that adds new page takes three parameters. First is the component which contains the registered name of the widget class you want to add – in this case a global component object referencing the current Component was passed. Next argument is the name of the registered widget class you want to use. Last is the index of the existing page before which new page will be placed. In this case CustomPage would be placed before ReadyForInstallation page.

Notice that name passed in addWizardPage function have to be the same as name of the root widget object created in .ui file and does not correspond with the .ui file name! For example if you change name of the widget object in CustomPage.ui file to MyOtherPage, you have to pass „MyOtherPage” to addWizardPage, although the name of the file in UserInterface tag remains the same.

<widget class="QWidget" name="MyOtherPage">
function Component()
{
    installer.addWizardPage(component, "MyOtherPage", QInstaller.ReadyForInstallation);
}

At this point we won’t be adding more functions or connect any signal and slots, as this will be covered in detail in the next entry of this series. After generating and running the new installer, you can see the results of the attached script:

Installer with custom page 

Translating 

As you already guessed my system language is not English, so default elements of the installer are translated, while the custom ones are not. To fix that Qt Translation system can be used.

Everything begins with preparing strings for translation. If you created your .ui file using Qt Creator and you want to translate only strings from this file, you don’t need to do anything in this step. However if you want to translate any of the strings from your installer script, don’t forget about wrapping them in qsTr() function.

At first place you need to generate a translation source file. It can be done using lupdate with -ts flag. At the beginning you pass files that need to be translated and at the end you enter language code that indicates translation language. To generate polish translation source file command should look as follows:

lupdate installscript.qs CustomPage.ui -ts pl.ts

As installscript.qs doesn’t contain any strings to translate, so it can be skipped in this case. However I wanted to leave it there, just so you won’t forget about it.

After running command, the .ts file is generated, so you can begin created translation using Linguist tool. It is software used for translating .ts files and generating binary Qt messages files, provided with Qt.

Linguist window

After you finished translating all strings you can use File->Release option in Linguist to generate the Qt messages file needed in further steps. You can also use the command line and use the following command:

lrelase pl.ts

In both cases you should get .qm file containing your translation in binary format. Now make sure it is in the meta directory. As a final step add a list of translations inside package.xml using the following tags:

<Translations>
        <Translation>pl.qm</Translation>
</Translations>

As you see, you can add more translations by simply adding more Translation tags. At the end package.xml should look similar to this code:

<?xml version="1.0" encoding="UTF-8"?>
<Package>
    <DisplayName>PACKAGE NAME 64-bit</DisplayName>
    <Description>This is going to install APP NAME on your machine</Description>
    <Version>1.0.0</Version>
    <ReleaseDate>2020-06-17</ReleaseDate>
    <Licenses>
        <License name="LICENSE TITLE" file="license.txt" />
    </Licenses>
    <Default>true</Default>
    <Script>installscript.qs</Script>
    <UserInterfaces>
        <UserInterface>CustomPage.ui</UserInterface>
    </UserInterfaces>
    <Translations>
        <Translation>pl.qm</Translation>
    </Translations>
</Package>

After adding translation and generating a new installer, you can see the results:

Translated cutom page

Summary

With this entry you learned how to customize the installer UI. The installer appearance is now your oyster. However this is not the end of this tutorial. In the next post, you will learn more about using scripts and handling custom behaviour of your installer. See you soon!

Qt at Virtual CES 2021

Special year, special events; Qt is participating at the first-ever Virtual Consumer Electronics Show 2021. You will find the latest news and demos at our virtual exhibitor booth, especially our consumer and automotive industry offering with Qt 6. Virtual CES takes place from 11th to 14th January, 2021 on CES’ website. 

KDDockWidgets 1.2.0 released

We have released KDDockWidgets 1.2.0.

In this version we added support for two platforms, Wayland and WASM. Additionally, Qt 6.0 is now supported.

Update: We now have a WASM Demo which you can run directly on your browser. It’s very similar to what you’d get on the desktop, except for the docking indicators and performance  (depending on browser).

Try the Online WebAssembly Demo

Wayland

The big highlight of KDDockWidgets 1.2.0 is Wayland.

This was needed urgently, as there’s no other docking framework on this platform (to my knowledge). Linux distros are gradually abandoning X11 in favor of Wayland, breaking many developer tools in the process.

The implementation was challenging, as we needed to work around wayland protocol limitations (or rather security features), which substantially restricted the client windows. For example, it’s very hard for a client to position its window at a certain coordinate, or to know where other windows are, or to know its Z-order and detect the drop areas bellow it.

See README-Wayland for details on the concessions we had to make.

Another hurdle was that it wasn’t very hard to crash the compositor or the Qt wayland client QPA itself, so we needed a few more workarounds since those aren’t fixed in KDE and Qt.

WASM / WebAssembly

KDockWidgets can now run on a browser, via Qt for WebAssembly.

It was almost running out of the box, just had to initialize the qrc resources.

One snag, however, is that translucent windows don’t work on WASM; they appear black. Therefore, the classical indicators are disabled and you get the segmented indicators by default instead, as these don’t use translucency. I’m not sure if this is a bug in Qt, or a WASM limitation.

Another weird thing is that it’s very snappy and fluid when running on my phone, while it’s a bit sluggish when testing on my laptop.

See README-WASM for setup instructions.

Qt 6

The port was straightforward. When I ran all 200 tests, I was surprised; they still passed without needing workarounds.

The only major work was getting rid of QStateMachine. This class is now in the qtscxml module, not yet ported to Qt 6. So, I just rewrote the parts that depended on it.

Let me know if you spot any bugs; I haven’t tested it extensively.

KDDockWidgets is commercial and open source (GPLv2 & GPLv3).

For commercial licensing regarding inclusion in proprietary software and/or for tailored support options, contact us and ask for a 30-day free trial license.

If you missed the blog about the previous version of KDDockWidgets, v1.1, you can read that here.

Visit the KDDockWidgets GitHub page to get the update: https://github.com/KDAB/KDDockWidgets/releases/tag/v1.2.0.

You can find the source code for the KDDockWidgets 1.2.0 release on GitHub at: https://github.com/KDAB/KDDockWidgets

Tarballs and zipballs for 1.2.0 are here: https://github.com/KDAB/KDDockWidgets/releases

Prebuilt packages for some popular Linux distributions are here: https://build.opensuse.org/project/repositories/isv:KDAB

About KDAB

If you like this blog and want to read similar articles, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post KDDockWidgets 1.2.0 released appeared first on KDAB.

QLogger: A Qt multi-threading logger

Since I restarted the blog more than 2 years ago I’ve never talked about QLogger in-depth. I linked to the repo and did a small introduction in the second entry (Logging with Qt) but that was all.

During this year QLogger has had some nice improvements going from some sort of threading to full multi-threading support. During the last month it went from close configuration to full. When once it was only possible to choose the log level, now you can configure a lot of different things, including the output type.

All of that while keeping the retro-compatibility from the old usage.

How to use of QLogger

The initialization of QLogger remains the same as it was before. It’s still follows the singleton pattern and same signature. The following line will create the instance if it doesn’t exist or it will retrieve the existing one:

QLoggerManager::getInstance();

After that you can choose to pause it so it doesn’t print any messages until you resume it:

const auto logger = QLoggerManager::getInstance();

logger->pause();
logger->resume();

Adding destinations (basic level)

QLogger works in a way where you add modules (at least one) and a file where you want to print. This is the simplest scenario and gives you the ability to add several modules that print in the same file by passing the list of modules. Or splitting the file printing a variable number of modules by adding destinations one by one.

const auto logger = QLoggerManager::getInstance();

logger->addDestination("myLog.log", "UI");
logger->addDestination("myOtherLog.log", {"Network", "DB"});

Finally, to change the log level of those modules, you can use the following:

const auto logger = QLoggerManager::getInstance();
const auto infoLogLevel = LogLevel::Debug;

logger->overwriteLogLevel(infoLogLevel);

Logging with QLogger

The easier way to log using QLogger is by using the predefined methods. They automatically log the message using the desired level from the following 7 ones:

  • QLog_Trace
  • QLog_Debug
  • QLog_Info
  • QLog_Warning
  • QLog_Error
  • QLog_Fatal

The usage would be something like:

QLog_Info("UI", QString("Executing the command: {%1}").arg(cmd));

If the choosen level (suffix _Info) is equal or higher than the configured level, it will print the message onto the destination.

New configuration for QLogger

Recently, a user named AphaseDev has introduced a new bunch of features in QLogger. That includes a whole level of configuration for the destinations as well as adding support for console logging using QLogger. The new configuration includes the following fields:

  • Folder where the logs directory will be placed.
  • Log mode: Now the user can define if the logs will be printed in the file, the console or both.
  • File name suffix: It is possible to configure the log file suffix showing the date and time or a number.
  • Log message format: The log message can include a wider amount of information and not only the module and the log message. It includes the thread that printed the message, the function who printed the message, and the file and line.

In addition to the configuration of the destination, it is now possible to configure the maximum size of the file. The default value is 1 MB but you can add any number in here. Removing the log files is also possible through the clearFileDestinationFolder method and optionally providing the oldest date to keep the files from.

It is also possible to overwrite the log mode (output redirected to console or log file) during execution time.

Versioning

So far I’ve kept QLogger as an “under development” repository. The problem of releasing versions of a library for Qt is that I would have to provide versions compiled with all the possible compilers and at least several Qt versions, what is something annoying.

So far nobody has requested that and my intention is to keep the repository free of of pre-compiled libraries. However at the same time of this post I’m starting to add a release tag to the QLogger repository. This will allow users to have an easier way to get the tested and ready-for-production versions of the library.

Since this is a library, I’m concerned about breaking changes so I’m going to use the QT_DEPRECATED_X attribute (equivalent to the deprecated attribute added in C++14) and add that flag in the configuration of the project. This will allow people to get at least warnings or errors in the best case.

The code can be found in here.

Feel free to comment and let me know what you would like to see in QLogger in the future.

QLogger: A Qt multi-threading logger first appeared on My C++ & Qt blog - Cesc M..

KD Soap 1.10.0 Released!

We just released KD Soap 1.10.0!

What is KD Soap?

KD Soap is a tool for creating client applications for web services. With KD Soap, it’s possible to create web services that don’t require further components. This tool makes it possible to interact with applications that have APIs that can be exported as SOAP objects. The web service then provides a machine-accessible interface to its functionality via HTTP. You can find out more about KD Soap on our KD Soap homepage.

What’s new in KD Soap 1.10.0?

KD Soap 1.10.0 is the first version of KD Soap that does not have support for Qt 4. You must have Qt 5.7 or higher to be able to use this release.

Additionally, this version will not prompt you for license choice. We advise that you consider carefully your choice of license to be certain it is the right one for your needs.

Another change we made for 1.10.0 is we deprecated the QMake buildsystem to make way for CMake. The CMake buildsystem generates .pri files for qmake users.

Want to know more?

For more information about KD Soap 1.10.0 and to snag your copy, visit the GitHub page.

If you missed the previous release and would like to see the changes that came with it, please visit the blog.

 

About KDAB

If you like this blog and want to read similar articles, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post KD Soap 1.10.0 Released! appeared first on KDAB.

December ’20 – monthly digest

News

Qt 6.0 Released

by Lars Knoll

The much-awaited Qt 6 was launched this month. We’ll be letting you know about the many contributions KDAB made to help make that happen – starting with changes to Qt 3D you can find out about below. Meantime, as Lars says “Qt 6.0 is the first release of the Qt 6 series addressing new market demands while keeping the core values at the heart of what we do.”

Read more…

Qt 3D Renderer changes and improvements in Qt 6

by Paul Lemire

From new performance optimizations in the backend to new decoupled rendering plugins, Qt 3D is ready for the next major Qt release.

Read all about it in Paul’s blog…

Qt 3D changes in Qt 6, interview

Published after our last month’s newsletter, we didn’t want you to miss out on the insights from KDAB’s Qt 3D maintainer, Mike Krus on the Qt 3D changes in Qt 6.

Click the image or here to view it in KDAB News.

 


Blogs

Full Stack Tracing – Part 3

by Milian Wolff

At this point, we’re going to assume that you’ve already captured a trace file for the problem you’re examining as a common trace format (CTF) file, a structured binary file format that LTTng natively generates. What do you do with this file?

Read more…

How to build Qt with the Address Sanitizer on Windows

by Alessandro Ambrosano

Some time ago, I wrote about how to build C++ projects with ASAN on Windows. Now, if you happen to deal with Qt projects you may want to take this one step further and sanitize Qt itself.

Read more…

 


Releases

Qt Widgets and More – Latest release

Communicating between a view/delegate and a model Sometimes a view would like to have more data for a cell than what is in a cell…

Watch the video here…

 


Events to close the year

Qt Desktop Days – final insights

See the last talk, from KDE, and the Q&A session with Kalle Dalheimer and Giuseppe D’Angelo (KDAB), Harri Porten (Froglogic), and Thiago Macieira (Intel).playlist.

ESE Kongress, Sindelfingen, Nov 30 – Dec 4

KDAB’s Anton Kreuzkamp presented ‘Kann das nicht der Compiler machen? – Maßgeschneidertes Code-Refactoring mit Clang-Tooling’.

C++ and System Software Summit, Shenzhen, Dec 4 – 5

This was a hybrid event, with speakers and attendees from China supplemented by speakers on screen from other parts of the world. Bjarne Stroustrup gave a keynote on ‘C++20 and the continuous evolution of C++’ and KDAB’s Ivan Čukić presented a talk on ‘How to design an elegant API without sacrificing performance’.

The post December ’20 – monthly digest appeared first on KDAB.

Why do manufacturing companies need a modern software strategy?



 

Software has become a critical factor of our economy. Manufacturing companies must start to think and act software-centric to survive. In this interview, software pioneer Matthias Kalle Dalheimer explains why conventional companies run the risk of becoming commoditized and how they can get ahead of the competition. What are the corner stones of a real modern software strategy? What can the “old economy” learn from the software industry (and vice versa)?

 

What are your thoughts when looking at software being a critical part of infrastructure and our daily lives?

You can liken this to an infrastructure, like railway tracks, where countries have built railway tracks in the late 1800s and the early 1900s and then neglected maintenance and now many western countries, like Germany, the UK, or Sweden find themselves in the situation where the technical infrastructure is starting to crumble. Even though software is less old than that, we have a similar situation of accumulated technical debt, meaning that software hasn’t been updated at the rate that it should have been. So, we will see more and more problems with software that hasn’t been maintained and companies, organizations, and whole countries will need to address that problem.

 

You mentioned technical debt. Can you say a bit more about that?

We’ve seen software development since the 1960s and, sadly, some of the software that is still in operation is about that old. So, companies have accumulated a huge amount of technical debt that they will need to pay off sooner or later. Many companies that come from a non-software technology background, such as machining companies or other hardware companies, find themselves unwittingly in a situation where the software that runs their machine deteriorates. Contrary to popular belief, software is not fire and forget, it needs to be maintained and updated just like hardware does, just like technical infrastructure does.

 

What does this mean for business strategies?

Any technology company needs to understand that a software strategy must be part of their business strategy. In the future, there will be no technology company that is not also a software company, because software is more and more the defining factor of what separates the different product offerings from each other. As a hardware company that realizes that it needs to become a software company as well, it is not enough to just buy a website or an app from somewhere. They will need to include the software development process into their overall product development process. As an engineering or technology company, you know how to do proper civil engineering or machine construction; this is something where the software industry can learn a lot from you. On the other hand, you also can learn a lot from the software industry. Agile development processes, thinking in platforms, and flexible development strategies are some things the software industry can contribute to your product development.

 

Can you give us an example for that?

If you’re a company that builds washing machines, you will already be used to thinking in platforms in order to create different product lines and models of washing machines. The same thinking needs to be applied to your software creation. Just starting from scratch every time is going to be too slow and will not let you be on the market fast enough.

 

So what is your recommendation for traditional companies trying to establish modern software development processes?

Today, software development is done in teams with careful planning and stringent quality assurance. As companies are building up software assets, they also need to include operations and best practices into their software development process. It’s not enough to just write software once, install it on a device and then forget about it. This will not be sufficient developer productivity for updates in the future.

 

How would you describe a modern software strategy then?

Part of a modern software strategy would be flexible work processes, work times, and work locations. This is something young software developers naturally expect. Today, software developers make themselves available on a global job market. As a technology company, this also means that even you can recruit on a global job market. However, this may require to make some of your processes, working times, or work locations more flexible.

 

So, where do you see this development going?

The number of screens that run software, the number of devices that run software is growing at a way faster rate than the number of software developers. So, every individual software developer needs to be able to produce more. It is very important that software developers get the most out of their time and follow best practices that have been established by the software industry in order to be able to keep up with the increasing demand of software development output. For that, software engineers will need to understand not only software development best practices, but also the underlying business of the technology company.

For More Information…

If you have further interest in the topic, you can also read Kalle’s whitepaper, Dodging Disruption with Software– how to prevent commoditization.

KDAB offers experienced software experts to help you deliver functional, high-performing, and innovative software across embedded, mobile, and desktop platforms for projects using C++, Qt, QML/Qt Quick, OpenGL, Qt 3D, and more: https://www.kdab.com/software-services/

 

About KDAB

If you like this blog and want to read similar articles, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post Why do manufacturing companies need a modern software strategy? appeared first on KDAB.

Welcome to our 2020 Qt Champions!

We have now handled the nominations with the current lifetime champions we have now come to a consensus on the Qt Champions of 2020! A special thank you to @SGaist, @mrjj, @aha_1980 and Orgad Shaneh for your help in this regard!

Firstly, I would like to make a special mention for one of the nominations this year which isn't a nomination for a person but for a whole project. The KDE project. As I am sure a lot of you will already be aware but the KDE project is very much involved with the Qt project and has its contributors have contributed a lot Qt over the years as well. So although as a project it is not eligable to be a Qt Champion, we were unanimous in the fact that we wanted to highlight the fact that the KDE project has contributed a lot to the success of Qt and as such warrant being mentioned as part of the Qt Champions.

Now without further ado, it is time to announce the winners of the Qt Champions for 2020. Starting with our year's Content Creator who is Bryan Cairns aka Voidrealms. Bryan has a few courses available on Udmey, specifically his course on Qt 5 Design Patterns and also has a popular group on Facebook which helps others with their Qt questions as well. For his work alone in creating the Qt 5 training course online for everyone to benefit from it was easy to make him our year's Content Creator.

When it comes to the Maverick this year, then the honor goes to Denis Shienkov. During the last year Denis has submitted an exceptionally high number of patches to Qbs and Qt Creator bringing in support for a number of different toolchains and debuggers which add extra value for bare metal developers. Not only that he has created a Visual Studio code extension for Qbs which brings the Qbs project to an even wider audience too. His continued effort to bring Qbs to a larger audience and to keep it working alone is justification enough for him being our Maverick this year.

This year we ended with two winners in our Developer category, both of them have contributed a lot, as well with patches as with reviews. So rather than just picking one, we decided to go with both of them: Ivan Komissarov and Giuseppe D'Angelo.

Ivan is another very active contributer for Qbs, he has submitted and reviewed at a rate which is really impressive for any contributor on any project. He hasn't limited himself to just code fixes, he has contributed documentation, improved support for features and is one of the key contributors for the Qbs project as well.

Giuseppe is a name which a lot of the developers may recognise, thanks to his numerous patches and also reviews on a lot of their patches as well. Giuseppe has contributed a lot of Qt 6 specific patches from the start of the whole process and has helped a lot to get Qt 6 into the state that was desired. Also his constructive feedback on patches has helped a lot of developers improve their patches and has also caught some things which may have gone unnoticed.

So both Ivan and Giuseppe are easily our Developer champions this year.

This year we have two new lifetime champions, both throughly deserved in getting their titles, starting with Christian Ehrlicher.

Christian is our Quality Assurer champion this year. He has been doing a lot to help ensure that the SQL support in Qt is much more stable, catching issues and fixing them in an module that has not received a lot of attention, but thanks to him is in a good and stable state. He has contributed patches and has reviewed even more ensuring that our quality in the code is kept to a high standard. For that he is worthy of the Quality Assurer title and also being our fifth lifetime champion.

Johan Specht aka @jsulm will be a name that you recognise if you frequent the Qt forum, he is our Community Builder champion this year being recognised for his numerous contributions on the the Qt forum helping out beginners and advanced users alike. When you get an answer from Johan then you know you are going to be on safe ground and will be able to get your question answered. For his long term commitment to the forum, it is alone reason why he is our sixth lifetime champion.

So congratulations to all of our Qt Champions for 2020 and congratulations to Christian and Johan once again on becoming our 5th and 6th lifetime champions.

Thank you to all of you and to all of your in the community for making this a great community to work with. I hope to work with many of you again in 2021!

Qt for Python 6 released

It is with great pleasure to announce that we have released a new version of Qt for Python for Qt 6 and a range of new features 🐍. PySide was initially released for Qt 4 and PySide2 for Qt 5.12. We have decided to follow the general Qt release versioning with this release, explaining the version leap to PySide6 and Shiboken6.    

How to build Qt with the Address Sanitizer on Windows

Some time ago, I wrote about how to build C++ projects with ASAN on Windows. Now, if you happen to deal with Qt projects you may want to take this one step further and sanitize Qt itself.

Why bother with a sanitized Qt build?

Let’s have a closer look on why having a sanitized Qt build around is a good idea.

If you’re already patching Qt for your own needs, sanitizing Qt is the only way to check for bugs on your code. This is the reason why we use sanitizers in the first place.

Otherwise, you may argue that Qt is “good” or “safe” or “bug free” enough. This, in principle, is not a safe assumption. Choosing to take your chances may still leave some of your bugs on the table. Let’s see an example:

#include <QApplication>
#include <QByteArray>
#include <QDebug>
#include <QTimer>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QTimer t;
    t.setInterval(0);
    t.setSingleShot(true);
    {
        QByteArray ba = QByteArrayLiteral("Test byte array literal");
        t.connect(&t, &QTimer::timeout, &t, [d=ba.data()](){
            qDebug() << d;
        });
    }
    t.start();

    return app.exec();
}

When we build this code with the address sanitizer and run it, we get this output:

Test byte array literal

Great, all good! Or is it? Let’s try to run the same code with a sanitized Qt. This is the output:

=================================================================
==15844==ERROR: AddressSanitizer: heap-use-after-free on address 0x12643130a628 at pc 0x7ff81ca3e54a bp 0x00b1e08f86e0 sp 0x00b1e08f8728
READ of size 24 at 0x12643130a628 thread T0
    #0 0x7ff81ca3e572 in _asan_wrap_strlen+0x1b2 (C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\Llvm\x64\lib\clang\10.0.0\lib\windows\clang_rt.asan_dynamic-x86_64.dll+0x18002e572)
    #1 0x7ff813417f6e in QString::fromUtf8 C:\qt5\qtbase\src\corelib\tools\qstring.h:572
    #2 0x7ff7780318aa in QtPrivate::QFunctorSlotObject<`lambda at C:\test-build-with-sanitized-qt\main.cpp:15:45',0,QtPrivate::List<>,void>::impl C:\qt-build-sanitized\include\QtCore\qobjectdefs_impl.h:439
    #3 0x7ff813cd4fc3 in QMetaObject::activate C:\qt5\qtbase\src\corelib\kernel\qobject.cpp:3781
    #4 0x7ff813cf1671 in QTimer::timerEvent C:\qt5\qtbase\src\corelib\kernel\qtimer.cpp:255
    #5 0x7ff813cbfcf5 in QObject::event C:\qt5\qtbase\src\corelib\kernel\qobject.cpp:1247
    #6 0x7ff8158ac7a7 in QApplicationPrivate::notify_helper C:\qt5\qtbase\src\widgets\kernel\qapplication.cpp:3737
    #7 0x7ff8158b2470 in QApplication::notify C:\qt5\qtbase\src\widgets\kernel\qapplication.cpp:3598
    #8 0x7ff813c19f8d in QCoreApplication::notifyInternal2 C:\qt5\qtbase\src\corelib\kernel\qcoreapplication.cpp:1084
    #9 0x7ff813d7ef0d in QEventDispatcherWin32::event C:\qt5\qtbase\src\corelib\kernel\qeventdispatcher_win.cpp:1064
    #10 0x7ff8158ac7a7 in QApplicationPrivate::notify_helper C:\qt5\qtbase\src\widgets\kernel\qapplication.cpp:3737
    #11 0x7ff8158b2470 in QApplication::notify C:\qt5\qtbase\src\widgets\kernel\qapplication.cpp:3598
    #12 0x7ff813c19f8d in QCoreApplication::notifyInternal2 C:\qt5\qtbase\src\corelib\kernel\qcoreapplication.cpp:1084
    #13 0x7ff813c1f045 in QCoreApplicationPrivate::sendPostedEvents C:\qt5\qtbase\src\corelib\kernel\qcoreapplication.cpp:1821
    #14 0x7ff84512b0b5 in QWindowsGuiEventDispatcher::sendPostedEvents C:\qt5\qtbase\src\platformsupport\eventdispatchers\qwindowsguieventdispatcher.cpp:81
    #15 0x7ff813d6fdee in qt_internal_proc C:\qt5\qtbase\src\corelib\kernel\qeventdispatcher_win.cpp:245
    #16 0x7ff88793e857 in CallWindowProcW+0x3f7 (C:\WINDOWS\System32\USER32.dll+0x18000e857)
    #17 0x7ff88793e298 in DispatchMessageW+0x258 (C:\WINDOWS\System32\USER32.dll+0x18000e298)
    #18 0x7ff813d757d5 in QEventDispatcherWin32::processEvents C:\qt5\qtbase\src\corelib\kernel\qeventdispatcher_win.cpp:639
    #19 0x7ff84512b046 in QWindowsGuiEventDispatcher::processEvents C:\qt5\qtbase\src\platformsupport\eventdispatchers\qwindowsguieventdispatcher.cpp:74
    #20 0x7ff813c0aaaf in QEventLoop::exec C:\qt5\qtbase\src\corelib\kernel\qeventloop.cpp:225
    #21 0x7ff813c1bf60 in QCoreApplication::exec C:\qt5\qtbase\src\corelib\kernel\qcoreapplication.cpp:1385
    #22 0x7ff778031443 in main C:\test-build-with-sanitized-qt\main.cpp:21
    #23 0x7ff7780326b3 in __scrt_common_main_seh D:\agent\_work\9\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #24 0x7ff888866fd3 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180016fd3)
    #25 0x7ff8890fcec0 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18004cec0)
0x12643130a628 is located 24 bytes inside of 48-byte region [0x12643130a610,0x12643130a640)
freed by thread T0 here:
    #0 0x7ff81ca45094 in _asan_memmove+0x344 (C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\Llvm\x64\lib\clang\10.0.0\lib\windows\clang_rt.asan_dynamic-x86_64.dll+0x180035094)
    #1 0x7ff77803141f in main C:\test-build-with-sanitized-qt\main.cpp:18
    #2 0x7ff7780326b3 in __scrt_common_main_seh D:\agent\_work\9\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #3 0x7ff888866fd3 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180016fd3)
    #4 0x7ff8890fcec0 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18004cec0)
previously allocated by thread T0 here:
    #0 0x7ff81ca451a4 in _asan_memmove+0x454 (C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\Llvm\x64\lib\clang\10.0.0\lib\windows\clang_rt.asan_dynamic-x86_64.dll+0x1800351a4)
    #1 0x7ff813503701 in QArrayData::allocate C:\qt5\qtbase\src\corelib\tools\qarraydata.cpp:118
    #2 0x7ff81350bcaf in QByteArray::reallocData C:\qt5\qtbase\src\corelib\tools\qbytearray.cpp:1905
    #3 0x7ff81341493b in QByteArray::data C:\qt5\qtbase\src\corelib\tools\qbytearray.h:569
    #4 0x7ff778031313 in main C:\test-build-with-sanitized-qt\main.cpp:15
    #5 0x7ff7780326b3 in __scrt_common_main_seh D:\agent\_work\9\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #6 0x7ff888866fd3 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180016fd3)
    #7 0x7ff8890fcec0 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18004cec0)
SUMMARY: AddressSanitizer: heap-use-after-free (C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\Llvm\x64\lib\clang\10.0.0\lib\windows\clang_rt.asan_dynamic-x86_64.dll+0x18002e572) in _asan_wrap_strlen+0x1b2
Shadow bytes around the buggy address:
  0x04a8b7561470: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x04a8b7561480: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x04a8b7561490: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x04a8b75614a0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 01 fa
  0x04a8b75614b0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 00
=>0x04a8b75614c0: fa fa fd fd fd[fd]fd fd fa fa 00 00 00 00 00 00
  0x04a8b75614d0: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x04a8b75614e0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x04a8b75614f0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x04a8b7561500: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
  0x04a8b7561510: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable: 00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone: fa
  Freed heap region: fd
  Stack left redzone: f1
  Stack mid redzone: f2
  Stack right redzone: f3
  Stack after return: f5
  Stack use after scope: f8
  Global redzone: f9
  Global init order: f6
  Poisoned by user: f7
  Container overflow: fc
  Array cookie: ac
  Intra object redzone: bb
  ASan internal: fe
  Left alloca redzone: ca
  Right alloca redzone: cb
  Shadow gap: cc
==15844==ABORTING

This is because, in the call to connect on line 15, we are copying a pointer to the internal buffer of a QByteArray, which will be already gone when the timer is started. Note that this is not inherently a Qt bug. Additionally, the documentation warns us that the lifetime of that pointer is bound to the one of the byte array. Since all of the allocations are happening inside Qt without sanitizing Qt itself, this bug will go undetected.

Building Qt with the Address Sanitizer

To generate a sanitized Qt build, we are going to use clang. Clang has been providing the Address Sanitizer on Windows for a while. This means we will only be able to create a release build for Qt, as clang on windows doesn’t support debug builds with the Address Sanitizer. If you have a recent version of Visual Studio, you can choose to do the same with the cl compiler in a similar way.

Qt comes with bundled mkspecs, to build with either clang or clang-cl. We will be creating our own sanitized clang-cl mkspec based on the original clang-cl one. To do so, duplicate the folder qt5/qtbase/mkspecs/win32-clang-msvc to qt5/qtbase/mkspecs/win32-clang-msvc-with-address-sanitizer. Next, replace the content of qmake.conf with the following:

include(../win32-clang-msvc/qmake.conf)
# Generate debug information
CONFIG += force_debug_info
# Force release build as debug builds are not supported
CONFIG += release
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -fsanitize=address
QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += -fsanitize=address
# # Add the path to the clang ASAN runtime and link against
QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += /LIBPATH:\"C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/lib/clang/10.0.0/lib/windows\"
QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += clang_rt.asan_dynamic-x86_64.lib /wholearchive:clang_rt.asan_dynamic_runtime_thunk-x86_64.lib

Now you can start building by specifying the mkspec with -platform win32-clang-msvc-with-address-sanitizer. Also, make sure you pass -no-pch to the configure script. Otherwise, the build will fail.

Note that, since rcc and moc are built with ASAN as well. They may (and will) generate some ASAN warnings at build time. So make sure you have ASAN_OPTIONS=halt_on_error=0 in your build environment. Do the same for building all your projects using this sanitized Qt version.

Some final touches

If you try launching an application built against this sanitized Qt build, it will raise an exception at startup. The error will look like this:

Unhandled exception at 0x00007FFA44FF2807 (Qt5Core.dll) in qtplain.exe: 0xC0000005: Access violation writing location 0x00000000756E6587.

What is this about? Let’s have a look at the disassembled code around the affected area:

0x00007FFA2DD827F4 xor eax,eax
0x00007FFA2DD827F6 xor ecx,ecx
0x00007FFA2DD827F8 cpuid
0x00007FFA2DD827FA mov esi,eax
0x00007FFA2DD827FC mov rdi,qword ptr [__asan_shadow_memory_dynamic_address (07FFA2EDC6E60h)]
0x00007FFA2DD82803 lea r12,[rbx+60h]
0x00007FFA2DD82807 mov qword ptr [rbx+40h],41B58AB3h  <-- EIP

What’s going on is that the cpuid instruction, when invoked with eax=0 (see xor eax, eax on address 00007FFA2DD827F4), will write a 12 bytes string spread on the three registries ebx, edx, ecx – in that order – identifying the manufacturer of the CPU.

In my case, for instance, cpuid returns 'GenuineIntel', which translates, adjusting for endianness, to the following values for rbx, rdx, rdx:

rbx: 0x00000000756E6547 . . . . u n e G
rdx: 0x0000000049656E69 . . . . I e n i
rcx: 0x000000006C64746E . . . . l e t n

A few instructions later, where the application breaks, the instruction on 0x00007FFA2DD82807 is trying to write on ebx + 0x40, whose value is exactly 0x00000000756E6587 (the address mentioned in the error message).

This means the registry wasn’t backed up and restored by the compiler around the cpuid instruction. This is a known clang bug that happens when a heap allocation occurs right after a cpuid instruction with ASAN enabled. Or, more in general, it is a rare bug that results in ebx being mismanaged by the compiler (see this and this).

So what can we do about it?

For lack of better options, a quick workaround for this is to replace all the calls to cpuid (see below) with their return values. To do so, just run all the calls to __cpuid on a small program. Then, copy the values on the Qt source code. The following is a list of all the occurrences:

Conclusion

The Address Sanitizer is a helpful tool for tracking and solving memory bugs. However, limiting ourselves to sanitize only our own code is not enough. Libraries can prevent bad API usage only up to a certain point. There are still cases where damage can be done undetected. Sanitizing consumed libraries will greatly increase the surface for automatic bug detection. Qt’s open source nature allows us to leverage this opportunity.

If you’d like to learn more about the tooling available for C++ developers working with Windows, you might be interested in our Debugging and Profiling C++ Applications on Windows training.

About KDAB

If you like this blog and want to read similar articles, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post How to build Qt with the Address Sanitizer on Windows appeared first on KDAB.

Speedup your Qt/QML list scrolling on lowend devices

Speedup your Qt/QML list scrolling on lowend devices

Something that has traditionally been complicated to achieve in Qt/QML, especially on low end hardware, is high performant list scrolling with complex delegates.
This has recently changed. In Qt 5.15, it is as simple as setting the new QML ListView property called reuseItems to true. For more details, have a look at the documentation.
In this blog post, I will explain how you can implement this feature in Qt Versions prior to 5.15.

Continue reading Speedup your Qt/QML list scrolling on lowend devices at basysKom.

Deploying app and generating offline installers for Windows Qt Installer Framework tutorial

Development is not an only part of product delivering – deployment and maintenance are both equally important parts of the product lifecycle. That is why Qt lend us a hand by providing Installer Framework. It is a set of tools that allows not only to create good-looking and functional installers but also update the app, provide tools for maintaining it, and much more. In this tutorial, you will learn the basics of Qt Installer Framework and find out how to generate your first offline installer for Windows. Let’s go!

 

How to get Qt Installer Framework? 

Qt Installer framework can be easily installed via Qt Maintenance tool or downloaded from Qt repository. When using a maintenance tool, it can be found in the Developer and Designer Tools section:

 

After download it should be stored in [QtDirectory]/Tools/QtInstallerFramework

How to generate installer with Qt Installer Framework? 

1. Create a deployment folder 

Before generating an installer, you have to prepare your app for deployment. The first step is to create a deployment folder where all necessary files for app execution and installer generation will be stored. Inside it, you should create two directories: „config” and „packages”.

 

As the name suggests, the first directory will contain configuration files for your installer – in this case a single XML file. What should this file contain?

 

2.  Create a config file

The configuration file consists of some general information about the app: installation directory, name of the installer, etc. You can make some interesting things by modifying this file – for example, add a „run after installation” checkbox, modify installer UI or even add remote repositories for fetching app updates. You can learn about all the available tags in the Qt Installer documentation.

 

Let’s create such a file. The basic one should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<Installer>
    <Name>APP NAME</Name>
    <Version>1.0.0</Version>
    <Title>INSTALLER WINDOW TITLE</Title>
    <Publisher>Scythe Studio</Publisher>
    <StartMenuDir>START_MENU_DIR</StartMenuDir>
    <TargetDir>@HomeDir@/APP_DIR</TargetDir>
</Installer>

Although it is minimalistic, for now, this would be enough.

 

3. Create a package 

Before you go any further, you should learn what the package actually is. The package is a module that contains a certain version or some parts of the app. If you include many packages, the installation can be customized – users can select what they want to install. Qt itself is a great example of such approach. Let’s take a look at the tree structure in the Qt installer:

 

As you see, the framework is divided into several packages containing kits for different platforms and modules with optionals functionality like a web engine.

 

According to the documentation, the packages directory should have following structure:

-packages
    - com.vendor.root
        - data
        - meta
    - com.vendor.root.component1
        - data
        - meta
    - com.vendor.root.component1.subcomponent1
        - data
        - meta
    - com.vendor.root.component2
        - data
        - meta

With this knowledge, you can now start creating the first packages for our app. To make things clear and simple, for now, we’ll roll on with only two packages: a 64-bit app version and a 32-bit one.

 

Begin by creating proper directories for the packages. We will stick to the „com.developername.shortpackagename” naming pattern:

 

 

What about packages content? Let’s begin populating them!

 

4. Add metadata 

Each package should contain two main directories inside: „data” and „meta”. First will contain executables, libraries, and other files necessary for running the app, while second hold information about the package. The „Meta” folder will contain only two files, in this case, so start with it.

 

 

Metadata should consist of „license.txt” and „package.xml” files. The text file is obvious – it provides the installer with license content. It doesn’t have any required format, but HTML tags are supported if you need some styling.

 

Now let’s talk about „package.xml” – this one is more interesting. This file contains information about the package, which will be presented in the installer window. By putting additional tags you can add custom installer pages, translations, dependencies between other packages and many more. We will talk about this file again, in another part of the tutorial, which will be published in the future. The „package.xml” content should look like this for now:

 

<?xml version="1.0" encoding="UTF-8"?>
<Package>
    <DisplayName>PACKAGE NAME</DisplayName>
    <Description>This is going to install APP NAME on your machine</Description>
    <Version>1.0.0</Version>
    <ReleaseDate>2020-06-17</ReleaseDate>
    <Licenses>
        <License name="LICENSE TITLE" file="license.txt" />
    </Licenses>
    <Default>true</Default>
</Package>

Most of the tags are self-explanatory. If you want to learn more about other tags see documentation.

 

5. Fill data  directory

When you add necessary files to the „meta” directory, move one to the „data” folder. This directory contains all the app files that the package holds. When installing the package, its contents will be unpacked to the target directory. In order to keep the installation folder clear, we suggest creating an additional subfolder in the data directory.

 

As there is already a large number of folders we talked about, we’ll call this one „package files directory”. With that keeping track would be simpler.

 

Now the crucial part of deployment preparation begins. Inside the package files directory, you need to add a substantial amount of files needed to run an app outside the Qt Creator IDE: all the executables, Qt and external libraries, dll files, etc. Fortunately, the Qt Framework will help us achieve this by providing a set of tools for deployment.

 

Now add the executable file to the package files directory. Simply copy it from the build folder. Now open the command line terminal in the package files directory. It is needed to run „windeployqt.exe” – a tool created for automatic loading of all the Qt dll files needed for running the app. To run this tool use this command:

[QtFolder]\[QtVersionThatYouUse]\[SelectedKitDirectory]\bin\windeployqt.exe APPNAME.exe --qmldir [DirectoryContainingProjectQMLSourcecode] --compiler-runtime

This command adds (almost) all necessary binaries and files that you need to launch a QML based app. The -qmldir flag is used to scan your QML code and add all the needed runtime libraries from the Qt Quick module. After this flag put your project directory – don’t worry it will be scanned recursively. If your app is not QML based, you can skip this flag.

 

In the tutorial case the full command should look like this:

C:\Qt\5.15.0\mingw81_64\bin\windeployqt.exe QtInstallerTutorial.exe --qmldir C:\Projects\QtInstallerTutorial --compiler-runtime

 

When the tool finishes its work you can see that now the package files directory is getting crowded.

Currently, windeployqt tool tends to ship a lot of unnecessary files here, but even now there is no every file you need. Not yet…

 

6. Add the  compiler-specific files

If you try to run the application now you’ll get an error pop-up showing info about missing files. Depending on the configuration, compiler-specific and some other libraries must be redistributed along with your application. According to the documentation, the basic ones are:

  • Qt
    • QT5CORE.DLL – The QtCore runtime

    • QT5GUI.DLL – The QtGui runtime

    • QT5WIDGETS.DLL – The QtWidgets runtime

  • VC++ 14.0 (2015)

    • VCCORLIB140.DLL, VCRUNTIME140D.DLL – The C runtime

    • MSVCP140.DLL – The C++ runtime

  • MinGW
    • LIBWINPTHREAD-1.DLL

    • LIBGCC_S_DW2-1.DLL

    • LIBSTDC++-6.DLL

 

However, to make sure that you didn’t miss anything, following Qt docs advice, we suggest using the Dependency Walker tool. After running it you can easily see what dependencies are missing.