KDAB Blogs – KDAB https://www.kdab.com The Qt Experts Fri, 29 May 2020 09:51:32 +0000 en-US hourly 1 https://wordpress.org/?v=5.4.1 https://www.kdab.com/wp-content/uploads/stories/cropped-Favicon-32x32.png KDAB Blogs – KDAB https://www.kdab.com 32 32 32184545 Using Visual Studio Code for Qt Applications – Part Two https://www.kdab.com/using-visual-studio-code-for-qt-apps-pt-2/ https://www.kdab.com/using-visual-studio-code-for-qt-apps-pt-2/#respond Thu, 28 May 2020 09:00:55 +0000 https://www.kdab.com/?p=22669 In the last blog post we saw an essential, C++ oriented, Visual Studio Code setup. That was enough to get going right away, but we can still definitely do more and better. Here I’ll show you how to get a complete setup for your qmake and CMake projects, all this while also wearing a Qt […]

The post Using Visual Studio Code for Qt Applications – Part Two appeared first on KDAB.

]]>
In the last blog post we saw an essential, C++ oriented, Visual Studio Code setup. That was enough to get going right away, but we can still definitely do more and better. Here I’ll show you how to get a complete setup for your qmake and CMake projects, all this while also wearing a Qt hat (on top of my C++ hat) and having a deeper look at the Qt side.

Build qmake Qt projects

Qmake is not integrated with Visual Studio Code the way CMake is, so setting up a qmake project for build is slightly more convoluted than doing the same with CMake. This means we’ll have to define our own build tasks. We’re going to do this in two stages: build steps definition and build steps combination, leveraging the fact that Visual Studio Code implements task dependencies and ordered sequential execution of dependencies.

Create build steps

As far as build steps are concerned, the following are, in a nutshell, the ones that will cover most cases:

  • Create the build directory (in a way that doesn’t fail if the directory already exists)
    {
      "label": "Create build dir",
      "type": "shell",
      "command": "mkdir -Force path/to/build/dir"
    }
    

    Here, -Force is a powershell parameter that will prevent the command to fail if the directory already exists. On Unix based systems, you can use mkdir -p instead.

  • Run qmake
    {
      "label": "Run qmake",
      "type": "shell",
      "command": "qmake",
      "arg": [ ... add your qmake arguments here ... ],
      "options": {
        "cwd": "path/to/build/dir"
      }
    }
    
  • Run make/nmake/jom, depending on the platform
    {
      "label": "Run make",
      "type": "shell",
      "command": "jom",
      "options": {
        "cwd": "path/to/build/dir"
      }
    }
    
  • Clear build folder This can mean different things depending on how the build file is configured. It could be a simple make clean, or a more thorough removal of the whole content of the build folder.

    {
      "label": "Clear build folder",
      "type": "shell",
      "command": "jom clean",
      "options": {
        "cwd": "path/to/build/dir"
      }
    }
    
Combine build steps

Now that our steps are defined, we can go on and define the actual build tasks. We’ll prepare two for this example, one for running a build, and one for running a clean build. Let’s see the task for a regular build:

{
  "label": "Build",
  "dependsOn": [
    "Create build dir",
    "Run qmake",
    "Run make"
  ],
  "dependsOrder": "sequence"
}

There are two new properties here: "dependsOn" is a list of task labels, and it means that those tasks need to be executed before the current task is built, while "dependsOrder", when set to "sequence", will tell Visual Studio Code to run all dependent tasks sequentially and in the given order.

The task for a clean build is very similar and will only have an extra step where the project is cleaned before being built again:

{
  "label": "Clean build",
  "dependsOn": [
    "Clear build folder",
    "Create build dir",
    "Run qmake",
    "Run make"
  ],
  "dependsOrder": "sequence"
}

And that’s it, now it’s just a matter to open the command palette (Ctrl+Shift+P), select “Task: Run Task” and then “Build”.

Use a default task

As an alternative (or better, an addition) to selecting manually the build task from a list every time, Visual Studio Code also allows to run a default task with a key combination (Ctrl+Shift+B). To mark a task as default, you need to add a few extra lines to the task configuration:

{
  // ... task configuration
  "group": {
    "kind": "build",
    "isDefault": true
  }
}
Use your own Qt

If Qt is not configured at a system level, or you want to use a Qt version other than the default one installed and configured in your system, you need to explicitly configure the environment so that every task is run with the right Qt version in the path. Visual Studio Code allows you to do this every time a terminal is launched for running a task, so our environment customizations are set before running the task command.

This is done in the settings file (or in the workspace settings if you’re working with a workspace), and the property name for this setting is system dependent: either "terminal.integrated.env.windows", "terminal.integrated.env.linux", or "terminal.integrated.env.osx". The property requires an object, where each property is the name of an environment variable, and the associated value is the value for the variable. Below is an example configuration for Windows:

{
  // All other settings...
  "terminal.integrated.env.windows": {
    "PATH": "C:/Qt/5.12.4/msvc2017_64/bin;${env:PATH}"
  }
}

Build CMake Qt projects

Setting up a CMake based project using the CMake extension doesn’t require any settings manipulation if Qt is already configured on your system. What you will need is to select a CMake kit (the CMake extension finds them automatically), a build variant, and launch the build with F7.

Short video showing how to launch a CMake build with Visual Studio Code

However, you may want to use extra arguments in the configuration step or specify your build directory so for instance it doesn’t end up being inside the source directory. You can customize CMake configuration arguments by setting the property "cmake.configureSettings" in your settings file. This property expects a list of string arguments that will be passed to CMake during the configuration step:

"cmake.configureSettings": {
  "CMAKE_PREFIX_PATH": "my/prefix/path",
  "ENABLE_FEATURE": "1",
  "ENABLE_OTHER_FEATURE": "0"
}

To customize the build directory, just set "cmake.buildDirectory" to the desired path. This value may contain variables, so it can be configured, for instance, to point a path relative to the project folder:

"cmake.buildDirectory": "${workspaceFolder}/../build-cmake-project"

If you want to use a custom Qt version, or Qt is not configured system-wide (as is the case on Windows) it’s enough to set CMAKE_PREFIX_PATH properly in the "cmake.configureSettings" property in the settings file. For example:

"cmake.configureSettings": {
  "CMAKE_PREFIX_PATH": "otherprefixpath;C:/Qt/5.12.4/msvc2017_64"
  // ... other args
]

You can find a complete documentation for the CMake Tools extension here, featuring a guide on how to use CMake Tools from the UI, and a documentation for all available settings.

Running and debugging our Qt application

Now that your application has been built, let’s see how we can launch it and, most importantly, debug it.

Running qmake projects

For projects built with qmake, we don’t have any help from extensions and the only option we have is to bake our own launch configurations in the way we’ve seen in the last blog post. This is done in the launch configurations file (launch.json) or in the workspace file, and this is how a launch configuration looks:

{
  "name": "My application",
  "type": "cppvsdbg",
  "request": "launch",
  "program": "path/to/application",
  "stopAtEntry": false,
  "cwd": "${workspaceFolder}",
  "environment": [],
  "externalConsole": false
}

