KDAB at SIGGRAPH 2018

Yes, folks. This year SIGGRAPH 2018 is in Canada and we’ll be there at the Qt booth, showing off our latest tooling and demos. These days, you’d be surprised where Qt is used under the hood, even by the biggest players in the 3D world!

SIGGRAPH 2018 is a five-day immersion into the latest innovations in CG, Animation, VR, Games, Digital Art, Mixed Reality and Emerging Technologies. Experience research, hands-on demos, and fearless acts of collaboration.

Meet us at SIGGRAPH 2018!

The post KDAB at SIGGRAPH 2018 appeared first on KDAB.

Managing cooking recipes

I like to cook. And sometimes store my recipes. Over the years I have tried KRecipes, kept my recipes in BasKet notes, in KJots notes, in more or less random word processor documents.

I liked the free form entering recipes in various notes applications and word processor documents, but I lacked some kind of indexing them. What I wanted was free-ish text for writing recipes, and some thing that could help me find them by tags I give them. By Title. By how I organize them. And maybe by Ingredient if I don’t know how to get rid of the soon-to-be-bad in my refridgerator.

Given I’m a software developer, maybe I should try scratch my own itch. And I did in the last month and a half during some evenings. This is also where my latest Qt and modern C++ blog posts comes from

The central bit is basically a markdown viewer, and the file format is some semi structured markdown in one file per recipe. Structured in the file system however you like it.

There is a recipes index which simply is a file system view with pretty titles on top.

There is a way to insert tags into recipes.

I can find them by title.

And I can find recipes by ingredients.

Given it is plain text, it can easily be synced using Git or NextCloud or whatever solution you want for that.

You can give it a spin if you want. It lives here https://cgit.kde.org/scratch/sune/kookbook.git/. There is a blueprint for a windows installer here: https://phabricator.kde.org/D12828

There is a markdown file describing the specifics of the file format. It is not declared 100% stable yet, but I need good reasons to break stuff.

My recipe collection is in my native language Danish, so I’m not sure sharing it for demo purposes makes too much sense.

QtDay Italy, May 23-24

Once more in Florence, QtDay Italy is almost upon us and we’ll be there.

Giuseppe D’Angelo will be giving a talk on Gammaray, KDAB’s open source profiling and debugging tool.

GammaRay is a “high-level debugger”, able to show the status of various Qt subsystems inside an application, with an easy to use interface (that does not require any knowledge of Qt internals). GammaRay can, amongst other things, show the properties of any QObject in the application, show the status of all state machines, inspect and debug layouting and stacking of both widgets and Qt Quick applications, analyze raster painting, show the 3D geometry in a Qt3D scene, and much more.

This talk introduces the basics of GammaRay usage, with some interesting cases as examples of problem solutions.

See you in Florence!

The post QtDay Italy, May 23-24 appeared first on KDAB.

Where KDEInstallDirs points to

The other day, some user of Extra CMake Modules (A collection of utilities and find modules created by KDE), asked if there was an easy way to query cmake for wherever the KDEInstallDirs points to (KDEInstallDirs is a set of default paths that mostly is good for your system, iirc based upon GNUInstallDirs but with some extensions for various Qt, KDE and XDG common paths, as well as some cross platform additions). I couldn’t find an easy way of doing it without writing a couple of lines of CMake code.

Getting the KDE_INSTALL_(full_)APPDIR with default options is:

$ cmake -DTYPE=APPDIR ..
KDE_INSTALL_FULL_APPDIR:/usr/local/share/applications

and various other options can be set as well.

$ cmake -DCMAKE_INSTALL_PREFIX=/opt/mystuff -DTYPE=BINDIR ..
KDE_INSTALL_FULL_BINDIR: /opt/mystuff/bin

This is kind of simple, but let’s just share it with the world:

cmake_minimum_required(VERSION 3.0)
find_package(ECM REQUIRED)
set (CMAKE_MODULE_PATH ${ECM_MODULE_PATH})

include(KDEInstallDirs)

message("KDE_INSTALL_FULL_${TYPE}: " ${KDE_INSTALL_FULL_${TYPE}})

I don’t think it is complex enough to claim any sorts of copyrights, but if you insist, you can use it under one of the following licenses: CC0, Public Domain (if that’s in your juristiction), MIT/X11, WTFPL (any version), 3-clause BSD, GPL (any version), LGPL (any version) and .. erm. whatever.

I was trying to get it to work as a cmake -P script, but some of the find_package calls requires working CMakeCache. Comments welcome.

QtKNX updates for 5.11

It has been a while since our last KNX development blog post, so we would like to give you a quick glance into some of the updates in QtKNX that are coming with the 5.11 release.

API improvements

One of the main improvements in this update was making Qt KNX’s object introspection and construction more intuitive. To deal with the high number of specializations needed for the KNXnet/IP frame, we’ve included the proxy pattern. For example, the information carried by a KNXnet/IP connection request frame can be accessed by the QKnxNetIpConnectRequestProxy class.

Here is an example of how to use it while implementing the KNXnet/IP server side receiving a connection request frame:

QKnxNetIpFrame frame = //...;
QKnxNetIpConnectRequestProxy request(frame);
if (!request.isValid())
  return;

auto ctrlEndpoint = request.controlEndpoint();
auto dataEndpoint = request.dataEndpoint();
auto cri = request.requestInformation();

Because the frame is a structure that has many fields, having to know the exact order of parameters that can be passed to the constructor makes it difficult to use correctly. To make this easier, we have introduced the builder pattern. It allows us to encapsulate the construction and thus provide a more flexible solution.

Here is an example demonstrating the benefits of using the QKnxNetIpConnectRequestProxy::builder() instead of the constructor call to the QKnxNetIpConnectRequestProxy:

auto frame = QKnxNetIpConnectRequestProxy::builder()
             .setControlEndpoint(hpai)
             .setDataEndpoint(hpai)
             .create();

The proxy and builder patterns have been included in most of the QtKNX classes.

ETS KNX project file parsing

Another interesting functionality that we will now support is the ability to extract information from an ETS KNX project file, specifically the group addresses and its associated data point types (DPT). For those not so familiarized with the KNX world, ETS stands for Engineering Tool Software, it’s a tool for the design and the commissioning of KNX installations.

Here is an example of how to use the functionality and request the parsing of an ETS KNX project file:

QKnxGroupAddressInfos infos(projFilePath);
infos.parse();

After that we check if there were any errors found through the parsing process:

if (infos.status() != QKnxGroupAddressInfos::Status::NoError)
        return;

Finally, we can extract the information that was parsed:

for (const auto &projId: infos.projectIds()) {
        auto installations = infos.installations(projId);
        // ...
        for (const QString &installation: installations) {
            for (const QKnxGroupAddressInfo &addInfo: groupAddresses) {
                if (!addInfo.isValid())
                    return;
                //...
            }
        }
}

Other important updates

  • Added new patterns for building and introspecting KNXnet/IP frames and structures.
  • Included new data point types (DPTs) up until DPT-30 and sub number less than 100.
  • Introduced new factory (QKnxDatapointTypeFactory), that simplifies the access to the DTPs and allows registering custom ones.
  • Enabled network address translation (NAT) support for KNXnet/IP device management and tunnel connections.
  • Added experimental API for building transport layer protocol data units (TPDUs).

We’ve also made important improvements on the documentation and many other updates. We encourage you to check it all out in the coming QtKNX 5.11 release. We look forward to your feedback!

The post QtKNX updates for 5.11 appeared first on Qt Blog.

Get Started with Qt 3D Studio 2.0 beta 1

Now that the beta 1 release of Qt 3D Studio 2.0 is out, let’s go through the steps involved in trying it out for real.

Pre-built runtime binaries

As outlined in last year’s post, the runtime component of Qt 3D Studio has undergone significant changes. This means that the Viewer application that is launched whenever pressing the green “Play” button in Qt 3D Studio and, more importantly, the C++ and QML APIs with the engine underneath, have all been rewritten in the familiar Qt-style C++ on top of Qt 3D. In practice the runtime is an ordinary Qt module, providing both C++ libraries with classes like Q3DSWidget, Q3DSPresentation, etc. and a QML plugin Studio3D and friends.

The releasing of the pre-built binaries for the runtime has improved a lot for version 2.0: there is now a dedicated entry in the Qt installer which will install the necessarily files alongside the normal Qt installation, so pulling in the runtime via QT += 3dstudioruntime2 or by import QtStudio3D 2.0 in QML will work out of the box in a fresh Qt installation. No more manual building from sources is needed (except when targeting certain platforms).

Let’s Install

At the moment Qt 3D Studio binaries are provided for Windows and macOS. Linux may be added in future releases. It is worth noting that this does not mean the runtime is not suitable for running on Linux (or Android or QNX or INTEGRITY, for that matter) – it, like the most of Qt, will build (cross-compile even) and run just fine, assuming a well-working OpenGL implementation is available for your platform. (however, glitches can naturally be expected with less stable and complete graphics stacks) So while we expect the design work in the Qt 3D Studio application done on Windows or macOS for now, Qt applications using the created 3D presentations can be developed on and deployed to all the typical Qt target platforms.

When launching the online installer, take note of the following entries. Note that the layout and the location of these items may change in the installer in beta 2 and beyond. What is shown here is how things look as of 2.0 beta 1.

The runtime depends on Qt 5.11, meaning it must be installed together with 5.11.0 (or a future release, here we will use the release candidate).

In the example run shown on the screenshots we opted for Visual Studio 2015, but choosing something else is an option too – the installer takes care of downloading and installing the right set of pre-built binaries for the Qt 3D Studio runtime.

q3dsb1inst1

q3dsb1inst2

Once installation is finished, you will have the Qt 5.11 RC, a recent version of Qt Creator, Qt 3D Studio 2.0 beta 1, and the necessary runtime libraries all in place.

Let’s Design

Launching Qt 3D Studio and opening the example project from <installation root>\Tools\Qt3DStudio-2.0.0\examples\studio3d\SampleProject should result in something like the following.

q3dsb1screenshot

For details on what can be done in the designer application, check the documentation. Speaking of which, the documentation for Qt 3D Studio has been split into two parts in version 2.0: the runtime has its own documentation set with the API references, introduction, system requirements, and other topics. (the links are currently to doc-snapshots, the contents will move to doc.qt.io later on)

Let’s Code

Designing the presentation is only half of the story. Let’s get it into a Qt application.

Here we will code an example from scratch. Regardless, you may want to look at the runtime’s examples first. These ship in <installation root>examples\Qt-5.11.0\3dstudioruntime2.

q3dsb1screenshot2
The qmldatainput example in action

For now, let’s start with an empty project. Launch Qt Creator and create a new, empty Qt Quick project targeting Qt 5.11.

q3dsb1screenshot3

The application template gives us a main QML file like this:

q3dsb1screenshot4

When the runtime is installed correctly alongside Qt, we can add the following to make our Qt Quick application load up a Qt 3D Studio presentation and compose it with the rest of the Qt Quick scene.

    ...
    import QtStudio3D 2.0
    
    Window {
        ...
        Studio3D {
            anchors.fill: parent
            anchors.margins: 10
            Presentation {
                source: "file:///c:/QtTest/Tools/Qt3DStudio-2.0.0/examples/studio3d/SampleProject/SampleProject.uip"
            }
        }
    }

(replace c:\QtTest as appropriate)

In many real world applications it is quite likely that you will want to place the presentation’s files and assets into the Qt resource system instead, but the raw file references will do as a first step.

Launching this gives us quite impressive results already:

q3dsb1screenshot5

What we see there is the live Qt 3D Studio presentation rendered by the new Qt3D-based engine into an OpenGL texture which is then used by the Qt Quick scenegraph when drawing a textured quad for the Studio3D element. The keyframe-based animations should all run as defined in the Qt 3D Studio application during the design phase.

Now, a common misconception is that Qt 3D Studio is merely a designer tool and the scenes created by it are static with no runtime modifications possible when loaded up in Qt applications. This is pretty incorrect since applications have full control over

Future versions of Qt 3D Studio are expected to extend the capabilities further, for example with adding APIs to spawn and destroy objects in the scene dynamically.

Let’s change that somewhat annoying text in the middle of the scene, using a button from Qt Quick Controls 2. Whenever the button is clicked, the attribute corresponding to the text rendered by the Text node in the Qt 3D Studio scene will be changed.

Option 1: Direct Attribute Access

q3dsb1screenshot6

When digging down the scene structure at the left of the timline pane, take note of the fact that the Text node has a convenient, unique name already (DateAndTime). This is good since it means we can refer to it without further ado in the application code:

...
import QtQuick.Controls 2.2

Window {
    ...

    Studio3D {
        anchors.fill: parent
        anchors.margins: 10
        Presentation {
            id: pres
            source: "file:///c:/QtTest/Tools/Qt3DStudio-2.0.0/examples/studio3d/SampleProject/SampleProject.uip"
        }

        Button {
            text: "Change text"
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            onClicked: pres.setAttribute("DateAndTime", "textstring", "Hello World")
        }
    }
}

For details on this approach, check out the documentation for Presentation and the attribute name table.

q3dsb1screenshot7
Clicking the button results in changing the ‘textstring’ property of the Text node in the Qt 3D Studio presentation. The change is then picked up by the Qt 3D Studio engine, leading to changing the rendered text.

Option 2: Data Input

While changing properties via setAttribute & co. is simple and effective, Qt 3D Studio also supports another approach: the so-called data inputs. With data inputs, the designers of the 3D scene decide which attributes are controllable by the applications and assign custom names to these. This way a well-known, fixed interface is provided from the designers to the application developers. The example presentation we are using here exposes the following data inputs. (and note the orange-ish highlight for Text String in the Inspector Control in the bottom right corner)

q3dsb1screenshot8

The name dateAndTime is associated with the textstring property of the DateAndTime Text node. Let’s control the value via this approach:

...
import QtQuick.Controls 2.2

Window {
    ...

    Studio3D {
        anchors.fill: parent
        anchors.margins: 10
        Presentation {
            id: pres
            source: "file:///c:/QtTest/Tools/Qt3DStudio-2.0.0/examples/studio3d/SampleProject/SampleProject.uip"

            property string text: ""
            DataInput {
                name: "dateAndTime"
                value: pres.text
            }
        }

        Button {
            text: "Change text"
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            onClicked: pres.text = "Hello World"
        }
    }

Here the Text node starts up with a textstring value of “” (but note there is no actual reference to “textstring” anywhere in the application code), while clicking the button results in changing it to “Hello World”. What’s more, we can now use the usual QML property binding methods to control the value.

That is all for now. Expect more Qt 3D Studio related posts in the near future.

The post Get Started with Qt 3D Studio 2.0 beta 1 appeared first on Qt Blog.

How to Support the Notch and Why – THE Developer Guide for iOS & Android

More and more mobile devices feature a notch (or display cutout, as it is called on Android). To handle this little monster, mobile app developers now face many new challenges.

 

How hard can it be to support the notch – maybe one or two days to optimize existing apps for it?

 

That’s what we initially thought. As it turned out, it was a lot harder than expected. We ran into many bumps along the road of porting 20+ apps & games to properly support it.

As a native iOS and Android developer, you will experience similar issues yourself when you start to develop for devices with edge-to-edge screens. For iOS, Apple even requires you to support iOS 11 and the notch: All new apps & app updates submitted after July 2018 get rejected otherwise.

So we put up our sleeves and prepared this guide to show you how to support the notch in your apps. Thus the sooner you start following this guide the better you are prepared for the Apple change coming in July and for upcoming Android P changes.

The tips provided in this guide apply for both iOS and Android and are useful for cross-platform developers as well. Along the way, we also modified all the components in V-Play, a cross-platform framework for app & game development. It now supports the notch out-of-the-box, so you don’t need to go through this „notch hell“ yourself. :)

Here we go! We hope you enjoy the „Ultimate Guide to Survive the Notch“:

User Interface Challenges of Devices with Edge-to-Edge Displays

Many manufacturers already announced new models with edge-to-edge screens, which became even more popular after the release of the iPhone X:

Devices with Edge-to-Edge Screens and a Notch or Display Cutout

Such screens allow to get the most out of the available space the device offers. In addition to the rounded edges, there is a main pain point for mobile app developers: the notch.

iPhone X with Edge-To-Edge Display vs. iPhone 8

Instead of a clear rectangular frame, app developers now face arbitrary shaped screens. Also, hardware buttons at the front no longer exist. They got replaced by on-screen buttons and gestures provided by the OS. The following sections describe how to create adaptive layouts to handle those challenges for both iOS & Android. While this post uses examples for iPhone X, the same concepts and suggested solutions also apply for other devices & platforms with similar screens, like upcoming Android P devices.

Bigger Screen Size and Safe Area of iPhone X

For the iPhone X, the new screen holds two major factors to account for in your mobile app:

  • The screen is bigger in general, so there’s more space your app can use.
  • Your app content should not cover areas with a notch or native on-screen buttons. Otherwise, the elements you place at these parts of the screen are not accessible.

To support different device models and screens, most apps use a responsive layout. This means that the pages use the full height and width to show as much content as possible. This is a good thing. But if the notch and reserved areas are not taken into consideration, some parts of your app are covered or inaccessible.

Full-screen app content gets covered by the notch or on-screen gestures.

In the example screenshots shown above for the iPhone X, the notch covers the top navigation bar in portrait mode and your page content, the list item text, in landscape mode. For both orientations, the area for the home swipe gesture overlays your app at the bottom. Also note that the new screen comes with rounded corners.

To solve this problem, your app needs to consider the safe area of the screen. It is the part of your app, which won’t be covered by the notch or on-screen gestures. The required top and bottom screen insets determine the safe area in portrait mode:

Top and bottom insets determine the safe area in portrait mode.

For example, the navigation bar requires more padding at the top to be within the safe area. In landscape mode it looks a bit different. We then require margins to the left and right (for the rounded corners and the notch), as well as a small inset at the bottom (for the home swipe gesture):

Insets to the left, right and bottom determine the safe area in landscape mode.

How Do Existing Apps Look on iPhone X?

If you are worrying that your published app is already affected by the notch, you can relax. Only apps configured to target iPhone X will run full-screen. Your existing iOS apps will come with black borders as shown on the right in this image, to not overlay areas with a notch or screen gestures:

iOS App with and without iPhone X Support

The disadvantages are that the borders do not look good and the app does not match the style of other iPhone X apps – your user’s will realize this and your app will get a worse rating. The black border fallback is simply a backwards compatibility feature by Apple to not break anything. However, it also means some work for us app developers to support the new screen.

How to Create iPhone X Apps with Xcode

Enable iPhone X Support for Your App

Unless your app enables support for iPhone X, it will show with black borders by default. This also means, that your existing apps won’t be affected by the notch. However, if you want to fully support iPhone X and let your app fill the whole screen, you need to add an additional launch image for the iPhone X resolution in Xcode:

Add new launch images to support iPhone X.

Add one image with 2436 x 1125 pixels for landscape mode, and one with 1125 x 2436 pixels if you want to support portrait.

Position Your Content to the Safe Area Layout Guide

Many iOS apps use a navigation bar at the top and a tab bar at the bottom. With iOS 7, Apple decided to add the topLayoutGuide and bottomLayoutGuide properties, which match the insets for these bars in the view. Developers can thus align their content to match these insets.

For iPhone X, it is not enough to only take care of the top and bottom margins. We also have insets to the left and right of the screen, e.g. when in landscape mode. So Apple introduced the new safeAreaLayoutGuide property with iOS 11. The top and bottom layout guides are now deprecated.

Use the safe area layout guide to align your content with the iPhone X safe area.

To make sure your content isn’t covered by the notch, position it to the safe area layout guide. Similar to the previous top and bottom layout guides, this can be done with constraints.

But this simple solution is still far from perfect. Especially in landscape mode, constraining your content area can leave some ugly margins. To avoid this, you can instead add custom insets to your content only where necessary.

The new safeAreaInsets property gives access to the exact pixel inset for the safe area. You can thus tweak the layout to look exactly as you want. For example, you can design the cells of your list items to account for the safe area with a bigger indent. The view content can then cover the whole screen.

Use safe area insets to optimize your layout for landscape mode.

How to Migrate Existing Native iOS Apps to work with Safe Area Insets

To make updating your apps a bit easier, you have the option to activate the Use Safe Area Layout Guides setting for each of your Storyboards in Xcode.

"Use Safe Area Layout Guide" setting for Xcode storyboards.

The Storyboard then replaces the top and bottom layout guides with a safe area and updates the constraints. This is a quick first measure to get your app ready for iPhone X.

But as mentioned above, you will still need to check all your views to provide the best possible user experience. For example, to:

  • Let the background of a sub-view use the full screen while keeping the content safe.
  • Decide how to handle the insets when flicking a UIScrollView.
  • Set up your UITableView or UICollectionView to correctly layout for iPhone X.

Full-screen content vs. optimized layout for iPhone X.

Also, you might not be happy with the result of the default Use Safe Area Layout Guides setting in case your app hides the system status bar:

iPhone X Notch Issue with Hidden StatusBar

Due to a bug within the latest iOS 11 SDK, the navigation bar does not account for the notch in this case. Except for some workarounds, there is no simple solution for this issue at the moment of writing this guide. At least when relying on native iOS development with Xcode.

Android P Developer Preview: Display Cutouts

Many Android phone manufacturers already announced their upcoming device models with edge-to-edge displays and rounded corners. For example:

Upcoming Android Devices with Display Cutout

Google also already released the developer preview for Android P. It comes with the ability to handle these so-called display cutouts. In the iOS world, display cutout is equivalent to notch.

How to Test Apps with Display Cutout in Android P

The Android P Developer Preview allows simulation of display cutout. Android P is available with the SDK Manager of Android Studio. It is sufficient to install the Android P SDK and System Image to test on a virtual Android P device:

The Android P Developer Preview is available with the SDK Manager.

After installation is complete, you can start an emulator running Android P. The developer settings on Android P offer four different display cutout options to choose from:

Android P Developer Settings - Display Cutout Simulation

After selecting this option, the Android device will show with a bigger status bar that also includes a display cutout:

Android P Developer Preview with Simulated Display Cutout

The layoutInDisplayCutoutMode attribute controls how the window is laid out if there is a display cutout. By default your Android P app never extends into cutout areas – with a single exception. As visible on the image above, your app can safely cover the full screen for cutouts that do not exceed the status bar area.

Note: The window will lose this ability to extend into the cutout area when FLAG_FULLSCREEN or SYSTEM_UI_FLAG_FULLSCREEN is set.

To let your app always take advantage of the full screen, you can set the value LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. You are then responsible to keep your app content within the safe area of the screen. For example, when the device is in landscape mode or if the cutout exceeds the status bar in portrait.

Custom Layouts with Safe Area Insets in Android P

Like iOS 11, Android P includes features to determine the safe area of the screen and work with the given insets. The new DisplayCutout class lets you find out the location and shape of the non-functional areas where content shouldn’t be displayed.

To determine the existence and placement of the cutouts areas, use the getDisplayCutout() method. You can then access the following fields for the DisplayCutout:

Overall it means quite some work to let your app layout adapt to these new displays. Especially for developers that target both iOS and Android.

Save Time and Effort with V-Play Engine for Mobile Apps

Create iOS and Android Apps that Support The Notches and Display Cutouts

V-Play Engine focuses on making mobile app development easy. And it also supports the iPhone X notch and Android P devices with display cutouts out-of-the-box. You can write your app once, and build for iOS, Android or even Desktop with a single button press from 1 IDE. The source code is 100% shared across all platforms.

V-Play Support for Android P and Display Cutouts

V-Play builds upon C++ & Qt and utilizes QML & JavaScript. QML is a fast and easy-to-use declarative UI language. With only a few lines of code, it is possible to create native iOS and Android apps that look native on every device:

import VPlayApps 1.0
import QtQuick 2.0

App {
  // adds tab navigation (iOS) or drawer menu (Android) 
  Navigation {

    // first tab
    NavigationItem {
      icon: IconType.home
      title: "Main"

      // main page
      NavigationStack {
        Page {
          title: "Main"

          Rectangle {
            anchors.fill: parent // Rectangle fills whole Page
            color: "lightgreen"

            AppText {
              anchors.centerIn: parent // AppText is centered on Page
              text: "Safe Area"
            }
          }
        }
      }
    }

    // second tab
    NavigationItem {
      icon: IconType.gears
      title: "Settings"

      // settings page
      NavigationStack {
        Page { title: "Settings" }
      }
    }

  }
}

 

This is how the above example app looks like on an iPhone X:

V-Play Support for iPhone X and the Notch

The used components like Navigation and NavigationStack are prepared to work with safe area insets: They automatically include extra margins for the tab and navigation bar if required.

In contrast to the native iOS SDK it is also possible to hide the status bar without any issues. You can do this by setting a single property in your code:

import VPlayApps 1.0
import QtQuick 2.0

App {
  onInitTheme: {
    Theme.colors.statusBarStyle = Theme.colors.statusBarStyleHidden
  }

  // main page
  NavigationStack {
    Page {
      title: "Main"

      AppButton {
        anchors.horizontalCenter: parent.horizontalCenter
        text: "Toggle Status Bar"
        onClicked: {
          if(Theme.statusBarStyle !== Theme.colors.statusBarStyleHidden)  
            Theme.colors.statusBarStyle = Theme.colors.statusBarStyleHidden
          else
            Theme.colors.statusBarStyle = Theme.colors.statusBarStyleBlack
        }
      }
    }
  }
}

No status bar issue for iPhone X apps created with V-Play.

The top navigation bar in V-Play always supports the notch automatically, even with a hidden status bar.

Like the Use Safe Area Layout Guide setting for Xcode Storyboards, the content of your pages does not overlap reserved areas of the screen. But V-Play requires no extra setting to achieve this. The page content aligns with the safe area out-of-the box. For devices without a notch, the app does not show any extra margins or insets:

V-Play Components are prepared to support the safe area out-of-the-box.

Note: Configure iPhone X launch images for your iOS app to get full-screen support on iPhone X if you have an existing V-Play app. For new apps, this is set up automatically.

Optimize your User Interface with Adaptive Layouts

For most use cases, the default settings are fine to let your app look good on devices with and without display cutouts. If you want more control over how to display your content, you can disable the useSafeArea setting of each Page. You then have two options to work with the safe area:

  1. Configure only certain content items within the Page to align with the safe area.
  2. Retrieve the exact safe area inset of the screen and layout items as required.

The following example deactivates the useSafeArea setting and shows both options:

import VPlayApps 1.0
import QtQuick 2.0