You can run launch configurations both with or without debugger, using “Debug: Start Debugging” (F5) or “Run: Start Without Debugging” (Ctrl+F5) respectively. If Qt is not configured at a system level, or you want to use a custom Qt version, the corresponding launch configuration will need to be explicitly configured to include Qt in its path.

You can do this by updating the "environment" property in the launch configuration. Below is an example for Windows, setting only the "PATH" environment variable. Configurations for other systems need to be adjusted but are essentially similar.

"environment": [
  {
    "name": "PATH",
    "value": "C:/Qt/5.12.4/msvc2017_64/bin;${env:PATH}"
  }
]

Side note: here ${env:PATH} means whaterever value the environment variable PATH has before the launch configuration is run. In general, the syntax ${env:VARNAME} can be used to get an environment variable in a task or a launch configuration.

Running CMake projects

Working with CMake is easier in principle, as the CMake extension provides the commands “CMake: Run Without Debugging” and “CMake: Debug”, allowing you to respectively launch and debug CMake targets.

However, this approach has a number of shortcomings:

  • It’s not possible to specify per-target run arguments for debug runs.
  • It’s not possible at all to specify run arguments for non-debug runs.
  • Some debugging options such as source mapping or custom views with natvis are not configurable using cmake settings.

So in conclusion using the CMake extension for running targets is not really convenient if you want a comprehensive debugging experience, and the best way to go is still to create your own launch configurations.

The CMake extension provides a few convenient variables for launch configurations:

  • ${command:cmake.launchTargetPath}: resolves to the full path of the executable for the target selected from the launch target menu.
  • ${command:cmake.launchTargetDirectory}: resolves to the directory containing the executable for the target selected from the launch target menu.

Qt aware debugging

What we’ve seen until now will let you build and run your Qt applications, using either your system provided Qt or your own. Debugging will work out of the box already, as long as the application code is involved. But wouldn’t it be great to also be able to peek inside Qt’s source code while debugging? Or if we had a better visualization for Qt specific types?

Turns out we can do both with little manipulation on launch configurations. Let’s see how.

Configure debug symbols

Usually Qt debug symbols are distributed alongside libraries, so there’s no real need to explicitly configure debug symbols paths. If that’s not the case, you can configure the debug symbols path by setting the "symbolSearchPath" property on a launch configuration. This property is a string and contains a list of paths separated by a semicolon.

"symbolSearchPath": "otherSearchPath;C:/Qt/5.12.4/msvc2017_64/bin"

This of course can be useful for adding debug symbols for other libraries too.

Source mapping

If the source directory for your Qt differs from the actual source directory (or directories) used while building it, you can configure the debugger to resolve those paths correctly. This happens for instance with binary Qt releases on Windows. You can enable source mapping in launch configurations by adding the "sourceFileMap" property. This property requires an object where each key is the source folder as it’s provided by the debug symbols, and the corresponding value is the path where the source code is in your system. This is how it can be configured for a binary Qt release on Windows:

"sourceFileMap": {
    "C:/work/build/qt5_workdir/w/s": "C:/Qt/5.12.4/Src",
    "Q:/qt5_workdir/w/s": "C:/Qt/5.12.4/Src",
    "C:/Users/qt/work/install": "C:/Qt/5.12.4/Src",
    "C:/Users/qt/work/qt": "C:/Qt/5.12.4/Src"
}
Using Natvis for Qt aware objects visualization

Natvis is a Visual Studio framework that allows you to customize how native C++ objects are visualized in the debugger. Natvis visualization rules are specified through xml files with a specific schema. A natvis file lists visualization rules for each C++ type, and every visualization rule consists in a series of properties. Such properties are meant to be user friendly and will be displayed on the debug window when visualizing objects of the corresponding type.

To name a few examples, a QString is visualized as the string it contains and has a size property and a number of items corresponding to its characters, and QRect will have a width and a height property instead of just the bare (and less intuitive) internal representation of the top left and bottom right points (x1, y1, x2, y2).

If you want to enable natvis in a debug run, just set the "visualizerFile" property in your launch configuration so that it points to the natvis file.

"visualizerFile": "path/to/qt5.natvis"

Debug pane before and after configuring natvis

You can find a ready to use natvis file for Qt 5 at this link.

Updating the code model

In order to be able to navigate Qt headers and enable IntelliSense for the Qt API, it’s enough to adjust the C++ settings for our project (c_cpp_properties.json) by adding the Qt include folder (and all its subfolders):

{
  // ...
  "includePath": [
    // ...
    "C:/Qt/5.12.4/msvc2017_64/include/**"
  ]
}

If you’re working on a CMake project, it’s also possible to use the CMake plugin as a configuration provider. Doing so, include paths and defines will be bound to the currently configured CMake build, and won’t need to be specified manually. This simplifies the C++ properties file considerably, as it’s shown in the example below:

{
  "configurations": [
    {
      "name": "Win32",
      "intelliSenseMode": "msvc-x64",
      "configurationProvider": "vector-of-bool.cmake-tools"
    }
  ],
  "version": 4
}

A note about using Visual Studio compilers on Windows

Visual Studio provides batch files that automate the environment setup necessary to use their C++ compiler and linker. In the last post we saw how it’s possible to configure a task so that it sets up the environment through the vcvars.bat script before running a command.

However, if you need to configure the environment with vcvars.bat for most of your build steps, it is also possible to configure Visual Studio Code so that it runs the batch file for every task. To do so, you need to tweak the configured shell (which is powershell by default on windows) and pass a few args. The setting name for doing this is “terminal.integrated.shellArgs.windows” and it’s set as follows:

"terminal.integrated.shellArgs.windows": [
  "Invoke-BatchFile 'C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Auxiliary/Build/vcvars64.bat' amd64",
  "; powershell"
]

What’s going on here is this: Visual Studio Code will launch by default every shell task by calling this command:

powershell <terminal.integrated.shellargs.windows> -Command <task command> <task argument list>

So, if you set “terminal.integrated.shellArgs.windows” this way, the final command will look like this:

powershell Invoke-BatchFile 'path/to/vcvars' ; powershell -Command <task command> <task argument list>

As a result, task commands will be effectively run in a powershell with the right environment set.

And that’s it for now. Many new things on the table, and some advanced features too. Hopefully this will help you with your workflow.

But there is still more to say, so make sure you don’t miss the next post!

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 Using Visual Studio Code for Qt Applications – Part Two appeared first on KDAB.

]]>
https://www.kdab.com/using-visual-studio-code-for-qt-apps-pt-2/feed/ 0 22669
Using Modern CMake with Qt https://www.kdab.com/using-modern-cmake-with-qt/ https://www.kdab.com/using-modern-cmake-with-qt/#respond Mon, 25 May 2020 15:52:03 +0000 https://www.kdab.com/?p=24101 KDAB’s Kevin Funk presented Using Modern CMake with Qt at Qt Virtual Tech Con last month. He reported that the Qt Company did a great job moderating the sessions at this event, and there was a lively Q&A at the end – Kevin had to pick from about 60 questions, so this is a hot […]

The post Using Modern CMake with Qt appeared first on KDAB.

]]>
KDAB’s Kevin Funk presented Using Modern CMake with Qt at Qt Virtual Tech Con last month.

He reported that the Qt Company did a great job moderating the sessions at this event, and there was a lively Q&A at the end – Kevin had to pick from about 60 questions, so this is a hot topic.

Now the event is over you can access Kevin’s talk here, including the answers he had time for, and also his slides, below the abstract.

Using Modern CMake with Qt with Kevin Funk

Prerequisite: No prior CMake experience required

CMake is a cross-platform build system, with powerful APIs for finding dependencies of various or specific versions, and with many abstractions for platforms, compilers, other build systems, and dependencies.

The next major Qt version, Qt6, will be using CMake internally as its build system, so the CMake integration with Qt will likely get tighter and more versatile in the long-term.

In this talk, we’ll be introducing Qt specific CMake functionalities, in order to find and use Qt5 inside your personal CMake-based project, using modern CMake capabilities. We are going to discuss how to find Qt installs using CMake’s find_package function and how to find specific Qt versions when multiple versions are installed.

Further than that, useful CMake variables such as CMAKE_INCLUDE_CURRENT_DIR, CMAKE_AUTOMOC, CMAKE_AUTORCC, and CMAKE_AUTOUIC will be explained in detail and how the use of the CMake integrations can speed up the build drastically.

Last but not least some of the additional supplied Qt related CMake functions, such as for big resources or translation support will be discussed.

Target audience: Build Engineers or Software Engineers who would like to know more about using Qt under CMake.

Download Kevin’s slides: QTVTC20 – Using Modern CMake – Kevin Funk

About Kevin Funk

Kevin has actively developed with Qt/C++ since 2006 and has a special interest in tooling and profiling. He’s an active contributor to KDAB’s GammaRay analyzer (a high-level Qt application debugger) and has a strong emphasis on state machine tooling. He is a co-maintainer of the KDevelop IDE, a powerful C/C++ development environment backed by Clang, and is pushing for cross-platform success inside KDE. Kevin holds a Masters Degree in Computer Science.

Download Kevin’s whitepaper on CMake and Qt…

The post Using Modern CMake with Qt appeared first on KDAB.

]]>
https://www.kdab.com/using-modern-cmake-with-qt/feed/ 0 24101
Automating tasks in Qt Creator https://www.kdab.com/automating-tasks-in-qt-creator/ https://www.kdab.com/automating-tasks-in-qt-creator/#comments Thu, 21 May 2020 09:00:23 +0000 https://www.kdab.com/?p=23489 My first project when I entered KDAB was the migration of a multi-million lines Motif application to Qt… feels quite scary said like that. Fortunately, migrations from any toolkit to Qt is something KDAB has been doing from the beginning, and has lots of experience with. You may be wondering what this has to do […]

The post Automating tasks in Qt Creator appeared first on KDAB.

]]>
My first project when I entered KDAB was the migration of a multi-million lines Motif application to Qt… feels quite scary said like that. Fortunately, migrations from any toolkit to Qt is something KDAB has been doing from the beginning, and has lots of experience with.

You may be wondering what this has to do with automating tasks in Qt Creator, or why I have a new entry in my Qt Creator locator… keep up with me and everything will be clear shortly.

Qt Creator Locator showing the Run Script selected

Automate all things

There are several rules you have to follow when doing a migration project, but the most important ones are probably those two:

  • Do not mix migration and refactoring
  • Automate all things

The second one is true for everything (remember, a good developer is a lazy developer), but it’s particularly important when doing a migration, as you don’t want to rewrite all single lines in a multi-million lines application by hand.

At that time, I was introduced to the wonderful world of XEmacs and Lisp scripting. During the course of the migration, I spent hours writing Lisp scripts to automate some parts of the migration, some with general purpose (used everywhere), others with a very narrow focus (only used once for one file). Coming from Windows and Microsoft Visual Studio 6 at the time, this was quite a new way to work for me.

Then slightly after this migration project, Qt Creator was released. As much as I like XEmacs and vim (and we all know which one is the best 🙂 ), having a real IDE makes development so much easier, and Qt Creator was adopted quickly inside KDAB.

The road to automation in Qt Creator

Even if we are using Qt Creator, we still need to automate as much as possible, particularly when doing migration projects.

The Macro plugin

My first try was the creation of the macro plugin, contributed to Qt Creator in version 2.2.0. For those who know it, the name is inspired by the macro feature in Notepad++ (also a very nice editor at the time – Windows only). The plugin allows you to save and replay user inputs:

  • Start recording using Alt+[
  • Navigate, search, write code
  • Stop recording using Alt+]
  • Then replay the macro using Alt+R

If you want to reuse a macro between session, it’s possible to save it, call it using the locator (the rm shortcut – “run macro” – probably not really used) or even assign a shortcut.

Though a nice step toward automation, it’s still far from perfect, as a macro doesn’t understand code semantics (it’s only user inputs), and not everything can be recorded: for example completion is not recorded in the macro, as it’s not a user input.

The Scripting plugin

Following the macro plugin, our second iteration was the creation of a plugin allowing us to write and run scripts, like you could do with Lisp and XEmacs. At the time, Qt Script was still nice and shiny, so it was based on it and the scripts were written in javascript. Like for macros, you can run scripts using the locator, or even assign shortcuts to useful scripts.

Here is a small script commenting out the function the cursor is in, while keeping the cursor at the same position:

var editor = editors.current()
var start = editor.createMark()

editor.gotoPosition(editor.currentFunction.start)
editor.find("{")

var startOfFunction = editor.position()
editor.gotoBlockEnd()
editor.gotoLineStart();
editor.insert("*/\n")
editor.gotoPosition(startOfFunction)
editor.insert("\n/*")

editor.gotoPosition(start)

As you can see, it’s straightforward, and it has some semantic information of the code (editor.currentFunction for example). You have access to a wide range of APIs for scripting:

  • Access and handling of editors (text, C++ editors)
  • Code navigation
  • Files, file infos, directories
  • Semantic data
  • Git actions

It’s actually way better than macros, and to be honest I now only use macros locally, I never save them anymore.

This plugin is used for our Photon to Qt or MFC to Qt migrations.

The Scripting plugin… but better

Lately, we reviewed the scripting plugin and checked what could be improved:

  • It is based on the dying Qt Script module
  • It’s not possible to interact with the script

Back to the drawing board, coming from Qt Script/javascript the natural way forward is Qt Declarative/QML. Our new scripting plugin is now based on the QQmlEngine, and now supports user interactions.

A glimpse into our Qt Creator Scripting plugin

As said, the new plugin is now based on the QQmlEngine, opening a wide array of new features to us.

Script types

There are now two different script types one can use, depending on the needs:

  • javascript (*.js): automation without user interactions
  • QML (*.qml): automation, which allows us to add user interaction and visual UI