App {

  Page {
    useSafeArea: false // the page content can use all available space

    // fill whole page/screen with blue color (background)
    Rectangle {
      anchors.fill: parent
      color: "lightblue"
    }

    // Option 1: fill only safe area with green color (content)
    Rectangle {
      anchors.fill: parent.safeArea
      color: "lightgreen"
    }

    // Option 2: adaptive background to cover top inset area (or status bar area on devices without insets)
    Rectangle {
      width: parent.width
      height: nativeUtils.safeAreaInsets.top > 0 ? nativeUtils.safeAreaInsets.top : nativeUtils.statusBarHeight()
      color: "yellow"
    }
  }

}

 

The page content can now cover the full screen by default. You can use the safeArea property of the Page to align items with the safe area of the screen. In the above example, we use this to fill the safe area with a green rectangle. This is where you can place your content items.

The nativeUtils.safeAreaInsets hold the exact safe area insets of the screen in pixels. Devices without a notch do not have any insets and thus return 0. For iPhone X, the yellow rectangle will cover the top inset, which includes the status bar. To also support older devices, you fill the status bar if no inset is returned by nativeUtils.safeAreaInsets.top.

The available safeAreaInsets properties are:

  • nativeUtils.safeAreaInsets.top
  • nativeUtils.safeAreaInsets.right
  • nativeUtils.safeAreaInsets.bottom
  • nativeUtils.safeAreaInsets.left

Running this app on iOS or Android produces the following result:

Create adaptive layouts to perfectly support the notch or display cutouts in your apps.

Developing adaptive user interfaces this way is very convenient. The following example shows how you could use nativeUtils.safeAreaInsets.left to add more indent for the cells of a list.

import VPlayApps 1.0
import QtQuick 2.0

App {

  NavigationStack {
    ListPage {
      title: "List Page"
      useSafeArea: false // the page fills all available space
      model: 50 // quick way to populate the list with 50 items

      // UI for cells of the list
      delegate: SimpleRow {
        text: "Item #"+index

        // set indent of the cells
        // matches the safe area inset or minimum 16 dp (if no inset required, e.g. in portrait mode or on older devices)
        style.indent: Math.max(nativeUtils.safeAreaInsets.left, dp(16))
      }
    }
  }
  
}

With such simple additions, you can make sure that your app looks pixel-perfect on screens with and without safe area insets.

Adaptive Layout Example: Full-width list cells in landscape mode.

You don’t need to add such tweaks for apps that offer the default UI with a navigation bar and tab bar. The V-Play page and navigation components look good on all devices and adapt their style automatically.

Support for Display Cutout on Android P Devices

V-Play Engine is a cross-platform development tool that supports both Android and iOS. You can take the QML code of your iOS app and directly build for Android, or vice-versa. All components change their look and behavior then. They match the native style and user experience of the given platform:

V-Play Supports both iOS 11 and Android P.

The above image shows the Android and iOS style for the same example app. The Android style is already prepared to support edge-to-edge screens. No extra work is required, to make your app work cross-platform for iOS & Android with display cutouts, safe area and a notch!

Simulate Safe Area Insets while Developing on Desktop

It takes quite some time to always build and deploy to your phone or the simulator. With V-Play you can run and test your app directly on Desktop. It is even possible to simulate different devices and resolutions to see how your app will look like. You can change the resolution at runtime, without having to restart your app. This is a huge time-saver for UI development & testing! Native development for Android or iOS requires deployment to another real or virtual device to test the UI.

V-Play Device Resolution Simulation on Desktop

Along with the support for a display notch, V-Play also comes with a new resolution simulator entry for iPhone X. And the best thing is: It even covers the safe area insets you get on a real device:

iPhone X Desktop Simulation with Safe Area Insets

V-Play Engine is thus a huge time-saver when developing for iOS and Android. The V-Play SDK is free to use, so make sure to check it out!

 

 

If you enjoyed this post, please leave a comment or share it on Facebook or Twitter.

More Relevant App Development Resources

The Best App Development Tutorials & Free App Templates

All of these tutorials come with full source code of the mobile apps! You can copy the code to make your own apps for free!

App Development Video Tutorials

 

 

Thanks for reading & scrolling that far! :)

Do you have suggestions for posts or tutorials about app development?
Simply send us a message which tutorial you’d like to see here.

 

More Posts Like This

feature
How to Make Cross-Platform Mobile Apps with Qt – V-Play Apps

teaser-iphonex-support-and-runtime-screen-orientation-change-705px
Release 2.16.0: iPhone X Support and Runtime Screen Orientation Changes

How to Expose a Qt C++ Class with Signals and Slots to QML
How to Expose a Qt C++ Class with Signals and Slots to QML

The post How to Support the Notch and Why – THE Developer Guide for iOS & Android appeared first on V-Play Engine.

Creating RESTful applications with Qt and Cutelyst

This mini tutorial aims to show you the fundamentals of creating a RESTful application with Qt, as a client and as a server with the help of Cutelyst.

Services with REST APIs have become very popular in recent years, and interacting with them may be necessary to integrate with services and keep your application relevant, as well as it may be interesting to replace your own protocol with a REST implementation.

REST is very associated with JSON, however, JSON is not required for a service to become RESTful, the way data is exchanged is chosen by the one who defines the API, ie it is possible to have REST exchanging messages in XML or another format. We will use JSON for its popularity, simplicity and due to the QJsonDocument class being present in the Qt Core module.

A REST service is mainly characterized by making use of the little-used HTTP headers and methods, browsers basically use GET to get data and POST to send form and file data, however REST clients will use other methods like DELETE, PUT and HEAD, concerning headers many APIs define headers for authentication, for example X-Application-Token can contain a key generated only for the application of a user X, so that if this header does not contain the correct data it will not have access to the data.

Let's start by defining the server API:

  • /api/v1/users
    • GET - Gets the list of users
      • Answer: ["uuid1", "uuid2"]
    • POST - Register new user
      • Send: {"name": "someone", "age": 32}
      • Answer: {"status": "ok / error", "uuid": "new user uuid", "error": "msg in case of error"}
  • /api/v1/users/ - where UUID should be replaced by the user's UUID
    • GET - Gets user information
      • Answer: {"name": "someone", "age": 32}
    • PUT - Update user information
      • Send: {"name": "someone", "age": 57}
      • Answer: {"status": "ok / error", "error": "msg in case of error"}
    • DELETE - Delete user
      • Answer: {"status": "ok / error", "error": "msg in case of error"}

For the sake of simplicity we will store the data using QSettings, we do not recommend it for real applications, but Sql or something like that escapes from the scope of this tutorial. We also assume that you already have Qt and Cutelyst installed, the code is available at https://github.com/ceciletti/example-qt-cutelystrest

Part 1 - RESTful Server with C ++, Cutelyst and Qt

First we create the server application:

$ cutelyst2 --create-app ServerREST

And then we will create the Controller that will have the API methods:

$ cutelyst2 --controller ApiV1

Once the new class has been instantiated in serverrest.cpp, init() method with:

#include "apiv1.h"

bool ServerREST::init()
{
    new ApiV1 (this);
    ...

Add the following methods to the file "apiv1.h"

C_ATTR(users, :Local :AutoArgs :ActionClass(REST))
void users(Context *c);

C_ATTR(users_GET, :Private)
void users_GET(Context *c);

C_ATTR(users_POST, :Private)
void users_POST(Context *c);

C_ATTR(users_uuid, :Path('users') :AutoArgs :ActionClass(REST))
void users_uuid(Context *c, const QString &uuid);

C_ATTR(users_uuid_GET, :Private)
void users_uuid_GET(Context *c, const QString &uuid);

C_ATTR(users_uuid_PUT, :Private)
void users_uuid_PUT(Context *c, const QString &uuid);

C_ATTR(users_uuid_DELETE, :Private)
void users_uuid_DELETE(Context *c, const QString &uuid);

The C_ATTR macro is used to add metadata about the class that the MOC will generate, so Cutelyst knows how to map the URLs to those functions.

  • :Local - Map method name to URL by generating /api/v1/users
  • :AutoArgs - Automatically checks the number of arguments after the Context *, in users_uuid we have only one, so the method will be called if the URL is /api/v1/users/any-thing
  • :ActionClass(REST) ​​- Will load the REST plugin that will create an Action class to take care of this method, ActionREST will call the other methods depending on the called method
  • :Private - Registers the action as private in Cutelyst, so that it is not directly accessible via URL

This is enough to have an automatic mapping depending on the HTTP method for each function, it is important to note that the first function (without _METHOD) is always executed, for more information see the API of ActionREST

For brevity I will show only the GET code of users, the rest can be seen in GitHub:

void ApiV1::users_GET(Context *c)
{
    QSettings s;
    const QStringList uuids = s.childGroups();

    c->response()->setJsonArrayBody(QJsonArray::fromStringList(uuids));
}

After all the implemented methods start the server:

cutelyst2 -r --server --app-file path_to_it

To test the API you can test a POST with curl:

curl -H "Content-Type: application/json" -X POST -d '{"name": "someone", "age": 32}' http://localhost:3000/api/v1/users

Okay, now you have a REST server application, made with Qt, with one of the fastest answers in the old west :)

No, it's serious, check out the benchmarks.

Now let's go to part 2, which is to create the client application that will consume this API.

Part 2 - REST Client Application

First create a QWidgets project with a QMainWindow, the goal here is just to see how to create REST requests from Qt code, so we assume that you are already familiar with creating graphical interfaces with it.

Our interface will be composed of:

  • 1 - QComboBox where we will list users' UUIDs
  • 1 - QLineEdit to enter and display the user name
  • 1 - QSpinBox to enter and view user age
  • 2 - QPushButton
    • To create or update a user's registry
    • To delete the user record

Once designed the interface, our QMainWindow sub-class needs to have a pointer to QNetworkAccessManager, this is the class responsible for handling communication with network services such as HTTP and FTP. This class works asynchronously, it has the same operation as a browser that will create up to 6 simultaneous connections to the same server, if you have made more requests at the same time it will put them in a queue (or pipeline them if set).

Then create a QNetworkAccessManager *m_nam; as a member of your class so we can reuse it. Our request to obtain the list of users will be quite simple:

QNetworkRequest request(QUrl("http://localhost:3000/api/v1/users"));

QNetworkReply *reply = m_nam->get(request);
connect(reply, &QNetworkReply::finished, this, [this, reply] {
    reply->deleteLater();
    const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
    const QJsonArray array = doc.array();

    for (const QJsonValue &value : array) {
        ui->uuidCB->addItem(value.toString());
    }
});

This fills with the data via GET from the server our QComboBox, now we will see the registration code which is a little more complex:

QNetworkRequest request(QUrl("http://localhost:3000/api/v1/users"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

QJsonObject obj {
    {"name", ui->nameLE->text()},
    ("age", ui->ageSP->value()}
};

QNetworkReply *reply = m_nam->post(request, QJsonDocument(obj).toJson());
connect(reply, &QNetworkReply::finished, this, [this, reply] {
    reply->deleteLater();
    const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
    const QJsonObject obj = doc.object();

    if (obj.value("status").toString() == "ok") {
        ui->uuidCB->addItem(obj.value("uuid").toString());
    } else {
        qWarning() << "ERROR" << obj.value("error").toString();
    }
});

With the above code we send an HTTP request using the POST method, like PUT it accepts sending data to the server. It is important to inform the server with what kind of data it will be dealing with, so the "Content-Type" header is set to "application/json", Qt issues a warning on the terminal if the content type has not been defined. As soon as the server responds we add the new UUID in the combobox so that it stays up to date without having to get all UUIDs again.

As demonstrated QNetworkAccessManager already has methods ready for the most common REST actions, however if you wanted to send a request of type OPTIONS for example will have to create a request of type CustomOperation:

m_nam->sendCustomRequest("OPTIONS", request);

Did you like the article? Help by giving a star to Cutelyst and/or supporting me on Patreon

https://github.com/cutelyst/cutelyst

Qt 3D Studio 2.0 Beta Available

We are getting close to releasing the Qt 3D Studio 2.0 and the first Beta is released today. First beta packages are now available through the Qt online installer & Qt download. Let’s have a quick summary of the changes & new features we are introducing. For detailed information about the Qt 3D Studio please visit our web pages at: https://www.qt.io/3d-studio

New Runtime & Viewer Application

One of the biggest changes in the 2.0 release is the new Qt 3D Studio runtime which is built on top of the Qt 3D module. From user perspective this change is not directly visible, but a very important item under the hood. Using Qt 3D means deeper and easier integration to the Qt framework. It also makes it easier for us to introduce new features from both tooling and 3D engine perspective. First example of the new features is the Qt 3D Studio 2.0 Viewer Debugging and Profiling UI which shows the basic information about the rendering performance and structure of the 3D scene.

Qt 3D Studio Viewer Profile and Debug view

Qt 3D Studio Viewer Profile and Debug view

Deploying your UI project to the Viewer application in the target device with debugging and profiling enabled allows you to immediately see what the potential design performance bottlenecks are. You can also spot cases where you are using large textures or 3D models have a lot of parts which are not visible.

Improved Data Input

Data Inputs are a mechanism for integrating the user interface to the application logic. The Data Input functionality in the 1.1 release was somewhat limited and basically offered support only to control animation timelines and changing slides. With the 2.0 release we have introduced several new data types which can be now easily tied to different object properties in the 3D scene.

Improved Data Input

Improved Data Input

For more details on using Data Inputs please refer to documentation 

Editor Improvements

Biggest change in the editor side is the new timeline view which has been totally rewritten. This rewrite makes it easier for us to introduce new features in the future and already in the 2.0 release we have already made several small usability improvements.

New timeline

New timeline

We have also made changes to the shortcut keys and mouse usage so that changing between different Camera Views (Perspective, Top, Scene Camera etc.) and panning and orbiting is easier, and the behavior is closer to the common practices in 3D design tools. For more details please refer to keyboard shortcuts documentation.

Installation

Qt 3D Studio 2.0 beta releases are available through Qt online installer under the Preview section. Qt online installer can be obtained from Qt Download page and commercial license holders can find the packages from Qt Account.

Some example projects can be found under examples folder in the installation directory. Additional examples and demo applications can be found from https://git.qt.io/public-demos/qt3dstudio repository. If you encounter issues with using Qt 3D Studio or you would like to suggest new feature, please use Qt3D Studio project in the https://bugreports.qt.io

The post Qt 3D Studio 2.0 Beta Available appeared first on Qt Blog.

Optimizing Device Communication with Qt MQTT

Qt for Automation has been launched in conjunction with Qt 5.10 as an AddOn to Qt for Application Development or Qt for Device Creation. One module in that offering is our client-side solution for MQTT called Qt MQTT.

Qt MQTT focusses on the client side, helping developers to create sensor devices and or gateways managing data to be sent via MQTT.  MQTT describes itself to be lightweight, open and simple. The principle idea is to reduce the protocol overhead as much as possible. The most used version of this protocol is MQTT 3.1.1, usually referred to as MQTT 4. The MQTT 5 standard has been agreed on recently, and we are working on adding support for it in Qt MQTT. But that will be part of another announcement later this year.

To verify the functionality of a module and also to provide guidelines for developers on its usage, The Qt Company created a demo which is called SensorTag. We will use this demo as a basis for this blog series.

A brief introduction can be viewed in this video:

The source code of this demo is located in our Boot 2 Qt demo repository here ( http://code.qt.io/cgit/qt-apps/boot2qt-demos.git/tree/tradeshow/iot-sensortag ).

Basically, this demo describes a scenario in which multiple sensors report data to a gateway (in this case Raspberry Pi3) via Bluetooth, which then again sends data to an MQTT broker in the cloud. Multiple gateways mesh up to generate a sensor network.

automation

Each sensor propagates updates to what they measure, more specifically

  • Ambient Temperature
  • Object Temperature
  • Acceleration
  • Orientation / angular velocity
  • Magnetism
  • Altitude
  • Light
  • Humidity

As the focus of this series is about data transmission, the Sensor / Gateway combination will be summed up as “device”.

The demo serves two purposes; It has a pleasant user interface, which appeals to many, and it showcases how easy it is to integrate MQTT (and Qt MQTT).

MQTT is a publish/subscribe protocol, which implies that data is sent related to a specific topic and other recipients register themselves to a broker (server) to receive notifications on each message published.

For the devices above, available messages are:

  • [Topic: Sensors/active, Data: ID]: Every 5 seconds a sensor publishes an “Online” message, notifying subscribers that the device is still active and sending data. On initial connect it also includes a Will message “Offline”. A will message is sent whenever a device disconnects to notify all subscribers with a “Last Will”. Hence, as soon as the network is disconnected, the broker broadcasts the last will to all subscribed parties.
  • [Topic: Sensor/<sensorID>/<datatype>/, Data:<value>]: This is send from each sensor whenever a value for a specific datatype like in above list changes. The user interface from the video subscribes to these messages and updates the graphics accordingly.

Side-note: One additional use-case could be to check the temperature of all devices. In that case, “wildcard” subscriptions can be very useful. Subscribing to “Sensor/+/temperature will lead to receiving temperature updates from all sensors.

Currently, there are around 10 sensors registered at the same time at peak times, mostly when the demo is presented at tradeshows. As mentioned above, demo code exists to showcase an integration, not necessarily the most performant or energy-saving solution. When going towards production, a couple of questions need to be asked:

  • What would happen in a real-world scenario? Would the demo scale up to thousands of devices reporting data?
  • Does the demo fit to requirements on hardware and/or battery usage?
  • Is it within the boundaries of communication limitations of Low Power WAN solutions?

In case you are not familiar with LPWAN solutions like LoRA or Sigfox, I highly recommend Massimo’s talk (https://www.youtube.com/watch?v=s9h7osaSWeU ) at the Qt World Summit 2017.

 

To simplify the source to look at and to reduce it to a non-UI minimal example, there is a minimal representation available here . In that the SensorInformation class has a couple of properties, which get updated frequently:

class SensorInformation : public QObject

{
    Q_OBJECT
    Q_PROPERTY(double ambientTemperature READ ambientTemperature WRITE setAmbientTemperature NOTIFY ambientTemperatureChanged)
    Q_PROPERTY(double objectTemperature READ objectTemperature WRITE setObjectTemperature NOTIFY objectTemperatureChanged)
    Q_PROPERTY(double accelerometerX READ accelerometerX WRITE setAccelerometerX NOTIFY accelerometerXChanged)
    Q_PROPERTY(double accelerometerY READ accelerometerY WRITE setAccelerometerY NOTIFY accelerometerYChanged)
    Q_PROPERTY(double accelerometerZ READ accelerometerZ WRITE setAccelerometerZ NOTIFY accelerometerZChanged)
    Q_PROPERTY(double altitude READ altitude WRITE setAltitude NOTIFY altitudeChanged)
    Q_PROPERTY(double light READ light WRITE setLight NOTIFY lightChanged)
    Q_PROPERTY(double humidity READ humidity WRITE setHumidity NOTIFY humidityChanged)
[..]

 

Whenever a property is updated the client publishes a message:

    m_client->publish(QString::fromLatin1("qtdemosensors/%1/ambientTemperature").arg(m_id),
                      QByteArray::number(ambientTemperature));

 

The device update rate depends on the type of sensors, items like temperature and light intensity are updated less frequently than, for instance, acceleration.

To get an idea of how much data is sent, example Part1B hooks into the client’s transport capabilities. MQTT in its standard has only a limited number of requirements for the transport. Whatever transmits the data must send it ordered, lossless and bi-directional. Theoretically, anything starting from QIODevice is capable of this. QMqttClient allows to specify a custom transport via QMqttClient::setTransport(). Here, we use the following:

 

class LoggingTransport : public QTcpSocket
{
public:
    LoggingTransport(QObject *parent = nullptr);

protected:
     qint64 writeData(const char *data, qint64 len) override;
private:
    void printStatistics();
    QTimer *m_timer;
    QMutex *m_mutex;
    int m_dataSize{0};
};

Inside the constructor a timer is created to invoke printStatistics() at a regular interval. writeData simply stores the length of data to be send and then passes on to QTcpSocket::writeData().

To add the LoggingTransport to a client, all one needs to do is:

    m_transport = new LoggingTransport(this);
    m_client = new QMqttClient(this);
    m_client->setTransport(m_transport, QMqttClient::AbstractSocket);

The output shows that after 11 seconds one sensor sends about 100KB of data. This is just one sensor. Considering the “real-world” example this is clearly unacceptable for distribution. Hence, the effort is now to reduce the number of bytes to be published without losing information.

The demo itself uses one connection at all times, meaning it does not need to dis- or reconnect. The connect statement in MQTT 3.1.1 is around 10 bytes plus the ID of the client. In case a device would reconnect each time to send data, this can add up to a significant amount. But in this case, we “optimized” it already.

Consequently, we move on to the publishing step. There are two options, reduce the size of each message and reduce the number of messages.

For the former, the design of a publish message for ambient temperature is the following:

Bytes Content
1 Publish Statement & Configuration
1 Remaining Length of the message
2 Length of the topic
71 Topic: qtdemosensors/{8f8fde60-933d-44cf-b3a7-8dac62425a63}/ambientTemperature
2 ID of the message
1..8 Value (String for double)

It is obvious that the topic itself is to be taken responsible for the size of the message, especially as the payload storing the value is just a fraction of the size of a message.

Concepts which can be applied here are:

  • Shorten the “root” topic (qtdemosensors -> qtds)
  • Shrink the size of the ID (UUID -> 8 digit number)
  • Replace the clear text of sensortype with an enum (ambientTemperature -> 1)

All those approaches come with a price. Using enums instead of clear text property reduces the readability of a message, the subscriber always has to know what type of data corresponds to an ID. Reducing the size of the ID potentially limits the maximum number of connected devices, etc. But applying those items leads to more than three times longer period until the 100KB barrier is reached (See example Part 1C).

At this stage, it becomes impossible to reduce the message overhead without losing information. In the showcase, I mentioned that the simulated sensors are to be used in the field, potentially sending data via LPWAN. Typically, sensors in this area should not send data on such a high frequency. If that is the case, there are two additional options.

First, the messages are getting combined to one single message containing all sensor properties. The table above showed that the amount of data for the value part has just been a fraction of the message overhead.

One approach is to use JSON to propagate properties, this can be seen in example Part 1d. QJsonObject and QJsonDocument are very handy to use, and QJsonDocument::toJson() exports the content to a QByteArray, which fits perfectly to an MQTT message.

 

void SensorInformation::publish()
{
    QJsonObject jobject;
    jobject["AmbientTemperature"] = QString::number(m_ambientTemperature);
    jobject["ObjectTemperature"] = QString::number(m_objectTemperature);
    jobject["AccelerometerX"] = QString::number(m_accelerometerX);
    jobject["AccelerometerY"] = QString::number(m_accelerometerY);
    jobject["AccelerometerZ"] = QString::number(m_accelerometerZ);
    jobject["Altitude"] = QString::number(m_altitude);
    jobject["Light"] = QString::number(m_light);
    jobject["Humidity"] = QString::number(m_humidity);
    QJsonDocument doc( jobject );
    m_client->publish(QString::fromLatin1("qtds/%1").arg(m_id), doc.toJson());
}

 

The size of an MQTT publish message is now at around 272 bytes including all information. As mentioned before, it comes at the cost of losing information, but also at significantly reducing the bandwidth required.

To summarize this first part, we have looked into various solutions to reduce the amount of data being sent from a device to an MQTT broker with minimal effort. Some approaches trade off readability or extensibility, others come with a loss of information before data transmission. It really depends on the use-case and the scenario in which an IoT solution is put into production. But all of these can easily be implemented with Qt. Until now, we have only covered Qt’s feature set on JSON, MQTT, networking, and connectivity via Bluetooth.

In the meantime, you can also find more information on our website and write your comments below.

The post Optimizing Device Communication with Qt MQTT appeared first on Qt Blog.

Code contributions via bug reports and forum posts

Contribution of source code is now allowed via Qt systems such as bug reports and forums. Traditionally all source code contributions to the Qt Project are governed via Contribution License Agreement (CLA), except possibility given to the commercial license holders to provide bug fixes and similar small modifications that The Qt Company has pushed into Qt. We have now updated the Qt Account service terms to more clearly state that source code can be contributed via the Qt systems.

The preferred way to contribute source code to the Qt Project is still via the CLA, according to the contribution guidelines. But sometimes a user who has not accepted the CLA has a patch that would, for example, fix a bug in Qt. Providing such a patch is now also possible via the Qt systems, for example via the bug reports or forum posts.

When such a “casual contribution” is done, it will be the responsibility of The Qt Company to pick up the contributed source code and complete the needed steps of pushing the fix into Qt. So the contributed code will not automatically go in as-is, but via the regular contribution process that ensures good quality of the source code in the Qt repositories.

The earlier service terms of the Qt Account and other Qt systems already provided adequate rights for The Qt Company to publish the content provided by the registered users. However, the earlier version did not explicitly mention that this includes source code, so we wanted to make the clarification. As we take these matters seriously, we will only use source code contributed from now on. In case you have earlier submitted a patch via some of the Qt systems, please submit it again.

In addition to providing source code, there are many other ways to contribute to Qt, for example by reporting bugs, supporting others in Qt mailing lists or forums, translating to other languages, and writing documentation.

If you have any questions regarding contributions to Qt, please do not hesitate to ask from our legal.

The post Code contributions via bug reports and forum posts appeared first on Qt Blog.

OPC UA support in Qt 5.11

OPC UA is a central element of the Industry 4.0 story providing seamless communication between IT and industrial production systems. basysKom has initiated Qt OPC UA in 2015 with the goal of providing an out of the box Qt API for OPC UA. In 2017 basysKom, together with The Qt Company, has finished up a Technology Preview of that API. It will be available with the upcoming Qt 5.11 release end of May.

The focus of Qt OPC UA is on HMI/application development and ease of use for client-side development. The Tech Preview implements a subset of the OPC UA standard. It allows to connect to servers, read and write attributes, call methods on the server, monitor values for data changes and browse nodes. All this functionality is provided by asynchronous APIs which integrate nicely into Qt applications.

Qt OPC UA is primarily an API and not a whole OPC UA stack. A plugin interface lets you integrate existing OPC UA stacks as API backends. Currently, plugins for the following stacks are available:

  • FreeOpcUa
  • open62541
  • Unified Automation C++ SDK 1.5

Qt OPC UA will be available directly from the Qt installer for those holding a Qt for Automation license. The source code itself is triple licensed (GPL, LGPL and commercial) with the exception of the Unified Automation backend which is only available under a commercial license. Users of one of the Open Source licenses will need to compile Qt OPC UA themselves. See here for a list of build recipes.

The backends for FreeOpcUa and open62541 are available under an Open Source license. When going for an Open Source solution, we recommend the open62541 plugin as it is the more complete implementation with an active community and a good momentum. It also has fewer dependencies, making usage on platforms such as Android or iOS much easier.

On the platform side, the technology preview will be available for

  • Windows with Visual Studio 2015 & 2017 as well as MinGW
  • Linux (Desktop and Embedded)
  • Android and iOS

Please note that not every backend is available on every platform.

On top of what is part of the Tech Preview, there are already a number of additions planned. Among them support for transport security, the discovery service, event support, and filters.

If you would like to find out more, join my webinar on OPC UA on 19 June. I will be happy to answer your questions.

The post OPC UA support in Qt 5.11 appeared first on Qt Blog.

New in Qt 5.11: improvements to the model/view APIs (part 1)

The Qt model/view APIs are used throughout Qt — in Qt Widgets, in Qt Quick, as well as in other non-GUI code. As I tell my students when I deliver Qt trainings: mastering the usage of model/view classes and functions is mandatory knowledge, any non-trivial Qt application is going to be data-driven, with the data coming from a model class.

In this blog series I will show some of the improvements to the model/view API that KDAB developed for Qt 5.11. A small word of advice: these posts are not meant to be a general introduction to Qt’s model/view (the book’s margin is too narrow… but if you’re looking for that, I suggest you start here) and assumes a certain knowledge of the APIs used.

Implementing a model class

Data models in Qt are implemented by QAbstractItemModel subclasses. Application developers can either choose one of the ready-to-use item-based models coming with Qt (like QStringListModel or QStandardItemModel), or can develop custom model classes. Typically the choice falls on the latter, as custom models provide the maximum flexibility (e.g. custom storage, custom update policies, etc.) and the biggest performance. In my experience with Qt, I have implemented probably hundreds of custom models.

For simplicity, let’s assume we are implementing a table-based model. For this use case, Qt offers the convenience QAbstractTableModel class, which is much simpler to use than the fully-fledged QAbstractItemModel. A typical table model may look like this:

class TableModel : public QAbstractTableModel
{
public:
    explicit TableModel(QObject *parent = nullptr)
        : QAbstractTableModel(parent)
    {
    }

    // Basic QAbstractTableModel API
    int rowCount(const QModelIndex &parent) const override
    {
        return m_data.rowCount();
    }

    int columnCount(const QModelIndex &parent) const override
    {
        return m_data.columnCount();
    }

    QVariant data(const QModelIndex &index, int role) const override
    {
        if (role != Qt::DisplayRole)
            return {};

        return m_data.getData(index.row(), index.column());
    }

private:
    Storage m_data;
};

First and foremost, note that this model is not storing the data; it’s acting as an adaptor between the real data storage (represented by the Storage class) and the views.

When used into a Qt view (for instance a QTreeView), this code works perfectly and shows us a nice table full of data, for instance like this:

Making the code more robust

The code of the class above has a few issues.

The first issue is that the implementation of rowCount() and columnCount() is, generally speaking, wrong. Those functions are supposed to be callable for every model index belonging to this model, plus the root (invalid) model index; the parameter of the functions is indeed the parent index for which we’re asking the row count / column count respectively.

When called with the root index, the functions return the right amount of rows and columns. However, there are no rows and no columns below any of elements in the table (because it is a table). The existing implementation does not make this distinction, and happily returns a wrong amount of rows/columns below the elements themselves, instead of 0. The lesson here is that we must not ignore the parent argument, and handle it in our rowCount and columnCount overrides.

Therefore, a more correct implementation would look like this:

    int rowCount(const QModelIndex &parent) const override
    {
        if (parent.isValid())
            return 0;

        return m_data.rowCount();
    }

    int columnCount(const QModelIndex &parent) const override
    {
        if (parent.isValid())
            return 0;

        return m_data.columnCount();
    }

The second issue is not strictly a bug, but still a possible cause of concern: we don’t validate any of the indices passed to the model’s functions. For instance, we do not check that data() receives an index which is valid (i.e. isValid() returns true), belonging to this very model (i.e. model() returns this), and pointing to an existing item (i.e. its row and column are in a valid range).

    QVariant data(const QModelIndex &index, int role) const override
    {
        if (role != Qt::DisplayRole)
            return {};

        // what happens here if index is not valid, or not belonging to this model, etc.?
        return m_data.getData(index.row(), index.column());
    }

I personally maintain quite a strong point of view about this issue: passing such indices is a violation of the API contract. A model should never be assumed to be able to handle illegal indices. In other words, in my (not so humble) opinion, the QAbstractItemModel API has a narrow contract.

Luckily, Qt’s own views and proxy models honour this practice. (However, be aware that some other bits of code, such as the old model tester from Qt Labs, does not honour it, and will pass invalid indices. I will elaborate more on this in the next blog post.)

Since Qt will never pass illegal indices to a model, it’s generally pointless to make QAbstractItemModel APIs have wide contracts by handling all the possible inputs to its functions; this will just add unnecessary overhead to functions which are easily hotspots in our GUI.

On the other hand, there are cases in which it is desirable to have a few extra safety checks in place, in the eventuality that an illegal index gets passed to our model. This can happen in a number of ways, for instance:

  • in case we are developing a custom view or some other component that uses our model via the model/view API, accidentally using wrong indices;
  • a QModelIndex is accidentally stored across model modifications and then used to access the model (a QPersistentModelIndex should have been used instead);
  • the model is used in combination with one or more proxy models, which may have bugs in the mapping of the indices (from source indices to proxy indices and viceversa), resulting in the accidental passing of a proxy index to our model’s functions.

In the above scenarios, a bug somewhere in the stack may cause our model’s methods to be called with illegal indices. Rather than crashing or producing invalid data, it would be very useful to catch the mistakes, in order to gracefully fail and especially in order to be able to debug them.

In practice all of this means that our implementation of the QAbstractItemModel functions needs some more thorough checks. For instance, we can rewrite data() like this:

    QVariant data(const QModelIndex &index, int role) const override
    {
        // index is valid
        Q_ASSERT(index.isValid());

        // index is right below the root
        Q_ASSERT(!index.parent().isValid());

        // index is for this model
        Q_ASSERT(index.model() == this);

        // the row is legal
        Q_ASSERT(index.row() >= 0);
        Q_ASSERT(index.row() < rowCount(index.parent())); 
        // the column is legal 
        Q_ASSERT(index.column() >= 0);
        Q_ASSERT(index.column() < columnCount(index.parent()));

        if (role != Qt::DisplayRole)
            return {};

        return m_data.getData(index.row(), index.column());
    }

Instead of hard assertions, we could use soft assertions, logging, etc. and returning an empty QVariant. Also, do note that some of the checks could (and should) also be added to the rowCount() and columnCount() functions, for instance checking that if the index is valid then it indeed belongs to this model.

Introducing checkIndex

After years of developing models I’ve realized that I must have written some variation of the above checks countless times, in each and every function of the QAbstractItemModel API. Recently I gave the question some more thought, and I came up with a solution: centralize the above checks, so that I don’t have to re-write them every time.

In Qt 5.11 I have added a new function to QAbstractItemModel: QAbstractItemModel::checkIndex(). This function takes a model index to check, and an option to determine the kind of checks that should be done on the index (see the function documentation for all the details).

In case of failure, the function returns false and prints some information in the qt.core.qabstractitemmodel.checkindex logging category. This gives us the flexibility of deciding what can be done on failure, and also to extract interesting data to debug an issue.

Using the brand new checkIndex() our data() reimplementation can now be simplified to this:

    QVariant data(const QModelIndex &index, int role) const override
    {
        // data wants a valid index; moreover, this is a table, so the index must not have a parent
        Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid));

        if (role != Qt::DisplayRole)
            return {};

        return m_data.getData(index.row(), index.column());
    }

Again, the example has an hard assert, which means that the program will crash in case of an illegal index (forcing the developer to do something about it). On the other hand the check will disappear in a release build, so that we don’t pay the price of the check at each invocation of data(). One could instead use a soft assert or just a plain if statement (as many models — unfortunately — do, including the ones coming with Qt) for customizing the outcome of the check.

This is an example of the logging output we automatically get in case we pass an invalid model index, which is not accepted by data():

qt.core.qabstractitemmodel.checkindex: Index QModelIndex(-1,-1,0x0,QObject(0x0)) is not valid (expected valid)

And this is an example of the output in case we accidentally pass an index belonging to another model (which happens all the time when developing custom proxy models):

qt.core.qabstractitemmodel.checkindex: Index QModelIndex(0,0,0x0,ProxyModel(0x7ffee145b640)) is for model ProxyModel(0x7ffee145b640) which is different from this model TableModel(0x7ffee145b660)

Conclusions

I hope that this addition to QAbstractItemModel will help developers build better data models, and to quickly and effectively debug situations where the model API is being misused.

In the next instalment I will talk about other improvements to the model/view framework in Qt 5.11.

About KDAB

KDAB is a consulting company offering a wide variety of expert services in Qt, C++ and 3D/OpenGL and providing training courses in:

KDAB believes that it is critical for our business to contribute to the Qt framework and C++ thinking, to keep pushing these technologies forward to ensure they remain competitive.

The post New in Qt 5.11: improvements to the model/view APIs (part 1) appeared first on KDAB.

Calling all contributors!

QtCS

One month to go till Qt Contributors’ Summit in Oslo!

The dates are June 11-12.

If you haven’t yet, now is the time to register!

There will be two intense days of discussions and work on the future of Qt. Anyone who has an interest and has in some way had an influence on the Qt project is welcome to the event to talk and share their views on the current state and future of Qt.

You can find the agenda on the event wiki page. Now is the time to add your topic on the list.

Please note that when you do add a topic, you need to prepare the session, and I will check that you have prepared. Also as a change from previous years, we will not automatically make wiki pages of the sessions (people are free to do so naturally), but put the tasks that come out of the sessions to bugreports, where they are more likely to be followed up.

At this point I would like to thank the sponsors of the event for making this possible!

KDAB-300x204

luxoft-logo

froglogic

 

egits-logo

 

 

1280px-intel-logo-svg

 

logo

 

Thank you and see you in Oslo!

The post Calling all contributors! appeared first on Qt Blog.

Generating Third-Party Attribution Documents

In this post, I’ll show you how to use the qtattributionsscanner tool and Python to generate an attribution document for third-party code in Qt.

Qt and Third-Party Code

Qt is available under both opensource and commercial licenses. While commercial users are free to hide their use of Qt, GPL and LGPL mandate that the use of Qt is properly attributed. In addition, several Qt modules contain third-party code that are bundled under their own licenses. We make sure that the licenses are liberal, so that they do not restrict the use of Qt too much. However, several of them do require attribution, too. Typically, in the documentation of the final product.

We actually go to a great length to make sure that third-party code is correctly attributed in our documentation. We have a process in place that requires any change of third-party code to be carefully reviewed. Additions of new third-party code to a Qt library, or significant updates, need to be approved by Lars Knoll, the chief maintainer of the Qt Project. We use tools like Fossology to double check correct attributions. All third-party code will be listed in the documentation of the respective Qt module, but also in the Licenses used in Qt overview section of the documentation. Significant changes of third-party modules are listed in the respective modules change log. Starting with Qt 5.11, we also will list changes in a separate documentation page.

If you bundle Qt in your application or device, you also need to provide these attributions – usually in the form of an attribution section of your documentation. The most straightforward way to create such a document is to copy the sections in the Qt documentation. However, this is a lot of work and can lead to errors. Luckily, there is now a cleaner way. Since Qt 5.9, the attributions are not written in plain qdoc markup. Instead, they are saved as qt_attribution.json files that are located close to the actual source code. The format of these JSON files is simple and documented (see QUIP-7). Now we just need an application that finds the files and generates attribution documents in a format of your choice.

qtattributionsscanner

It turns out that we already have an application for the collection of qt_attribution.json files: The qtattributionsscanner command line tool. You can find it in the bin directory of Qt.

When you specify a source directory for the tool, it recursively searches for qt_attribution.json files in there, and parses them. In addition, it takes an -output-format parameter, which currently supports qdoc and json as arguments. qdoc output is the default, because the tool was developed for generating Qt documentation. json generates a document in the same format as the input files. As a result, the attributions from the directory tree are placed into one document.

You might ask yourself, how can you generate other formats besides json and qdoc? My first hack, when I had the need to generate a PDF, was to add a markdown argument to qtattributionsscanner. Markdown is easy to read by itself, and there are tools available that convert it to HTML, which in turn can be used to generate a PDF. Anyhow, this is just one format, and the exact layout and content were hard-coded to my needs, so I surely didn’t want to merge this. Wouldn’t it be more flexible to use a template engine, so that you can generate attribution files with the exact format and layout you want?

qtattributionsformatter

What we want is an application that generates documents out of a JSON document and a template file. In the spirit of “not reinventing the wheel”, let’s use a language and library that makes this easy. I’ve been going for Python, using the Jinja2 templating engine. This is the Python file for setting up the engine:

import argparse
import io
import json
import os
import sys
from jinja2 import Environment, FileSystemLoader, Template

parser = argparse.ArgumentParser()
parser.add_argument("-f", "--file", nargs="?", help="qt_attribution.json file",
                    type=argparse.FileType('r'), default=sys.stdin)
parser.add_argument("-o", "--out", nargs="?", help="file to write to",
                    type=argparse.FileType('w'), default=sys.stdout)
parser.add_argument("-t", "--template", help="template file to use", default="markdown.md")
parser.add_argument("-v", "--verbose", action="store_true")
args = parser.parse_args()

# Set up jinja2
env = Environment(
  loader = FileSystemLoader(os.path.dirname(os.path.realpath(__file__)) + "/templates")
)
template = env.get_template(args.template)

# Read in qt_attribution.json file
attributions = json.load(args.file)

# Load content of license files directly into the structure
for entry in attributions:
  if entry['LicenseFile']:
    if (args.verbose):
      sys.stderr.write("Loading " + entry['LicenseFile'] + "...\n")
    with io.open(entry['LicenseFile'], mode='r', encoding='utf-8', errors='replace') as content:
      entry['LicenseText'] = content.read()

# Render
result = template.render(attributions = attributions)
args.out.write(result.encode('UTF8'))

And this is the markdown.md file template:

# Attributions for Qt Libraries

{% for entry in attributions -%}
{%- if "libs" in entry.QtParts -%}
## {{entry.Name}}

Copyright

```
{{entry.Copyright}}
```

License: {{entry.License}}

```
{{entry.LicenseText}}
```
{%- endif %}
{%- endfor %}

With {%- if "libs" in entry.QtParts -%} ... %{-endif}, we filter out attributions that are not part of Qt libraries, but examples, tools, or tests.

You can also find the sources at https://git.qt.io/kakoehne/qtattributionsformatter.

Putting It Together

To generate a list of attributions in Qt in Markdown, we can now combine the qtattributionsscanner for the collection part and the new qtattributionsformatter.py for the formatting part:


qtattributionsscanner --output-format json qt-everywhere-src-5.11.0-rc1/ | python qtattributionsformatter.py > qt_attributions.md

Outlook

This was easy enough. So you might ask yourself why isn’t this part of Qt yet, in this form or in a similar form? That is because there are some shortcomings:

  • Chromium uses its own file format, which qtattributionsscanner does not understand yet. Therefore, the output does not include third-party code inside Qt WebEngine yet.
  • You need a Qt source code checkout. I think we should package the JSON files as part of the build artifacts so that you can also generate documentation for a binary installation of Qt.
  • The attribution text is unnecessarily long, because a lot of license texts are duplicated.
  • When running on the default Qt checkout, the tool will pick up attributions for all Qt libraries, even if your application does not use a particular library. For now, you can limit this by either tweaking the source tree or adding some basic filtering to Python. Int the long run, this should be done automatically for you. The deployqt tools (windeploqt, macdeployqt …) can determine which libraries to package and similar logic could be used for generating code attribution documentation.
  • Even if you just take the libraries into account, there might be code that your Qt build doesn’t use. A lot of the third party code is in fact optional and only used on some platforms or in some setups.

The last issue raises some interesting questions. Should we use the Qt configuration system to select the necessary attributions? Or should we use Quartermaster, which uses a build graph to determine which attributions are needed? How big of a problem do ‘false positives’ present?

Even though more research is needed before making the generation of attribution files an official feature, I hope anybody struggling with this issue will find this proof-of-concept helpful.

The post Generating Third-Party Attribution Documents appeared first on Qt Blog.

QML and Qt for Python interaction

Besides QtWidgets for desktop applications, Qt has another UI technology, QML.
Today, I would like to show how QML interacts with Qt for Python, roughly based on the tutorial example declarative/extending/chapter3-bindings.

First, let’s have a look at the typical boiler plate code for loading a .qml file. We instantiate a QGuiApplication and a QQuickView.
We set its resize mode property to SizeRootObjectToView so that the QML element is expanded to the view size.

app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)

We then instruct the view to load the QML file, using the method setSource.
Since a QML file typically is to be found next to the Python script, we construct a complete path using functions of the os module:

current_path = os.path.abspath(os.path.dirname(__file__))
qml_file = os.path.join(current_path, 'app.qml')
view.setSource(QUrl.fromLocalFile(qmlFile))
if view.status() == QQuickView.Error:
    sys.exit(-1)

Now, the view can be shown and the application run. To ensure the correct destruction order, del must be invoked on the view object before quitting the application

view.show()
res = app.exec_()
del view
sys.exit(res)

With this code, we can display QML files. For example, a minimal hello world is shown when creating app.qml as follows:

import QtQuick 2.0

Text {
    text : 'Hello, world!'
}

Extending QML by using classes written in Python

Let’s implement something on top of QQuickPaintedItem:

class PieChart (QQuickPaintedItem):
    def __init__(self, parent = None):
        QQuickPaintedItem.__init__(self, parent)
        self.color = QColor()

    def paint(self, painter):
        pen = QPen(self.color, 2)
        painter.setPen(pen);
        painter.setRenderHints(QPainter.Antialiasing, True);
        # From drawPie(const QRect &rect, int startAngle, int spanAngle)
        painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1),
            90 * 16, 290 * 16);

    def getColor(self):
        return self.color

    def setColor(self, value):
        if value != self.color:
            self.color = value
            self.update()
            self.colorChanged.emit()

    colorChanged = Signal()
    color = Property(QColor, getColor, setColor, notify=colorChanged)