For the javascript scripts, it’s close to what was possible with the previous scripting plugin based on Qt Script, the only difference is that we require a main function.

function main() {
    message.log("This is a log line: message.log(...)")
}

A QML script uses the same API, but allows more freedom, as you can now add a UI to it (using QtQuick) and/or add user interaction with the mouse and keyboard. Here is a small example of a script adding a header to the current file (it could have been done with a javscript script too, it’s just an example):

import QtQml 2.2
import Script 1.0

Script {
    property var mark

    function init() {
        mark = editor.createMark()
        editor.gotoDocumentStart()
        editor.insert("/****************************************************************************\n")
        editor.insert("/* Copyright (C) " + Qt.formatDate(new Date(), "yyyy") + " Klaralvdalens Datakonsult AB. All rights reserved.\n")
        editor.insert("** This file is part of the ACME project.")
        editor.insert("\n**********************************************************************/\n\n")
        m.restore()
        Qt.quit()
    }
    TextEditor {
        id: editor
        fileName: Editors.currentFileName
    }
    Component.onCompleted: init()
}

User interaction

One of the benefits of having QML scripting is the availability of handling user interaction on an editor: as a script creator, you can easily handle key or mouse inputs on an editor:

import QtQml 2.2import Script 1.0
TextEditor {
    id: editor
    fileName: Util.mktemp("foo_XXXXXX.txt")

    KeyHandler {
        key: Qt.Key_Left
        filter: true
        onKeyPressed: doSomething()
    }
    MouseHandler {
        onClicked: doSomethingElse()
    }
    // ...
}

Which ultimately leads you to write a game (actually 2: whack-a-mole and follow-path):

Conclusion

As someone said once: developers are lazy, and that’s (usually) a good thing. It certainly took us some time to develop the different plugins, but it’s paying off. It’s also more fun to write a tool to automate the work than doing the work itself.

For now the scripting plugin is internal to KDAB, let us know if that’s something you would be interested in.

You can download a KDAB whitepaper on Migrations 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 Automating tasks in Qt Creator appeared first on KDAB.

]]>
https://www.kdab.com/automating-tasks-in-qt-creator/feed/ 4 23489
Why is my screen still black https://www.kdab.com/why-is-my-screen-still-black/ https://www.kdab.com/why-is-my-screen-still-black/#respond Mon, 18 May 2020 09:00:55 +0000 https://www.kdab.com/?p=23340 Part 2 If you are here from Part 1, welcome back. If you are wondering why we started at Part 2, go to Part 1. So, you tried everything from the first part (that was relative to you), and your screen is still a backlighting test? No problem. (Well.. I mean, clearly there is but […]

The post Why is my screen still black appeared first on KDAB.

]]>
Part 2

If you are here from Part 1, welcome back. If you are wondering why we started at Part 2, go to Part 1.

Black Screen

Uncanny Valley!

So, you tried everything from the first part (that was relative to you), and your screen is still a backlighting test? No problem. (Well.. I mean, clearly there is but you know what I mean) We’ve gathered another five reasons this could be happening and how to go about fixing them.

Issue 6: Directional light is pointing in the wrong direction.

There are a few choices when it comes to choosing a light source for your scene. You can even add more than one. So we have Point lights, Directional lights, Spot lights and Area lights. You can then also have emissive textures that will act as a light source. Some of these get tricky… say, if you have a Spot or Directional light, you have to make sure they are pointing at something. For testing, you can always have a point light in the scene but even with these, you have to make sure they won’t be ‘inside’ an object, aren’t black and have a decent brightness.

Issue 7: It’s so dark in here. Did you not turn any lights on?

If using a lighting model, ensure the lights are actually enabled. A good test here is to set a temporary glClearColor (eg pink) – this will usually show un-lit geometry as black. Another solution is to set an ambient colour term and/or changing the background colour to something lighter.

Issue 8: Are you supplying enough power to your Raspberry Pi 4?

The Raspberry Pi 4 has dual HDMI outputs. Using the Qt EGLFS backend, these are available as different displays – so can run two different Qt applications, one full-screen on each. But if your system is near the limits of its power supply (and the onboard power monitor is quite picky, on the Pi) – the second display might fail to initialise. When debugging this problem, we initially tested different OpenGL backends and QPA plugins, but none of these made any difference. Very occasionally both displays would work, but mostly the second one would fail to initialise with an EGL error. A beefier power supply fixed the problem immediately. (Sometimes, it’s really not a software problem)

Issue 9: The GL context won’t create.

This can happen for instance if you upgrade your drivers (especially common with Linux and NVidia cards) and don’t reboot, there’s a high chance that your system won’t be able to create a GL context anymore. To make sure that this is the issue, start a simple 3D program such as glxgears. If it does not work, only one solution : reach for that restart button.

For more info, see: Checkliste Allgemein (German)

Issue 10: Return of the mac. – You’re using the wrong profile

OpenGL has been around for a while and has many version. Maybe you are using something that requires a more recent version of OpenGL? One thing that is more subtle, especially when updating old code to more modern practices, is the concept of profile. As of 3.2, contexts can be created with a Core profile or a Compatibility profile. The latter preserves compatibility with older fixed function pipeline code and settings. However, it is optional for drivers to implement that profile. Apple, in its wisdom, has decided not to do so. So if you ask for a Compatibility profile, it will create a 2.1 context, and you will not be able to use 3.0 or later features.

So, make sure Core profile is enabled, on the default QSurfaceFormat instance.

Other cross-platform issues are quite common. For example, NVIDIA drivers tend to be forgiving and accept using texture2D() in shaders even though it should not be allowed in a Core profile. So test on as many platforms and driver setups you can lay your hands on.

Once you’ve double checked the camera settings, shaders and your model settings, 6, 7, 8, 9, and 10, you should be good to go! If not, why not comment your issue below and we’ll try to get it in the next part.

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 is my screen still black appeared first on KDAB.

]]>
https://www.kdab.com/why-is-my-screen-still-black/feed/ 0 23340
KDAB at Qt Virtual Tech Con https://www.kdab.com/kdab-at-qt-virtual-tech-con/ https://www.kdab.com/kdab-at-qt-virtual-tech-con/#respond Wed, 29 Apr 2020 12:15:06 +0000 https://www.kdab.com/?p=23492 Since the postponement of Qt World Summit this May 12-14, The Qt Company decided to host a virtual one in its place called Qt Virtual Tech Con. The event offered talks you won’t hear in October, virtual exhibits, and Q&As online, for free. KDAB’s Kevin Funk presented Using Modern CMake with Qt and we showed […]

The post KDAB at Qt Virtual Tech Con appeared first on KDAB.

]]>
Since the postponement of Qt World Summit this May 12-14, The Qt Company decided to host a virtual one in its place called Qt Virtual Tech Con. The event offered talks you won’t hear in October, virtual exhibits, and Q&As online, for free.

KDAB’s Kevin Funk presented Using Modern CMake with Qt and we showed a demo in the Virtual Exhibition: Lufthansa Technik Takes Qt into the Skies.

You can access all the talks and download Kevin’s slides here.