This overrides the QQuickPaintedItem.paint() method to draw simple pie chart. The color is defined as property so that it is exposed to Qt. To make the type known to QML, we insert:

qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart');

right after creating the QGuiApplication.

app.qml can then be changed to:

import Charts 1.0
import QtQuick 2.0

Item {
    width: 300; height: 200

    PieChart {
        id: chartA
        width: 100; height: 100
        color: "red"
        anchors.centerIn:parent
    }

    MouseArea {
        anchors.fill: parent
        onClicked: { chartA.color = "blue" }
    }

    Text {
        anchors {
            bottom: parent.bottom;
            horizontalCenter: parent.horizontalCenter;
            bottomMargin: 20
        }
        text: "Click anywhere to change the chart color"
    }
}

for our custom type to appear.
Additionally, clicking with the mouse will change the color property.

The post QML and Qt for Python interaction appeared first on Qt Blog.

Modern C++ and Qt – part 2.

I recently did a short tongue-in-cheek blog post about Qt and modern C++. In the comments, people discovered that several compilers effectively can optimize std::make_unique<>().release() to a simple new statement, which was kind of a surprise to me.

I have recently written a new program from scratch (more about that later), and I tried to force myself to use standard library smartpointers much more than what I normally have been doing.

I ended up trying to apply a set of rules for memory handling to my code base to try to see where it could end.

  • No naked delete‘s
  • No new statements, unless it was handed directly to a Qt function taking ownership of the pointer. (To avoid sillyness like the previous one)
  • Raw pointers in the code are observer pointers. We can do this in new code, but in older code it is hard to argue that.

It resulted in code like

m_document = std::make_unique<QTextDocument>();
    auto layout = std::make_unique<QHBoxLayout>();
    auto textView = std::make_unique<QTextBrowser>();
    textView->setReadOnly(true);
    textView->setDocument(m_document.get());
    layout->addWidget(textView.release());
    setLayout(layout.release());

By it self, it is quite ok to work with, and we get all ownership transfers documented. So maybe we should start code this way.

But there is also a hole in the ownership pass around, but given Qt methods doesn’t throw, it shouldn’t be much of a problem.

More about my new fancy / boring application at a later point.

I still haven’t fully embraced the c++17 thingies. My mental baseline is kind of the compiler in Debian Stable.

Cutelyst 2.3.0 released

Cutelyst - The C++ Web Framework built with Qt, has a new release.

In this release a behavior change was made, when asking for POST or URL query parameters and cookies that have multiple keys the last inserted one (closer to the right) is returned, previously QMap was filled in reverse order so that values() would have them in left to right order. However this is not desired and most other frameworks also return the last inserted value. To still have the ordered list Request::queryParameters("key") builds a list in the left to right order (while QMap::values() will have them reversed).

Some fixes on FastCGI implementation as well as properly getting values when uWSGI FastCGI protocol was in use.

Lastly a crash when performing TechEmpower benchmarks resulted in the removal of some nested event loops calls that were creating a huge stack, and made me realize that my proposed methods to make async apps easier were broken by design, basically you can't use QEventLoop::exec() to wait for events. So Context::wait() and next() are deprecated and the code disabled, with the exception of WebSockets until I can make some changes to HTTP/1 and FastCGI parser both are to be considered synchronous.

Removing a QCoreApplication::processEvents() that was added in order to try to give other connections an execution slice almost doubled the speed in plain text when benchmarking locally, using a single core the requests per second have gone from 105 K to 190 K, after understanding the stupidity I did this isn't of much surprise :)

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

Qt for Automation Blog Series

Greetings!

It’s not a big secret that both the industrial and infrastructure sectors will be far more automated in the future. The main trends that drive this movement are the ubiquitous Digital Transformation, as well as standardization within the industry 4.0 and upcoming industrial IoT technologies. Side note: if you’d like to learn more about those trends in detail, we have written two ebooks on the topic. One focuses on the technical aspects, one on the business aspects. Both are of course free on our resources page

On the road to discovering new businesses ventures, you may have asked yourself: What are use cases? Is the market ready? How do we monetize our product? Is the technology ready?

If the last one sounds like more of an afterthought, you might not be aware of all the pitfalls related to scalability you will encounter sooner or later:

Think about thousands of sensors that measure dozens of different types of data, network environments with varying degrees of reliability, numerous variations of user end-points with or without displays. Add to that the choice of platform you want to run your software on. Desktop environments? Mobile? Embedded? The Cloud?

Generally speaking, you will have to implement more functionalities for more use-cases, on many platforms, in many flavors, with better performance and footprint, but with less code and smaller data traffic!

Perfectly aligning all these elements requires careful planning to avoid scalability issues and to stay flexible to efficiently develop, improve and maintain your applications.

The good news is that leading technology vendors are already looking for solutions. And that’s what this blog series is about: To inspire and prepare you with best practices and technologies on how to start off your project and make it ready for the future.

Over the next couple of weeks, please look forward to reading the following topics (links will be updated as we publish the posts):

Find out more and Get in Touch

If you’re curious about what’s in the Qt for Automation box, head on over to our website or contact us.

The post Qt for Automation Blog Series appeared first on Qt Blog.

Release 2.16.1: Live Code Reloading with Custom C++ and Native Code for Qt

You want to use QML live code reloading to develop your application and you have custom C++ code? V-Play version 2.16.1 introduces the Live Client Module. You can use it to add QML live reloading features to your own application. This release also adds an important change for iOS app publishing, as well as other fixes and improvements.

Create Mobile Apps with QML Live Reloading on Desktop, Android and iOS

With the V-Play SDK, you can develop your mobile apps with live code reloading. View your app on any connected device at the same time, without waiting for slow deployment.

 

Tip for Qt developers: You can also use live code reloading with Qt Quick applications that do not include V-Play components! This means if your app uses for example an ApplicationWindow as root component and does not use any V-Play import, the live code reloading for your QML code still works.

How does QML Live Reloading with V-Play Live Work

Time for a quick detour to the basics of a Qt application. It consists of 2 layers.

qt-application-cpp-qml-layers

The C++ layer handles all the core functionality and does the heavy lifting. The C++ layer also contains the QML engine, which is able to load QML code at runtime. Thanks to the QML engine, you can reload the whole QML layer at runtime.

This is exactly what happens when you hit save, and V-Play Live reloads your application. Your changed QML, JS and asset files are transferred to the V-Play Live Client, and the QML layer is reloaded.

qt-application-cpp-qml-layers-with-vplay-live

All your custom C++ code however is part of the C++ layer. This code requires a build step to compile and deploy with the application. Many of you guys requested to be able to use your own C++ code together with QML live reloading. Good news for you, you can now use the V-Play Live Client Module in your own applications!

How to Build your own Live Client with Custom C++ and Native Code

With the new Live Client Module, you can add live code reloading to your own application in seconds. All you need to do is perform 2 simple steps:

1. Add the v-play-live config to your pro file

Open the *.pro file of your project and change the following line:

CONFIG += v-play

to this:

CONFIG += v-play v-play-live

Or you can also use 2 separate lines like this, so you can enable/disable the Live Client Module easier:

CONFIG += v-play
CONFIG += v-play-live

Also make sure that your resources are commented out in your pro file:

RESOURCES += # resources.qrc # uncomment for publishing

2. Start the Live Client instead of your project main QML file

Go to your project’s main.cpp file and add the following line at the include section at the top:

#include <VPLiveClient>

You do not want to load your project’s main QML file initially, instead you want to start as Live Client. Your project will then start with a connection screen and you can connect to the Live Server.

Remove the following 2 lines in your main.cpp file. You will need those lines for standard deployment or publishing later, so only comment them like this:

// vplay.setMainQmlFileName(QStringLiteral("qml/Main.qml"));
// engine.load(QUrl(vplay.mainQmlFileName()));

Now we can start the Live Client with one line of code. Add it just before the return statement at the end of the main function:

VPlayLiveClient liveClient(&engine);

That’s it, you turned your own project into a Live Client. Build and run your project for any platform you want, Windows, macOS, Linux, Android or iOS.

live-client-module-mobile-and-desktop

You can connect it to your Live Server just like the default Live Clients.

custom-live-client-connected-in-server

Tip: Disable the automatic start of the default Live Client in your Live Server, because you will use your own client instead!

disable-automatic-start-of-default-live-client

To switch back to standard deployment, for example to publish your app, just undo the changes above.

Use Cases with new Live Client Module

There also is a more detailed blog post about communication between C++ and QML. These are only short examples, to give you an idea of what you can do.

Add a Global C++ Object as a Context Property

You can make C++ objects accessible from anywhere in your QML files, with a context property.

Expose an object of your custom C++ class with a context property, e.g. in your main.cpp:

int main(int argc, char *argv[])
{
  MyGlobalObject* instance = new MyGlobalObject();
  engine.rootContext()->setContextProperty("myGlobalObject", instance);
}

Now you can access your context property from anywhere inside your QML files.

AppButton {
  text: "Do Something"
  onClicked: myGlobalObject.doSomething("with this text")
}