Using Modern CMake with Qt with Kevin Funk

Prerequisite: No prior CMake experience required

CMake is a cross-platform build system, with powerful APIs for finding dependencies of various or specific versions, and with many abstractions for platforms, compilers, other build systems, and dependencies.

The next major Qt version, Qt6, will be using CMake internally as its build system, so the CMake integration with Qt will likely get tighter and more versatile in the long-term.

In this talk, we’ll be introducing Qt specific CMake functionalities, in order to find and use Qt5 inside your personal CMake-based project, using modern CMake capabilities. We are going to discuss how to find Qt installs using CMake’s find_package function and how to find specific Qt versions when multiple versions are installed.

Further than that, useful CMake variables such as CMAKE_INCLUDE_CURRENT_DIR, CMAKE_AUTOMOC, CMAKE_AUTORCC, and CMAKE_AUTOUIC will be explained in detail and how the use of the CMake integrations can speed up the build drastically.

Last but not least some of the additional supplied Qt related CMake functions, such as for big resources or translation support will be discussed.

Target audience: Build Engineers or Software Engineers who would like to know more about using Qt under CMake.

 

About Kevin Funk

Kevin has actively developed with Qt/C++ since 2006 and has a special interest in tooling and profiling. He’s an active contributor to KDAB’s GammaRay analyzer (a high-level Qt application debugger) and has a strong emphasis on state machine tooling. He is a co-maintainer of the KDevelop IDE, a powerful C/C++ development environment backed by Clang, and is pushing for cross-platform success inside KDE. Kevin holds a Masters Degree in Computer Science.

Download Kevin’s whitepaper on CMake and Qt…

The post KDAB at Qt Virtual Tech Con appeared first on KDAB.

]]>
https://www.kdab.com/kdab-at-qt-virtual-tech-con/feed/ 0 23492
An engineer answers the doorbell https://www.kdab.com/an-engineer-answers-the-doorbell/ https://www.kdab.com/an-engineer-answers-the-doorbell/#respond Tue, 28 Apr 2020 09:00:23 +0000 https://www.kdab.com/?p=23378 Due to Covid-19, the KDAB office in Berlin feels really empty.  Some times, it’s just me, working on hardware, and a few other guys dotted around. The office staff are all working from home. The Problem My office is very far away from the door, yet, from time to time, KDAB gets deliveries and, as […]

The post An engineer answers the doorbell appeared first on KDAB.

]]>
Due to Covid-19, the KDAB office in Berlin feels really empty.  Some times, it’s just me, working on hardware, and a few other guys dotted around. The office staff are all working from home.

The Problem

My office is very far away from the door, yet, from time to time, KDAB gets deliveries and, as I’m always there, while others come and go, people ask me if I can receive the parcels. I figured it would be cool if I could somehow stay at my desk and get notified if someone rings the bell.

Hmmm…

Some years back, we had fixed up a make-do basic doorbell to cover a period of time when our normal one wasn’t working. doorbellThis ‘formerly temporary doorbell’, is still in place glued over the original doorbell. You can see it here. It’s a standard remote-controlled device and operates on very common frequencies. You can also see a bit of the label on the bell and the cable coming out of it where I added a new power supply to get it working again, since the original, non-standard battery was running low and we did not have another one lying around. So far so good…

My first idea was to connect a default, very cheap, rf433 receiver to the bell and set it closer to my office so I’d be sure to hear it. There are dozens of projects around on-line for this, like this one, using Arduino and/or raspberry pi, and I knew some of my colleagues had already played around with this technology, so I soon found what I needed here in the office.

It didn’t take long to connect the receiver to a raspberry pi and get it to receive the messages sent from the doorbell. Nice.

Until I realized it only worked when it was 10cm away from the bell, with no obstacles in between! It definitely wasn’t going to work through walls :/.

Not to be thwarted, I knew I had a different module at home with a chip which already had protocol parsing inside. The only problem is, there seems to be no implementation rights for pre-build on the raspberry pi, other than Arduino.

I complained about this in our internal chat channel, and a couple of my colleagues jokingly suggested I use a software-defined radio(SDR). I told them I always carry such a thing in my backpack. The guys thought I was joking, but it’s true! its a DVB-T2 USB stick.

Next day I looked into it…

My solution

There’s not much to see really. I took an Astrometa DVB-T2 and a raspberry pi to operate it. Then I used rtl_433 to receive the doorbell signal via rtl-sdr.

close-up raspberry pi and USB

The signal then pings the chat channel. Perfect!

Someone is at the Door

The details

The rtl_433 project has dozens of decoders of various standard protocols, including the one used by our doorbell. It’s possible to output received data as json, so I set it up to do that. Then I added some glue node.js code to parse the json followed by a webhook to our internal chat. The code is really ugly so I’m definitely not showing it here, but it seems to work :-).

Finally, I tried using an old stick which I had lying around at home to support the DVB-T, but it seems that the stick cannot receive it as well as the DVB-T2 one. Furthermore, since, by this time, I had added an additional doorbell so I could also hear the bell from the other door in the office, (meaning it needed to receive from two places), I stuck with the DVB-T2 one for now, so I didn’t really need the extra stick.

Conclusion

The system has already proven itself, I have already picked up parcels from DHL/UPS and others while staying in my office. It might still be useful when the crisis is over as, after admin hours, we have the problem that the developers who prefer to work later cannot hear the doorbell. But, so that the bell isn’t disturbing to developers (or indeed myself!) when there are staff at the office to answer the door, I will probably have to change it a bit so it’s less noisy :-).

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 An engineer answers the doorbell appeared first on KDAB.

]]>
https://www.kdab.com/an-engineer-answers-the-doorbell/feed/ 0 23378
Demos at Qt World Summit 2020 https://www.kdab.com/demos-at-qt-world-summit-2020/ https://www.kdab.com/demos-at-qt-world-summit-2020/#respond Thu, 23 Apr 2020 16:44:28 +0000 https://www.kdab.com/?p=23347 Qt World Summit 2020 in Palm Springs, CA has been postponed and the new date is October 20-22. KDAB will be Gold Sponsor. As well as a range of talks and 3 one-day training classes, we will also present an array of exciting demos in the KDAB booth. Check them out! KDAB Demos at Qt […]

The post Demos at Qt World Summit 2020 appeared first on KDAB.

]]>
Qt World Summit 2020 in Palm Springs, CA has been postponed and the new date is October 20-22.

KDAB will be Gold Sponsor. As well as a range of talks and 3 one-day training classes, we will also present an array of exciting demos in the KDAB booth. Check them out!

KDAB Demos at Qt World Summit, 2020

Speidels Braumeister

  • UI and process control for a home brewing appliance
  • Rich and intuitive Qt Quick frontend
  • Adapted to cost-effective hardware
  • Yocto-based platform customization
  • KDAB provided full-stack support from BSP to UI effects

Unu Dashboard for electric scooter

  • Navigation framework integrated with Qt Quick scene
  • Speedometer implemented using OpenGL shaders
  • Running on a Yocto-based platform

Watch the video

Download the Case Study