You can find a full example including the C++ files here: How to Access a C++ Object from QML

Register your C++ Class as QML Type

Another option to communicate between C++ and QML, is exposing your C++ class as QML type.

Expose the QML type, e.g. in your main.cpp:

#include "myqmltype.h"

// …

int main(int argc, char *argv[])
{
  // …

  // MyQMLType will be usable with: import com.yourcompany.xyz 1.0
  qmlRegisterType<MyQMLType>("com.yourcompany.xyz", 1, 0, "MyQMLType");

  // …
}

Use your custom QML type anywhere in your QML files:

import com.yourcompany.xyz 1.0

// …

MyQMLType {
  id: myType
  someProperty: "someValue"
  onSomePropertyChanged: doSomething()
}

You can find a full example including the C++ files here: How to Register your C++ Class as a QML Type

GitHub Example for using C++ with QML

You can also download this example project from GitHub. The Live Client Module integration steps are already prepared in the VPlayCppQML.pro and main.cpp files, you only need to uncomment them!

Download GitHub Example

Use All V-Play Plugins with Live Reload

Some plugins, like push notifications, rely on the app identifier of an application. With the Live Client Module, you will build your applications with your own app identifier set. This means you can use those plugins with live reloading as well.

Teaser: Use Live Code Reloading also for Published Apps

To see code changes reload your app within seconds on mobile or Desktop without a recompile is a magic moment. Once you experienced it, you’ll wonder how you could develop without it as it is THE biggest time improvement for development.

What if you could also update your published app in the app stores (or on Desktop) just as simple as during development? Your users would not need to update your app via the app stores, but you can choose which version you want to provide them. And this update is available to your users within seconds, no app store update process required.

We are currently working on this solution. If you are interested in access to it, please contact us here.

iOS Bundle Identifier Migration

Starting with V-Play 2.16.1, the app’s bundle identifier for iOS is set using the PRODUCT_IDENTIFIER setting in your *.pro project configuration. To adapt to the new setting perform the following steps:

1. Open your *.pro project file and add the following block:

# configure the product's bundle identifier
# this identifier is used for the app on iOS
PRODUCT_IDENTIFIER = com.your.company.YourApp

where com.your.company.YourApp matches the CFBundleIdentifier setting of your existing Project-Info.plist configuration.

2. Open your Project-Info.plist in the ios subfolder and replace the value of CFBundleIdentifier with $(PRODUCT_BUNDLE_IDENTIFIER), so that it looks like the following:

<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>

3. After running qmake, your iOS build uses the new setting.

Note: Make sure to transition your project to this new format, as otherwise app store build uploads from Xcode 9 might fail.

All V-Play Project Wizards already use the new project setting.

More Improvements and Fixes

  • SimpleRow now includes a badgeValue property that allows to show a specified value in a badge style on the right edge of the row.
    vplay-simple-row-badge
    import VPlayApps 1.0
    import QtQuick 2.0
    
    App {
      id: app
    
      Navigation {
        navigationMode: navigationModeDrawer
    
        NavigationItem {
          icon: IconType.heart
          title: "Badge Item"
          badgeValue: "9"
    
          NavigationStack {
    
            Page {
              title: "My First App"
    
              SimpleRow {
                badgeValue: "5"
                text: "Badge Row"
              }
            }
          }
        }
      }
    }
    
  • NavigationItem uses the new SimpleRow::badgeValue property to show a specific value displayed in a badge style on the right edge of the row, if displayed with navigationModeDrawer.
    vplay-navidationitem-drawer--simple-row-badge
    Code Example
  • You can now use the SearchBar::textField property to access the internal AppTextField of the search bar.
  • Fixes a potential crash and function evaluating warnings during object destruction when a Navigation and NavigationStack setup is used together with a Loader item.
  • Resolves a possible memory leak on iOS during app shutdown with the GoogleCloudMessaging and GameCenter plugin.

How to Update V-Play

Test out these new features by following these steps:

  • Open the V-Play SDK Maintenance Tool in your V-Play SDK directory.
  • Choose “Update components” and finish the update process to get this release as described in the V-Play Update Guide.

V-Play Update in Maintenance Tool

If you haven’t installed V-Play yet, you can do so now with the latest installer from here. Now you can explore all of the new features included in this release!

For a full list of improvements and fixes to V-Play in this update, please check out the change log!

 

 

 

More Posts Like This

 

feature
How to Make Cross-Platform Mobile Apps with Qt – V-Play Apps

teaser-iphonex-support-and-runtime-screen-orientation-change-705px

Release 2.16.0: iPhone X Support and Runtime Screen Orientation Changes

new-firebase-qt-features-live-code-reloading-qt-5-10-1-vplay-release-2-15-1
Release 2.15.1: New Firebase Features and New Live Code Reloading Apps | Upgrade to Qt 5.10.1 & Qt Creator 4.5.1

new-mobile-app-development-documentation-with-qml-live-reloading-of-code-snippets
New Mobile App Development Documentation with QML Live Reloading of Code Snippets

The post Release 2.16.1: Live Code Reloading with Custom C++ and Native Code for Qt appeared first on V-Play Engine.

GSOC 2018 with The Qt-Project

gsoc18

 

It’s summer time and what can be better than an internship and that too with Qt. Yeah, i got accepted in GSOC 2018 with The Qt-Project as my organization.  The goal of my project is to provide meson build system support to Qt-creator natively.

Brief about the project : “Meson is a build system that has become popular with open source projects in the last couple of years. Qt Creator should be able to open meson projects natively. The goal of the project is to provide meson build support to Qt creator IDE.”

My mentor Tobias Hunger is really nice and patient person 🙂 . Tobias helped me in writing a good proposal and helped me in setting up my dev environment too.

Currently we are in Community bonding period and i am getting familiar with the Qt community at dev level. what’s the work procedure, how to contribute and what guidelines to follow.

I followed this guide : https://wiki.qt.io/Setting_up_Gerrit to setup my dev environment.

Some common problems/FAQ that you can face are :

  1. not using real name in git config user.name
  2.  if you encounter any sanity bot check errors follow this guide : http://wiki.qt.io/Early_Warning_System
  3. Follow coding guideline : http://wiki.qt.io/Qt_Coding_Style

That’s all for now folks. To know more about my progress , stay tuned for more blog posts 😉

P.S. if you want a video tutorial on how to setup the working environment just let me know. I will try to create it . PEACE !!

 

Compressed Textures in Qt 5.11

As modern user interfaces become ever more graphics intensive, the demands on graphics memory to hold the textures increase. This is particularly relevant for embedded systems, where resources come at a higher premium, and can be a challenge for system performance. One of the key remedies for this is to reduce the memory requirements of the graphics assets.

OpenGL texture compression has the potential to give significant savings both in startup time and runtime performance:

  • Startup: no time required to uncompress the jpeg or png format
  • Startup: since the texture is much smaller, it requires significantly less time to upload it to GPU memory
  • Runtime: Significantly reduced strain on memory bandwidth
  • Decompression is very simple and happens in hardware, so does not pose significant drag down of performance

Compressed textures in Qt Quick 2

The Qt Quick 2 source code has for a long time included the textureprovider example. This showed how to expand Qt Quick with a custom image provider that could read simple ETC1-compressed textures from pkm format container files.

In Qt 5.10, that functionality was imported, somewhat silently, into Qt Quick itself. Hence, without further ado, one could now use a local pkm file or resource as the source of an Image element. In addition, support for ETC2 compression schemes was added.

Now in Qt 5.11, this functionality has been revamped and extended. Most importantly, support for ktx – the Khronos texture container file format – has been added. This format allows a much wider range of compression schemes, so Qt Quick is in practice only limited by what the target GPU and driver can handle.

screenshot

Using compressed texture files in a Qt Quick application requires nothing special. The key part of the qml code for the screenshot above is simply:

Grid {
    columns: 2
    Image { source: "slides.png" }
    Image { source: "slides.ktx" }
    ...
}

As always, the memory savings comes at a cost. There is a trade-off between memory and visual quality. In the screenshot above, one can see how the bottom edges of the green area have become ragged compared to the original. The different texture compression schemes can provide different results, both in memory savings and image quality.

Transparency Trick

Special consideration must be taken for textures with transparency. For performance reasons, Qt Quick expects transparent textures to have the alpha channel pre-multiplied into the color channels. For normal images, Qt Quick takes care of this itself. But for compressed textures, it must necessarily be done before the image compression is performed. Some texture compression tools have built-in ability to do this. For those that do not, one can use other image manipulation tools to pre-process the source assets. For example, using ImageMagick, the following command line will create an image copy with pre-multiplied alpha:

convert mytexture.png \( +clone -alpha Extract \) -channel RGB
        -compose Multiply -composite mytexture_pm.png

Note that the resulting mytexture_pm.png will not look right when viewed with a normal png viewer, since the png format itself does not handle pre-multiplied alpha. But after texture compression and loading into Qt Quick, it will be correct.

Fallback Fix

Now, what if one wants to run the application and the compressed texture files are not available, or not usable? Say, during development one may have only the original images available, or one may want to run on a target without OpenGL support. It is suboptimal to have a separate variant of the qml code for such cases. Naturally, there are many ways to solve this issue in Qt Quick. However, Qt 5.11 has added a little feature to the Image element that makes it particularly easy in many cases, namely automatic file extension detection. This means that if an Image element specifies a non-existing local file or resource name, Qt Quick will search for an image file with the same base name, by appending the known file extensions in turn. So, for example, if the code example above was changed to:

Image { source: "slides" }

Qt Quick will do the following:

  • First, if OpenGL is available, look for “slides.pkm” and “slides.ktx”, and load the first file found, if any.
  • Then, if nothing loaded by step 1, look for “slides.jpg”, “slides.png” etc., and load the first file found.

So, by just leaving out the file extension of the source file in the Qt Quick code, one has created a simple fallback mechanism.

The post Compressed Textures in Qt 5.11 appeared first on Qt Blog.

Hello Qt for Python

The first Qt for Python technology preview release is almost here, and for this reason we want to give a brief example on how it will open the doors to the Python world.

Let’s build a simple application to show the simplicity of Qt for Python using QWidgets.
Every script will have more or less the same structure:

  1. We create a QApplication
  2. Then we include all the QWidgets and structures we want to use (e.g., a QLabel)
  3. We show the application and start our QApplication

If we put these ideas together, we will have something like this:

# hello_world.py
from PySide2.QtWidgets import QApplication, QLabel

app = QApplication([])
label = QLabel("Hello Qt for Python!")
label.show()
app.exec_()

To execute it, a simple python hello_world.py will do the work.

But that’s not the whole story, the real question is: how to access the methods of a Qt class?
To simplify the process, we kept Qt APIs. For example, if we want to specify the size of a QLabel, in C++ we will have something like:

QLabel *label = new QLabel();
label->setText("Hello World!");
label->resize(800, 600);

The equivalent using Qt for Python will be:

label = QLabel()
label.setText("Hello World!")
label.resize(800, 600)

Now that we know the equivalent from C++ we can a write a more sophisticated application.

import sys
import random
from PySide2.QtCore import Qt
from PySide2.QtWidgets import (QApplication, QWidget,
    QPushButton, QLabel, QVBoxLayout)


class MyWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.hello = ["Hallo welt!", "Ciao mondo!",
            "Hei maailma!", "Hola mundo!", "Hei verden!"]

        self.button = QPushButton("Click me!")
        self.text = QLabel("Hello World")
        self.text.setAlignment(Qt.AlignCenter)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.text)
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)

        self.button.clicked.connect(self.magic)

    def magic(self):
        self.text.setText(random.choice(self.hello))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MyWidget()
    widget.resize(800, 600)
    widget.show()
    sys.exit(app.exec_())

If you are not familiar with Qt development, it is a common practice to extend a certain class and adapt it to our needs. In the previous example, we are using QWidget as a base class, and we included a QLabel and a QPushButton.

The application is really simple:

  1. First, we write a list containing Hello World in many languages.
  2. Then, we initialize a QPushButton and a QLabel with a certain alignment, font and size.
  3. After that, we create a QVBoxLayout to include our objects, and we assign it to our class.
  4. And finally, we connect the clicked() signal of our QPushButton to our method called magic.

As a result, every time we click the button, we will get a Hello World in a random language!

The structure of this simple script will be the base for most of the applications using Qt for Python, and we encourage you to test it as soon as Qt for Python is out!

The post Hello Qt for Python appeared first on Qt Blog.

Scaling Down to Low-End Hardware with Qt Professional Services

How low do you want to go? Our fantastic guys at R&D have brought Qt over to the microcontroller units (MCUs). Make sure to check our proof-of-concept. The results look promising, and we have received a lot of requests from customers who want to use lower-end hardware to reduce costs. Our ultimate goal this year is to make this service available to everyone, no matter the architecture (hardware + board support package + real-time operating system).

Qt on MCUs

Today, Qt supports i.MX7 on the lowest end, and we are now looking into even lower-end hardware. We’re currently working on two environments; (a) STM32F4/7+RTEMS  (b) NXP1050+uCLinux. Get more technical info with the interesting deep dive in Mikhail’s blog post.

Sounds great, doesn’t it?

In addition to this, you can also contact us if you would like us to help you out with the following:

  • create and maintain a whole end-to-end software stack for your device and tooling
  • create a Qt application architecture tailored to suit your time restrictions, budget, and performance goals
  • deliver turnkey software solution with your application
  • advise on technologies for optimal software performance

So, how low do you want to go? We at the Qt Professional Services team are eager to cut down your costs. Get in touch! (make sure to type “Qt on MCU” in the comment section when filling the form)

 