KUESA™ 3D Runtime on i.MX 8M

  • Performance optimized real-time rendering
  • Streamlined integration of 3D content from DCC like Blender
  • Seamless integration into Qt / QML / Qt 3D
  • Intuitive/artistic approach of defining new “Iro Materials”

Watch a tutorial on Kuesa

QiTissue: Big data and image visualizer

  • 2D and 3D visualization from cutting edge clinical diagnostics data sets
  • Efficiently handles gigabytes of data
  • Integrates scientific image processing and analysis
  • Built on top of Qt Widgets, Qt Graphics View, Qt Quick, and Qt 3D
  • Embedded on a Linux Tegra board (3D)

Watch the video…

KDAB Profiling and Analysis Tools

tooling and profiling kdab

 

New demo coming soon!

 

The post Demos at Qt World Summit 2020 appeared first on KDAB.

]]>
https://www.kdab.com/demos-at-qt-world-summit-2020/feed/ 0 23347
Why is my screen black? https://www.kdab.com/why-is-my-screen-black/ https://www.kdab.com/why-is-my-screen-black/#respond Mon, 20 Apr 2020 09:00:48 +0000 https://www.kdab.com/?p=23137 Part 1 So, you’ve just poured your heart and soul into some real-time 3D rendering code and hit render. Wringing your hands in anticipation you wait for the screen to show your marvellous creation. Still… waiting. It says it’s done but, nothing. Well, maybe not nothing but simply darkness. You stare into the deep dark […]

The post Why is my screen black? appeared first on KDAB.

]]>
Part 1

So, you’ve just poured your heart and soul into some real-time 3D rendering code and hit render. Wringing your hands in anticipation you wait for the screen to show your marvellous creation. Still… waiting. It says it’s done but, nothing. Well, maybe not nothing but simply darkness. You stare into the deep dark void as your own reflection stares back at you.

Black Screen

Your beautifully rendered item

So, what went wrong?

Issue 1: The rendered object is actually, like some good old English Panto, “behind you!”

This is usually a common issue for the first render. It’s easy to overlook the Z position of the camera and even which way the camera was facing. There are then issues of various libraries and programs using different coordinate systems. OpenGL, for example, looks along the negative Z axis whilst Direct3D uses the positive.

Also if it’s a planar piece of geometry such as a quad to be used as a sprite, ensure that you are not rendering it exactly edge on. Yes we’ve done this too!

Try setting your window clear color to something other than black. That way even if your fragment shader (see later) is broken and outputting all fragments as black you will at least see the silhouette of the object.

Issue 2: You’re inside the object!

So, a few things can be at play here. First of all make sure the coordinates of the camera aren’t the same or too close to the item(s) you are rendering, like with Issue 1. However, you should also double check the ‘model units’. Is the model using mm instead of m, for example. This can be a common issue with shared or imported models.

Once you’ve checked the relative positions and orientation of your camera, also check that the object falls within the limits of the view frustum’s near and far planes.

Issue 3: Your triangle winding could be backwards.

If your winding order is opposite to what you expect and you have back or front face culling enabled then the rasterizer may not be generating any fragments for your object at all.

A fix for this would be to use a tool such as GammaRay or Apitrace to check geometry. In OpenGL you can also disable culling via glDisable(GL_CULL_FACE).

Issue 4: Shaders – are they compiling and linking? Are you feeding them the correct resources?

Make sure that #version is the very first token – no new lines, or anything of the sort before, as some drivers check that religiously. Have your application code check for compilation and linker failures and output any errors. Often it is simple syntactical errors or issues with the interface between shader stages. Also check that your shader stages are outputting exactly what you expect. For fragment shaders, output intermediate variables as a color to see what is going on.

Also use tools such as apitrace, renderdoc or nSight to introspect frames and check that you really have bound the correct set of buffers and textures.

Issue 5: Qt 3D specific: No techniques matched the actual renderer.

When building Qt 3D scenes that are designed to run on multiple platforms, materials need to provide multiple shaders targeting each specific version of OpenGL. Each version information is stored on QTechnique nodes attached to a QEffect node. Similarly, you can implement different algorithms (forward vs deferred rendering for example), so they get assigned filter keys which are key/value pairs. Finally, some algorithms require multiple passes, but may use different shaders in different passes. This pass information is stored in QRenderPass nodes (attached to the technique), also using filter keys.

When Qt 3D comes to do the render it needs to select the technique based on the available hardware. It will also need to select the technique appropriate to the rendering algorithm that is used. And when it processes each render pass, it will also need to select the appropriate shader based on the render pass. This can be controlled by building a frame graph which QTechniqueFilter nodes and QRenderPassFilter nodes.

You can find a more detailed explanation here.

A common source of “not seeing anything” (or missing some objects) is not providing valid shaders for a specific combination of active technique and current render pass.

In order to help debug this, the new debugging overlay introduced in Qt 3D 5.15 provides a way of dumping the filter state of the scene graph and frame graph which helps understand why some object may not be renderer. It will dump technique details only for the active graphics API (i.e. if you’re running on the desktop, it will not show details relative to OpenGL ES techniques).

For example, here’s a dump of the information for a very simple scene using the default forward renderer:

Active Graphics API: OpenGL 4.1 (Core Profile) (ATI Technologies Inc.)
Render Views:
  1 [ Qt3DExtras::QForwardRenderer <renderingStyle: forward> ]
Scene Graph:
  Qt3DCore::Quick::Quick3DEntity{1}
    Qt3DRender::QCamera{13}
    Qt3DExtras::QOrbitCameraController{16}
    Qt3DCore::Quick::Quick3DEntity{75} [ T <renderingStyle: forward>  ]
    Qt3DCore::Quick::Quick3DEntity{86} [ T <renderingStyle: forward>  ]

This shows the active technique (desktop OpenGL on macOS); the technique filter used in the frame graph (QForwardRenderer is derived from QTechniqueFilter); the details of which matching techniques are assigned to materials.

So, once you’ve double checked the camera settings, shaders and your model settings, go again and you should be bright as rain!

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 is my screen black? appeared first on KDAB.

]]>
https://www.kdab.com/why-is-my-screen-black/feed/ 0 23137
Qt, range-based for loops and structured bindings https://www.kdab.com/qt-range-based-for-loops-and-structured-bindings/ https://www.kdab.com/qt-range-based-for-loops-and-structured-bindings/#comments Fri, 17 Apr 2020 09:00:19 +0000 https://www.kdab.com/?p=23179 Qt has a long history. The first stable version was released before the first version of C++ was standardized and long before the different C++ compiler vendors started shipping usable implementations of the C++ standard library. Because of this, Qt often followed (and still follows) some design idioms that feel unnatural to the usual C++ […]

The post Qt, range-based for loops and structured bindings appeared first on KDAB.

]]>
Qt has a long history. The first stable version was released before the first version of C++ was standardized and long before the different C++ compiler vendors started shipping usable implementations of the C++ standard library. Because of this, Qt often followed (and still follows) some design idioms that feel unnatural to the usual C++ developer.

This can have some downsides for the Qt ecosystem. The evolution of the C++ programming language which sped up quite a bit in the last decade often brings improvements which don’t fit well with the Qt philosophy. In this blog, I offer some ways to work with this.

Range-based for loops

C++11 brought us the range-based for loop which allows easy iteration over any iterable sequence, including common containers such as std::vector, std::map, etc.

for (auto name: names) {
    // ...
}

When you write code like the above, the compiler (C++11) sees the following:

        {
            auto && __range = names;
            for (auto __begin = begin(names), __end = end(names); __begin != __end; ++__begin) {
                auto&& name = *__begin;
                // ...
            }
        }

It takes the begin and end iterators of the names collection, and iterates from one to the other.

Rather simple, but it is a very nice syntactical improvement to the language — it is a significant reduction of boilerplate code and much easier on the eyes.

But, it was not designed with Qt collection classes in mind. You can check out the “Goodbye, Q_FOREACH” blog post by Marc for one example where the range-based for loop collided with the Qt design principles, most notably with the copy-on-write feature because of which we got the qAsConst helper function.

Structured bindings

Another new feature, this one from C++17, are the structured bindings.

They add syntactic sugar for decomposing structures. For example, if we have a function that returns a pair of values (std::pair or a QPair) we can declare variables that refer to the values inside of the pair instead of having to access them through .first and .second.

        auto [x, y] = mousePosition();

This can significantly improve code readability. In the previous example, the names x and y communicate the meaning much better than .first and .second would.

This is even more the case if we use a function like QMultiMap::equal_range which returns a pair of iterators delimiting the range of values that are stored under a specified key in a QMap. Seeing participants.equal_range("kdab").second would look like we are accessing the second value in the map that is stored under the “kdab” key. If we used structured bindings, we could have sane variable names:

        auto [beginParticipant, endParticipant] = participants.equal_range("kdab");

Structured bindings can lead to quite succulent code when combined with the range-based for loops for iteration over STL-compliant map-like containers:

        for (auto [key, value]: stdMap) {
            // ...
        }

Each key-value pair in stdMap, will be stored in an invisible (unnamed) variable, and key and value will be references to its inner elements.

Sidebar: don’t be fooled by decltype(key) telling you key is a normal value, for all intents and purposes, it is a reference.

QHash, QMap and STL compatibility

Sadly, the previous code snippet can not work with Qt’s associative containers because the API is not compatible with that of std::map and similar containers.

The problem is in the API of the iterators for QHash and QMap. Instead of returning a key-value pair when you dereference the iterator, it returns only the value. This means that the range-based for loop can only iterate over the values stored inside of the collection, it can not (by default) access the keys:

        for (auto value: map) {
            // ...
        }

When we use the QHash and QMap iterators directly, we can access the key with .key() and the value with .value() but this does not help us with the range-based for loop. As we’ve seen, it is just a syntactic sugar which expands to an ordinary for loop that iterates over a collection automatically dereferencing (calling operator*()) the iterator in each iteration.

So, as far as the range-based for loop is concerned, the key and value member functions do not even exist.

This deficiency of the Qt’s associative containers’ API has been noticed, and QHash and QMap provide us with alternative, more STL-like, iterators since Qt 5.10 — the key_value_iterator and the const_key_value_iterator. When dereferenced, these iterators return a std::pair containing both the key and the value. To quote the Qt documentation:

The QMap::key_value_iterator typedef provides an STL-style iterator for QMap and QMultiMap.

QMap::key_value_iterator is essentially the same as QMap::iterator with the difference that operator*() returns a key/value pair instead of a value.

This means that we can use the structured bindings with them:

        auto [key, value] = *map.keyValueBegin();

But we still cannot use this with the range-based for loop to iterate over all key-value pairs in the collection. The range-based for loop will call .begin() and .end(), and not .keyValueBegin() and .keyValueEnd().

This is easily remedied by creating a simple wrapper over QHash and QMap that will rename .keyValueBegin() and .keyValueEnd() to .begin() and .end() like so:

        template <typename T>
        class asKeyValueRange
        {
        public:
            asKeyValueRange(T &data)
                : m_data{data}
            {
            }

            auto begin() { return m_data.keyValueBegin(); }

            auto end() { return m_data.keyValueEnd(); }

        private:
            T &m_data;
        };

Instead of passing a Qt associative container directly to the range-based for loop, we just need to pass it wrapped inside of the asKeyValueRange class, and we will finally be able to use the idiomatic C++17 way of iterating over key-value pairs with QHash and QMap:

        for (auto [key, value]: asKeyValueRange(map)) {
            // ...
        }

It is important to note that this is a somewhat simplified implementation of the asKeyValueRange wrapper that takes the reference to the original QHash/QMap, so it might lead to a dangling reference if used improperly.

Iteration over Qt SQL results

Another part of Qt that hasn’t been designed with common C++ idioms in mind is the Qt SQL module. Its API is designed as if it were a Java library and not a C++ one. Instead of having normal iterators over the results in the QSqlQuery, we need to use the .next() member function to fetch each result. The .next() member function returns a Boolean value denoting if there is another result, and the result itself is accessible through other QSqlQuery member functions.

Apart from the API, iteration over the QSqlQuery results has another difference to usual C++ iterators. The QSqlQuery does not need an end iterator to know whether there is another result available. If .next() or .isValid() return false, this means we have reached the end of the result set.

Having the iterator itself know when it has reached the end of the collection it belongs to is uncommon in STL, but it still is present. The input stream iterator (std::istream_iterator) is one such beast. We cannot know in advance where the end of an input stream is, we can just read values from the stream until the read fails. We have reached the end when the read failed. Similar to to the QSqlQuery — we have reached the end when .next() fails — when it returns false.

In these cases, the end iterator is only needed to fulfil the STL iterator API. It is just a dummy object (usually called a sentinel) that will trigger the validity check on the main iterator when it != end is evaluated.

C++17 brought a small change to the range-based for loop meant for this exact use-case. When C++17 compiler sees the range-based for loop from the first code snippet we had, it will convert it to the following code:

        {
            auto && __range = names;
            auto __begin = begin(names);
            auto __end = end(names);
            for ( ; __begin != __end; ++__begin) {
                auto&& name = *__begin;
                // ...
            }
        }

The difference is easy to overlook.

        auto __begin = begin(names), __end = end(names)

is replaced by

        auto __begin = begin(names);
        auto __end = end(names);

While these two snippets look mostly the same, there is an important difference — in the first snippet, both __begin and __end need to have the same type whereas they can be different in the second.

This allows us to create a begin function that returns a powerful iterator that knows when it has reached the end of a collection, while the end function returns a dummy value — a sentinel.

The sentinel can be just a simple empty type:

        struct QSqlResultSentinel {};

        QSqlResultSentinel end(QSqlQuery& query)
        {
            return {};
        }

The iterator is where the main logic lies. For it to work with the range-based for loop, it needs to know how to do the following operations:

– It needs to have the operator++ that moves to the next result; – It needs to have the operator!= which takes a sentinel object and returns whether iterator is valid or not; – It needs to have the operator* that dereferences the iterator.