The post Scaling Down to Low-End Hardware with Qt Professional Services appeared first on Qt Blog.

Qt on Microcontrollers (MCU)

People often ask us about if it’s possible to use Qt for software development on microcontrollers (MCU), and if Qt can run without an operating system (“bare metal”). Today we will answer these questions and show you some concrete examples.

What is the point of using microcontrollers?

MCUs are small computers on a single integrated circuit. They’re similar to systems on a chip (SoC), albeit less sophisticated. Microcontrollers are used in automatically controlled products and devices, such as car engine control systems, implantable medical devices, wearables, remote controls, office machines, appliances, power tools, toys, and other embedded systems. The main advantage of using MCUs is their small size and comparatively very low cost – especially for large volumes of production.

So, we can already see the main features of MCUs from the definition: small size, low power consumption and, naturally, low price per unit. Thus, we can say that the main point of using MCU is a natural desire to save cost.

Why use Qt on an MCU?

Low computing power applies certain restrictions to the choice of software development tools, especially if we talk about the GUI, e.g. in regards to firmware size, runtime memory usage and how “fancy” the GUI can be.

Today we do not have a universal GUI library for MCUs. Sure, there are some that could solve some part of the task for this or that particular MCU model, but that is not enough. And quite rarely (or actually never) those libraries are created with “cross-platform-ability” in mind.

Although some commercial toolkits are actually pretty good, in most cases they have a closed source code. So you’re buying a “black box” and risk to find yourself vendor-locked.

Now imagine how great it would be if we could use the Qt framework: cross-platform and comprehensive library of classes (including GUI), with excellent documentation and lots of examples, and with a fantastic Open Source community.

Unfortunately, up to this moment, due to the mentioned hardware restrictions, embedded development with Qt (Qt for Device Creation) was officially supported only on devices of Cortex-A level, mostly under Linux and some commercial RTOSes (INTEGRITY, QNX, and VxWorks).

But today, this situation has changed.

Research

Getting started

So, we got ourselves a research: investigate the possibilities of running Qt on MCU hardware.

Let’s be clear from the beginning on what microcontrollers we’re talking about exactly because some might start to dream about MCUs with a 12 Mhz CPU and 128 bytes of RAM. That would be quite a gap because Qt’s current hardware requirements are:

  • 256 MB of RAM;
  • 500 MHz CPU (1 GHz preferred);
  • OpenGL ES 2.0 support.

Definitely not the microcontroller level, because those have a far smaller footprint.

And the boards we selected for the research are:

STM32F469STM32F469 – ARM Cortex-M4, FPU unit single precision

STM32F746STM32F746 – ARM Cortex-M7, FPU unit single precision, L1 Cache (Data/Instruction)

STM32F769STM32F769 – ARM Cortex-M7, FPU unit double precision, L1 Cache (Data/Instruction)

As you can see from specifications, their hardware resources are way lower than what Qt “officially” requires.

Regarding OpenGL support, thanks to Qt Quick 2D Renderer it is not a strict requirement, because we can render our graphics using raster paint engine.

We started with porting the following Qt modules:

Porting

How do you port Qt to different target platforms? Well, first we need to understand what exactly is required for Qt to function. And in general, there are two main requirements you need to meet:

  • POSIX-compatible operating system;
  • C++11-compatible compiler.

Let’s start with C++11 requirement. With version 5.7, Qt started to require platforms to support C++11 because we aim to provide a powerful and modern C++ framework. However, if your platform can only support C++98 at best, then you can of course try to do it with Qt 5.6 (or older), but then considering the fact that new configuration system (so-called Qt Lite) was introduced only with Qt 5.8, it will be a tough task for you to “squeeze” Qt into an MCU environment.

Now regarding POSIX – Portable Operating System Interface. That actually answers the question why Qt does not work on “bare metal” out of the box. Inside Qt we are using a lot of POSIX functions (pthreads, mmap, fopen, open and others), so if we want to run Qt on bare metal, we need to create your own implementation of POSIX – basically implement your own operating system. Fortunately, that isn’t the case in our research.

We decided to use an Open Source RTOS and we chose RTEMS for its most notable features:

  • simplicity;
  • POSIX support;
  • supports various file systems, including NFS and FAT;
  • includes a port of the FreeBSD TCP/IP stack;
  • C++11 support;
  • Open Source license (modified GPL);
  • an active community.

The process of porting Qt to RTEMS consists of the following steps:

  • Configure the board – set clock generator (frequency), memory (SDRAM, caches, MPU), initialize peripheral and so on;
  • Port RTEMS to STM32F4/F7 (create a BSP);
  • Port Qt to RTEMS:
    • Add support for it in Qt Core;
    • Create a new QPA plugin.

Porting Qt itself can be presented in the following illustration:

porting-qt

We won’t describe the whole process in detail (from configuring the board till the creation of a new QPA) just yet, even though that’s probably the most interesting part of the research. But this article was aiming only to tell you about the research and not to provide a step-by-step manual. If you are interested in conduction a pilot project, please contact us and submit your request.

Results

To demonstrate the results, we created three firmwares for each board with different demo applications.

Qt Widgets demo

Firmware size: 6.6 MB.
RAM required: 3.4 MB.

As we can see, Qt Widgets runs just fine.

Qt Quick / QML demo

Firmware size: 9 MB.
RAM required: 5 MB.

It’s easy to see that Qt QML’s dragging animation is somewhat slow on STM32F4/F746, but the clocks work rather well. Such behavior is an excellent example of lacking JIT compilation because those MCUs don’t support double-precision floating-point. However, STM32F769 does support it, thus the dragging animation looks much nicer on this board.

E-bike demo

We decided not to stop on simple demos and for the third firmware, we tried to run something more interesting. For instance – our recent e-bike demo.

Firmware size: 13 MB.
RAM required: 10 MB.

And even this demo works fine too. By the way, thanks to the cross-platform nature of Qt, we didn’t have to change a single line of code to compile it for RTEMS (the original target was running on Linux).

Conclusion

We can conclude that our research was successful. Sure, it is not a ready out-of-the-box solution right now, but we will continue to work on it.

Current tasks include the following:

  • porting more Qt modules, and first of all – libraries from Qt for Automation addon;
  • further port optimizations and performance improvements, e.g. to make use of the graphics accelerators provided by the boards, which we haven’t utilize yet;
  • further tinkering with the Qt configuration system (Qt Lite);
  • adding support for development on MCUs into Qt Creator.

So, what does this research mean for you and your projects? The source code of the new QPA and other modifications to the Qt code base should be available in Open Source (most probably under GPLv3), and of course in commercial license too, so you’ll be able to try it out yourself.

And we plan to provide consultancy services for preparing a system image and porting Qt to your MCU-based platform. We’ll have more information about that very soon, so stay tuned!

In the meantime, make sure to sign up for the Qt on MCUs webinar where we tell you more about the topic, show you some demos and answer your questions!

The post Qt on Microcontrollers (MCU) appeared first on Qt Blog.

Qt Creator 4.6.1 released

We are happy to announce the release of Qt Creator 4.6.1!

We fixed several issues in Android support, Clang code model, CMake and QMake project support, and more. Please find out about the details in our change log.

Get Qt Creator 4.6.1

The opensource version is available on the Qt download page, and you find commercially licensed packages on the Qt Account Portal. Qt Creator 4.6.1 is also available through an update in the online installer. Please post issues in our bug tracker. You can also find us on IRC on #qt-creator on chat.freenode.net, and on the Qt Creator mailing list.

The post Qt Creator 4.6.1 released appeared first on Qt Blog.

Virtlyst 1.1.0 released

Virtlyst - a libvirt web interface to manage virtual machines has a new release.

This release finishes support to connect to TCP or TLS virtd servers, it also fixes creating new instances from the flavor panel. And a few other fixes.

Of course I forgot to add the mandatory screenshot last time so here it goes:

instances

console

Go get it! https://github.com/cutelyst/Virtlyst/releases/tag/v1.1.0

If you like this software you can also support my work via patreon.

Participating the GENIVI All Member Meeting 2018 in Munich

The GENIVI All member meeting was held this year in Munich. I had the pleasure of joining the discussions on domain interaction, graphics sharing and hypervisor use in the automotive space.

One of the most interesting presentations on graphics sharing was given by BMW Car IT on the Ramses project, which allows transmitting a graphics scene over the network with relatively small amount of traffic. This is because Ramses implementation does not send all OpenGL commands for the next frame but only the ones that have changed. This maps well to automotive UI use cases where most of the time there aren’t a lot of changes. BMW showed a really impressive demo where 3D graphics content was provided by two sources to one scene. They are planning to contribute the implementation of Ramses to open source in Q3 2018.

There were two other presentations on graphics sharing by Harman and ADIT, which are utilizing different levels of graphics stacks in their implementation. It seems that Qt applications should be already compatible with ADIT’s Waltham protocol implementation.

I personally enjoyed listening to BMW’s talk describing their experiences on running and developing the CI system, which is used for building a Yocto-based Linux distribution. The challenges they had encountered were similar to what I have personally seen at Qt and also on projects prior to joining the Qt company.

I am planning on writing another blog post about how to apply the new Qt Remote Objects API when setting up inter-domain communication between automotive IVI and cluster systems written in Qt. So, stay tuned!

The post Participating the GENIVI All Member Meeting 2018 in Munich appeared first on Qt Blog.

Cutelyst 2.2.0 is out

Cutelyst just got a new release!

Thanks to the release of Virtlyst - a web manager for virtual machines, several bugs were found and fixed in Cutelyst, the most important one in this release is the WebSockets implementation that broke due the addition of HTTP/2 to cutelyst-wsgi2.

Fixing this was quite interesting as when I fixed the issue the first time, it started to make deleteLater() calls on null objects which didn't crash but since Qt warn's you about that it was hurting performance. Then I fixed the deleteLater() calls and WebSockets broke again :) a little of gdb foo and I found out that when I asked for the websocket to close Qt was emitting disconnected as a result of that call, and that signal was deleting the object we rely when we called close, which crashed the app.

As a new feature Context class has two new methods to help with async apps, a wait() method that creates a counter based local event loop and a next() method to decrease the event loop counter till quitting it. This way you can for example connect two QNetworkReply::finished() signals to Context::next() and call Context::wait(2); so once the two requests are finished wait() returns and the client receives the data.

Codacy was also added to increase the number of checks in our code base, and it has already shown some real issues.

UPDATE: Right after release I found a cppcheck code fix broke listening on TCP sockets, yes, writing more unit tests especially for the WSGI module is top on my TODO list. So 2.2.1 is out now :)

Get it here https://github.com/cutelyst/cutelyst/releases/tag/v2.2.1

Inspired by Car HMI event in Shanghai, 2018

Industry events are always unique stories of their own. I got a chance to present the latest thinking within automotive digitalization at the Car HMI event in Shanghai on May 19th, 2018. Together with me there were professionals from different OEMs, tier1s and software vendors operating both globally and locally in China. There was truly a cross pollination of ideas with such a variety of people in the same room. Although simultaneous interpretation creates specific challenges for interaction with the audience it was easy to read the positive reactions – a number of standing people taking pictures with smartphones is the new KPI for any keynote presentation!

Despite the fact that the presentations ranged from quantified market studies to forward leaning concepting cases it was easy to find common themes. The automotive industry has really taken consumer experience to the core of the design work. There were very few feature, capability or technology introductions. Actually, I do not recall any new specific technology intro from the whole event. Most of the presentations were addressing how to understand the consumer and how to bring the knowledge into final product through conceptualization and design processes.

Personally, one of biggest consumer insights was the usage of advanced features while driving – based on Audi’s research the Europeans are operating screens and knobs while driving, but in Asia, especially the Chinese, are operating the most advanced features while standing still. It creates a huge difference in how to approach driver distraction issues. You may see more leading digital experiences coming from China as the user behavior allows much richer use of “distractive” technologies.

The automotive industry has clearly learned one lesson – nobody talks about own experience islands like leading mobile vendors did in the verge of the mobile internet. Everybody is embracing the Internet and cloud based mobile experiences. Cars are becoming eyes of the Internet providing lots of contextual information for perfecting the experiences and at the same time cars are becoming the mouth of the Internet bringing the audiovisual experiences to drivers and passengers.

There is a great need for “something” to simplify the data transactions in both directions. The future experience will be a personalized blend of screens, voice, artificial intelligence and cloud based offerings. The commonly discussed topic was the process transformation needed across the automotive value chain. As consumers are more demanding, the creation process needs to shift several gears up as the current paperclip rockets do not take you to the moon.

One of the keywords mentioned multiple times was “iterativity” as highly connected and cross dependent experiences cannot be designed and developed in a traditional waterfall setup. You must have multiple iterations before the experience is ready to be shipped. In most of the cases the real consumer behavior will mandate changes to the experience on the field and hence the “iterativity” must continue like in any connected experience in the (mobile) Internet. The transformation to iterative approaches will require changes in processes, governance models, talent pools and even company structures. “Iterativity” was discussed also in my keynote through designer to developer workflow vision (picture 1) we have at Qt.

enhanced-developer-workflow

 

In short, the big themes of the industry are well understood and the urgency to change is there. The key question is who can renew itself fastest to serve digitally connected consumers of the future. Looking at Qt’s offering from the past, presence and future – our customers are strong candidates in creating the visually stunning connected experiences for the next generation of automotive customers.

 

The post Inspired by Car HMI event in Shanghai, 2018 appeared first on Qt Blog.