The basic implementation of the operator++ and operator!= would look like this:

        class QSqlResultIterator {
        public:
            QSqlResultIterator(QSqlQuery& query)
                : m_query(query)
            {
                m_query.next();
            }

            QSqlResultIterator& operator++()
            {
                m_query.next();
                return *this;
            }

            bool operator!=(QSqlResultSentinel sentinel) const
            {
                Q_UNUSED(sentinel);
                return m_query.isValid();
            }

            // ...

        private:
            QSqlQuery& m_query;
        };

        QSqlResultIterator begin(QSqlQuery& query)
        {
            return QSqlResultIterator(query);
        }

The only thing that remains is for us to decide what the dereference operator should do.

Since each record in the result can contain several values, it would be nice if we provided the operator[] to access those values. Therefore, when we dereference the QSqlResultIterator, we want to get a type that has operator[] defined on it which returns values from the current record.

We have several options on how to do this. The simplest, though not the cleanest, is to have the dereference operator return the reference to the iterator itself, and then define the operator[] in the iterator class.

        class QSqlResultIterator {
        public:
            // ...

            QSqlResultIterator& operator*()
            {
                return *this;
            }

            QVariant operator[] (int index) const
            {
                return m_query.value(index);
            }

            QVariant operator[] (const QString& name) const
            {
                return m_query.value(name);
            }
        };

If we weren’t interested in having the operator[] to access the values, then we could just return the current QSqlRecord with m_query.record() from the operator*().

While this is not a complete iterator implementation (we are missing iterator type traits and similar), it is sufficient for us to be able to use it with a range-based for loop:

        for (auto result: query) {
            qDebug() << result["name"] << result["surname"];
        }

We’ll see what we need to do in order to be able to use structured bindings with Qt SQL in the next part of this post.

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 Qt, range-based for loops and structured bindings appeared first on KDAB.

]]>
https://www.kdab.com/qt-range-based-for-loops-and-structured-bindings/feed/ 4 23179
Training at Qt World Summit 2020 https://www.kdab.com/training-at-qt-world-summit-2020/ https://www.kdab.com/training-at-qt-world-summit-2020/#respond Tue, 14 Apr 2020 13:39:01 +0000 https://www.kdab.com/?p=23228 Qt World Summit 2020 has been postponed until October 20-22. It will take place in Palm Springs, USA. KDAB will be running 3 one day training classes on October 20th: Advanced QML Multithreading in Qt, and Introduction to Qt 3D Let’s tell you a bit more about those classes before you sign up and catch […]

The post Training at Qt World Summit 2020 appeared first on KDAB.

]]>
Qt World Summit 2020 has been postponed until October 20-22. It will take place in Palm Springs, USA.

KDAB will be running 3 one day training classes on October 20th:

  • Advanced QML
  • Multithreading in Qt, and
  • Introduction to Qt 3D

Let’s tell you a bit more about those classes before you sign up and catch the extended Early Bird discount.

Advanced QML with Giuseppe D’Angelo

Prerequisite: Functional knowledge of QML (more than 1 year of experience)

The advanced QML course is designed to take programmers who already know QML to a deeper level of functional understanding and equips them with the cutting edge QML skills and know-how to boost their productivity at work.

Topics include:
  • Advanced integration of QML, JavaScript and C++
  • Using OpenGL in custom QML elements
  • Analysing and profiling the Qt Quick scene graph
  • Understanding and removing bottlenecks that affect a QML UI
  • Best practices for achieving optimal performances, even on constrained hardware resources

Target audience: Experienced QML developers targeting embedded and/or mobile platforms.

About Giuseppe D’Angelo

Senior Software Engineer at KDAB. Giuseppe is a long-time contributor to Qt, having used Qt and C++ since 2000, and is an Approver in the Qt Project. His contributions in Qt range from containers and regular expressions to GUI, Widgets and OpenGL. A free software passionate and UNIX specialist, before joining KDAB, he organized conferences on opensource around Italy. He holds a BSc in Computer Science.

Register here…

Multithreading in Qt with Jim Albamont

Prerequisite: Knowledge and experience programming with Qt and C++. A basic understanding of multithreaded programming is an advantage but not required.

Multithreaded programming is essential for developers to create fast and responsive applications on computers, phones, and embedded devices all with an increasing number of cores. Qt offers several mechanisms for multithreading; however, it can be difficult to know which to use and how to steer clear of common pitfalls. This course offers guidance how to write safe and efficient multithreaded code with Qt.

Topics include:
  • Basic multithreading concepts (threads, processes, data races, reentrency, shared data)
  • Synchronization primitives (mutexes, semaphores, condition variables)
  • Special concerns for Qt applications (cross-thread signals/slots, QObject thread affinity, the GUI thread)
  • Low-level multithreading with Qt (QThread, QThreadPool, QMutex, etc)
  • High-level multithreading with Qt (QtConcurrent)
  • A brief summary of atomic operations
  • Comparison between Qt and standard C++ multithreading programming

Target Audience: Qt Developers interested in multithreaded programming

About Jim Albamont

Senior Software Engineer at KDAB. Jim has actively developed with Qt since 2001. He has a background in computer graphics and data visualization, including 6 years as the lead developer of a multithreaded 3D visualization tool for financial data built with Qt and OpenGL. He has held Qt training classes throughout the US where he is based. Jim holds an MSc in Computer Science.

Register here…

Introduction to Qt 3D with Mike Krus

Prerequisite: This course requires use of Qt 5.7.1 or higher and assumes prior knowledge of Qt Quick. No prior OpenGL knowledge is required.

In this course you will learn Qt 3D and its use of modern programmable shader-based pipelines which can be applied to both OpenGL and OpenGL ES.

Topics include:
  • Drawing: Geometries, Materials and Lights
  • User Input: Picking, Keyboard Handling, Logical Devices
  • Integration and Helpers: Dynamic Scenes, QtQuick Integration
  • Scene Graph: Graphics Pipeline, GLSL, Coordinate Systems, Texturing
  • Frame Graph: Viewports, Layers, Selecting Shaders at Runtime, Post-processing Effects

Target audience: Developers who want to conveniently and efficiently integrate Qt 3D.

About Mike Krus

Senior Software Engineer at KDAB. Mike has been developing with C++ since 1996 and Qt since 2004. He has a broad range of experience in scientific applications, mainly in civil engineering and oil & gas industries. His range of expertise includes C++, QML and interactive 3D visualization software design on desktop and mobile as well as macOS development. Mike is the Qt maintainer for the tvOS platform, one of the core contributors to Qt 3D and is interested in building mobile applications with Qt, mainly on iOS. He has a PhD in Computer Science.

Register here…

KDAB trainers regularly contributes insights on Qt, OpenGL, 3D, C++ and more to KDAB blogs.

See what trainees say about our KDAB training.

The post Training at Qt World Summit 2020 appeared first on KDAB.

]]>
https://www.kdab.com/training-at-qt-world-summit-2020/feed/ 0 23228