Qt Champion nominations for 2016 now open

Qt_Champion_200
It is the time of the year, when we can all take a moment to think who has been the most helpful, incredible, kind, skilled and friendly person in the Qt community.

Qt Champions is a way to recognize the individuals who strive to help the community most. They can be found in different places and doing different things, but they are all united in their drive to make Qt a friendly and helpful community.

Past Qt Champions include among others, Samuel Gaist, who has always been helpful and friendly on the forum, and has more posts than anyone else. Iori Ayane, who has written and translated several books into Japanese, and is a key person in the Japanese Qt scene. Robin Burchell, who is a long time Qt contributor doing excellent work in the code base. And Johan Thelin and Jürgen Bocklage-Ryannel, the authors of the QML book.

In addition to the recognition that the Qt Champion title brings, the champions get a full Qt license for a year,  invitations to next years main Qt event and naturally an awesome Qt Champion t-shirt!

So if you have ideas on who should be this years Qt Champion, head over to the Wiki to make your Qt Champion nominations!

The post Qt Champion nominations for 2016 now open appeared first on Qt Blog.

KDAB talks at QtCon 2016

Hello!

QtCon_logo

This is a small wrap-up from QtCon, the biggest Qt event in Europe in 2016, that happened at the beginning of September. At QtCon the Qt community joined forces with the KDE, FSFE and VideoLAN communities, to create an exciting event in the spirit of open collaboration and participation amongst projects.

During QtCon many KDAB engineers gave in-depth technical talks about Qt, QML, Qt3D, OpenGL and the other technologies around Qt development. All the sessions were of the highest quality, as you may expect from KDAB speakers, and extremely well received by the audience.

In case you missed some, here’s a complete list. You can find each talk’s description, slides, code / example material, and a recording of the session by following the links.

In no particular order:

See you at the Qt World Summit!

The post KDAB talks at QtCon 2016 appeared first on KDAB.

Qt on Android: How to create an Android service using Qt

Starting with Qt 5.7, we added the ability to create Android services using Qt. In this article we’re going to see how to get started and also how to communicate between the two.

Before we get started I want to add a big bold WARNING about the performance! Because the services are run in the background for a very long time, make sure your service doesn’t drain the device battery!

Getting started

Step I: Extend QtService

Every single Qt Android Service must have its own Service java class which extends QtService, so the first step is to create such a service:

// java file goes in android/src/com/kdab/training/MyService.java
package com.kdab.training;
import org.qtproject.qt5.android.bindings.QtService;

public class MyService extends QtService
{
}

Step II: Add the service section(s) to your AndroidManifest.xml file

The next step is to add the service section(s) to your AndroidManifest.xml file. To do that you first need to copy & paste the template from https://wiki.qt.io/AndroidServices to your AndroidManifest.xml file, then set android:name attribute with your service class name, as shown in the following snippet:

<application ... >
  <!-- .... -->
  <service android:process=":qt" android:name=".MyService">
  <!-- android:process=":qt" is needed to force the service to run on a separate
                                                        process than the Activity -->

    <!-- .... -->

    <!-- Background running -->
    <meta-data android:name="android.app.background_running" android:value="true"/>
    <!-- Background running -->
  </service>
  <!-- .... -->
</application>

BE AWARE: Every single Qt service/activity MUST run in it’s own process! Therefore for each service you must set a different android:process attribute value.

Step III: How to start the service ?

Now you need to decide how to start the service. There are two ways to do it:

  • on demand
  • at boot time

We’re going to check them both:

Start the service on demand

This is the most common way to start your service(s). To start the service you just need to call Context.startService(Intent intent) method. The easiest way is to add a static method to your MyService:

// java file goes in android/src/com/kdab/training/MyService.java
package com.kdab.training;

import android.content.Context;
import android.content.Intent;
import org.qtproject.qt5.android.bindings.QtService;

public class MyService extends QtService
{
    public static void startMyService(Context ctx) {
        ctx.startService(new Intent(ctx, MyService.class));
    }
}

Then simply call it from Qt to start it:

QAndroidJniObject::callStaticMethod<void>("com/kdab/training/MyService",
                                              "startMyService",
                                              "(Landroid/content/Context;)V",
                                              QtAndroid::androidActivity().object());

Start the service at boot time

This method is used quite seldom and is useful ONLY when you really need to run the service at boot time, otherwise I do recommend you to start it on demand.

First you need to add android.permission.RECEIVE_BOOT_COMPLETED permission to your AndroidManifest.xml file:

<application ... >

  <!-- .... -->
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</application>

Then you need to add a receiver element to your AndroidManifest.xml file:

<application ... >
    <!-- .... -->
    <receiver android:name=".MyBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <!-- .... -->
</application>

And finally, you need to implement MyBroadcastReceiver class, as shown in the following snippet:

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent startServiceIntent = new Intent(context, MyService.class);
        context.startService(startServiceIntent);
    }
}

Step IV: Where to put your Qt Service code?

Next you need to decide where you’re going to put your service code. Qt (and qmake) has two options for you:

  • in the same .so file with the application
  • in a separate .so file

We’re going to check them both:

Same .so for app & service(s)

Because you’ll have one big .so file, you need a way to know when it will run as an activity or as a service. To do that you just need pass some arguments to your main function. AndroidManifest.xml allows you to easily do that:

<service ... >
    <!-- ... -->
    <!-- Application arguments -->
    <meta-data android:name="android.app.arguments" android:value="-service"/>
    <!-- Application arguments -->
    <!-- ... -->
</service>

Then make sure you set the same android.app.lib_name metadata for both service(s) & activity elements:

<service ... >
    <!-- ... -->
    <meta-data android:name="android.app.lib_name"
                android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
    <!-- ... -->
</service>

I recommend you to use this method only if your activity and your service(s) share a large piece of code.

Separate .so files for app & service(s)

The second option is to create separate .so files for your app & service(s). First you need to create a separate server .pro file(s):

TEMPLATE = lib
TARGET = server
CONFIG += dll
QT += core
SOURCES += \
    server.cpp

The server .so main entry is the main function:

#include <QDebug>

int main(int argc, char *argv[])
{
    qDebug() << "Hello from service";
    return 0
}

Last you need to load the server .so file:

<service ... >
    <!-- ... -->
    <meta-data android:name="android.app.lib_name" android:value="server"/>
    <!-- ... -->
</service>

Use QtRemoteObject for communication

We’ve seen how to create and how to start a Qt on Android service, now let’s see how to do the communication between them. There are lots of solutions out there, but for any Qt project, I do recommend you use QtRemoteObject, because it will make your life so easy!

QtRemoteObjects is a playground Qt module led by Ford, for object remoting between processes/devices:

  • exports QObjects remotely (properties, signals & slots)
  • exports QAbstractItemModels remotely
  • creates a replicant on the client side you can interface with
  • repc generates source & replica (server & client) source files from .rep files
    • .rep file is the QtRemoteObjects IDL (interface description language)

As you can see it’s very Qt specific!
Let’s see how to add it to your projects and use it.

Get QtRemoteObjects

QtRemoteObjects project is located at http://code.qt.io/cgit/playground/qtremoteobjects.git/, to get it you need to run the following commands:

$ git clone git://code.qt.io/playground/qtremoteobjects.git
$ cd qtremoteobjects
$ ~/Qt/5.7/android_armv7/bin/qmake -r && make && make install

If needed, replace ~/Qt/5.7/android_armv7 with your Qt version and android ABI of choice.

Use QtRemoteObjects

Using QtRemoteObjects is pretty easy, you need to do a few easy steps:

– add QtRemoteObjects to your .pro files

# ...
QT += remoteobjects
# ...

– create .rep file(s)

class PingPong {
    SLOT(void ping(const QString &msg));
    SIGNAL(pong(const QString &msg));
}

– add .rep file(s) to the server .pro file

# ...
REPC_SOURCE += pingpong.rep
# ...

– add .rep file(s) to the client .pro file

# ...
REPC_REPLICA += pingpong.rep
# ...

– QtRemoteObjects source(server) side implementation

#include <QCoreApplication>
#include "rep_pingpong_source.h"

class PingPong : public PingPongSource {
public slots:
    // PingPongSource interface
    void ping(const QString &msg) override {
        emit pong(msg + " from server");
    }
};

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

    QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
    PingPong pingPongServer;
    srcNode.enableRemoting(&pingPongServer);

    return app.exec();
}

Let’s check the code a little bit.
First you need to implement all .rep interfaces (PingPongSource), then export PingPong object using enableRemoting.

– QtRemoteObjects replica(client) side implementation

#include "rep_pingpong_replica.h"

// ....
    QRemoteObjectNode repNode;
    repNode.connectToNode(QUrl(QStringLiteral("local:replica")));
    QSharedPointer<PingPongReplica> rep(repNode.acquire<PingPongReplica>());
    bool res = rep->waitForSource();
    Q_ASSERT(res);
    QObject::connect(rep.data(), &PingPongReplica::pong, [](const QString &msg){
        qDebug() << msg;
    });
    rep->ping("Hello");
// ....

Let’s check the code:

  • use QRemoteObjectNode to connect to QRemoteObjectHost
  • use QRemoteObjectNode:acquire to link the local object to the remote one
  • use the acquired object as its local (call slots, connect to signals, etc.)

As you can see, using Qt + QtRemoteObject is (much?) easier and more straight forward than Android’s Java services + AIDL 😉

Limitations

  • the activities & service(s) must run on a different process.
  • it is not possible (yet) to use QtCreator to easily add a service section to your AndroidManifest.xml file check QTCREATORBUG-16884
  • it is not possible (yet) to use QtCreator to easily generate a service subproject for us, check QTCREATORBUG-16885
  • it is not possible (yet) to see the services logs in QtCreator. You’ll need to use
     $ adb logcat 
    

    to see it, check QTCREATORBUG-16887

  • it is not possible (yet (hopefully)) to debug the services in QtCreator. This feature will take some time to implement it, therefore I’ll not hold my breath for it, check QTCREATORBUG-16886

Please use the above bug report links to vote for your favorite tasks, the ones that have more votes (usually) are implemented first!

You can find the full source code of this article here: https://github.com/KDAB/android

The post Qt on Android: How to create an Android service using Qt appeared first on KDAB.

RFC: How to fix a tricky leak in QFormLayout?

We have a nasty leak in QFormLayout::setWidget(). In setWidget(), we create the QWidgetItemV2 corresponding to the passed QWidget, and pass that on to Private::setItem, which has a bunch of error returns (guard clauses) that do not delete the item, among them negative row index and cell already occupied.

We could easily fix that missing delete, but this function is also used by setLayout(), say, where the item is the layout.

Conceptually deleting that item (= the nested layout) is completely OK, because the user should be able to rely on the form layout to take ownership of the nested layout, without ifs and buts.

But then we have code in tst_qformlayout that breaks. Simplified, it reads:

   QFormLayout layout;
   QHBoxLayout l4;
   layout.addLayout(-1, QFormLayout::FieldRole, &l4);

I guess you spot the problem? If l4 had been added, everything would’ve been peachy: The QHBoxLayout destructor unregistered itself from layout, which does not attempt to delete l4 when it itself is deleted.

But if l4 is not added for some reason, like in the test code above, the fixed code will attempt to delete l4, which is undefined behaviour, of course (double-delete).

I think such broken code deserves to be broken, for the greater good of fixing a resource leak. Esp. since a double-delete should complain much louder than a leak, and the API user can do something about the double-delete while she can’t do anything about the leak (the pointer is not reachable from outside QFormLayout).

I feel uneasy about adding this to 5.6 LTS, though, so I’ll make a minimal fix there, just for setWidget().

What do you think about the larger fix?


Filed under: English, Qt

Qt Conference Apps – out of the Developer Trenches – Part 1

by Ekkehard Gentz [Independent Software Architect, Consultant] (Qt Blog)

In a few weeks the Qt World Summit 2016 will open its doors in San Francisco and I have been given the chance to speak there about my experiences while developing the Qt World Summit 2016 Conference App. This article series here will give you some additional information to my presentation.

For nearly 40 years I have been developing software, where the last 8 years I have focused on mobile App Development. I started mobile App Development with BlackBerry OS7 (Java) followed by BlackBerry 10 native Apps (Qt 4.8, Cascades UI Controls).

In 2016 BlackBerry, for first time ever, started to build secure Android Phones and my customers asked for x-platform Apps. Personally, I liked the way BlackBerry 10 Apps were built using QML and Cascades. Fortunately Qt just started Qt 5.6 Tech Preview of new Qt Quick Controls 2. I did some first tests to see if Qt Quick Controls 2 will enable me to develop good looking and performant mobile Apps.

First steps went well so I decided to spend some more time and to give Qt 5.7 and Qt Quick Controls 2 a try in real-life projects. Over the last 4 years I built many mobile business Apps for Enterprise and SMB and I also did some Apps for Developer Conferences.

I asked Tero Kojo to develop the QtCon 2016 Conference App as a proof-of-concept to rely on new Qt Quick Controls 2. You can download the QtCon Conference App from Google Play (https://play.google.com/store/apps/details?id=org.ekkescorner.c2g.qtcon), Apple App Store (https://itunes.apple.com/us/app/qtcon-2016-conference-app/id1144162386), Amazon App Store (https://www.amazon.com/ekkescorner-QtCon-2016-Konferenz-App/dp/B01L7DVJTO), as APK (https://app.box.com/s/fgeo14re3hrp47shg915geo1q4gzyxrz) or build it by yourself from Open Source Github Repo (https://github.com/ekke/c2gQtCon_x).

The App was built without any extra native Code – pure Qt only. Feedback was great and I just started to do the Qt World Summit 2016 Conference App – Github Repo will be public soon. Hopefully this time the App will also be available for Windows 10 from Windows App Store. Special thanks to Maurice Kalinowski for his help, the QtCon Conference App is running on Windows 10, although I had some problems uploading this to Windows App Store.

There is a blog series about all my experiences using Qt Quick Controls 2 to develop mobile Apps (http://j.mp/qt-x), also a series in (German) Web & Mobile Developer Magazin and now some articles here at Qt Blog, too. You can expect some 3 – 4 articles here at Qt Blog about developing Qt Conference Apps.

All development is done in my spare time and my goal is to motivate mobile App Developers to try out Qt Quick Controls 2 to develop x-platform Apps. I never did Qt development before, also never did native Apps for Android, iOS or Windows but now I am able to develop and upload Apps to Google Play or Apple App Store :) I am also using Google Material Style to provide a modern mobile App feeling. Thanks to J-P Nurmi, Mitch Curtis and others for great hints HowTo customize Qt Quick Controls 2.

From my experiences over the last 6 months, developing mobile Apps with Qt 5.7 and Qt Quick Controls 2 is much more comfortable and easier than using Xamarin, React Native, Cordova, Angular or Ionic. The good news for all my friends from BlackBerry 10 community: there is a great amount of re-use of C++ Code from Cascades and also architecture style is similar using Signals/Slots and QObject* as data model.

Speed is key to success

The first impression of any mobile App with regards to User Experience comes from starting the App. The User should never have the feeling that an App is slow. Some of my recipes for a speedy start are below:

  • fast creation of C++ Classes
  • immediately show something on the screen
  • be dynamic: only instantiate UI Controls you really need

How am I doing this? Only instantiate C++ Classes, avoid any initialization as open Databases, load Cache Files and more.

DataServer::DataServer(QObject *parent) : QObject(parent)
{
    // Do NOTHING HERE
}

Use the fastest possible way to show some UI to the User. My root and main Navigation Control is a Drawer. The Drawer contains a list of “Destinations“, where a Destination is a specific area of the Application as

  • Home
  • Schedule
  • Speakers
  • Venue

01_drawer

Each Destination can be one of the Qt Quick Controls 2 Navigation Controls (http://doc.qt.io/qt-5/qtquickcontrols2-navigation.html) or Container Controls(http://doc.qt.io/qt-5/qtquickcontrols2-containers.html):

  • Pane
  • Page
  • StackView
  • SwipeView / Tab Bar

Inside the Drawer you can use a ListView to let the User select a Destination – take a look at Qt Quick Controls 2 Gallery Example. I‘m using a Repeater to create different types of Controls: Destinations, Divider, Header, …

To show the selected Destination best way is to use a StackView as your root UI Control and swap the content – so there‘s always only one Item at this root StackView.

02_destinations

To startup immediately don‘t create all the Drawer – Destinations ! This can easy be done with a little trick: define the Repeater without a data model.

        Repeater {
            id: destinations
            // Don‘t set the model here !
            // model: navigationModel
            Destination {
                id: destinationLoader
            }
        }

So nothing will be created now. To show something to the User create a lightweight Control as initialItem. I‘m using a BusyIndicator.

        // STACK VIEW INITIAL ITEM (BUSY INDICATOR)
        // immediately activated and pushed on stack as initialItem
        Loader {
            id: initialPlaceholder
            source: "pages/InitialItemPage.qml"
            active: true
            visible: false
            onLoaded: {
                // Show BUSY INDICATOR
                rootPane.initialItem = item
                item.init()
                // Now something is VISIBLE - do the other time-consuming stuff
                startupDelayedTimer.start()
            }
        }

The next trick is to start a Timer with a small delay to allow QML to show and animate the BusyIndicator. Then from Timer timeout execute all the initialization stuff and call some Q_INVOKABLE methods from your C++ Classes to load data from Cache and more.

As soon as this is done you can go on with creation of UI Controls. To trigger this set the Repeater Data Model and all the Destinations will be created and HomePage will become current Item on root StackView.

        Timer {
            id: startupDelayedTimer
            interval: 300
            repeat: false
            onTriggered: {
                initialPlaceholder.item.showInfo("Initialize Data ...")
                dataManager.init()
                settings = dataManager.settingsData()
                dataUtil.setSessionFavorites()
                // … and so on ...
                // inject model into Destinations Repeater
                destinations.model = navigationModel
                // show the Navigation Bars (Drawer and Favorites)
                initDone = true
                // now NavigationBars available
                // show first destination
                rootPane.activateDestination(firstActiveDestination)
            }
        }

 

Here we go: first „real“ Page is visible.

But wait: not all Destinations will really be created from the Repeater – this would take too much time and consume too much memory. All the Destinations are created dynamically using Loaders and I implemented some Activation Policies:

  • Immediate: The Control will be instantiated and remain. I‘m using this only for the first visible Page – the HomePage.
  • When-Selected: First time a User selects a Destination will create the Control and remain. This happens for all Destinations a User normaly will use while the App is running: Schedule, Speakers,…
  • While-Selected: Those Destinations are only created when needed and be destroyed if User changes the Destination. Candidates for this Policy: Help, Settings, About, …

Take a look at the code how all of this is implemented, attend my Session at Qt World Summit 2016 in San Francisco (http://www.qtworldsummit.com/speakers/ekkehard-gentz/) or meet me at #QtWS16.

Stay tuned – next article will cover the QObject* Data Model I‘m using, Caching and Data Binding.

The post Qt Conference Apps – out of the Developer Trenches – Part 1 appeared first on Qt Blog.

Qt Graphics with Multiple Displays on Embedded Linux

Creating devices with multiple screens is not new to Qt. Those using Qt for Embedded in the Qt 4 times may remember configuration steps like this. The story got significantly more complicated with Qt 5’s focus on hardware accelerated rendering, so now it is time to take a look at where we are today with the upcoming Qt 5.8.

Windowing System Options on Embedded

The most common ways to run Qt applications on an embedded board with accelerated graphics (typically EGL + OpenGL ES) are the following:

  • eglfs on top of fbdev or a proprietary compositor API or Kernel Modesetting + the Direct Rendering Manager
  • Wayland: Weston or a compositor implemented with the Qt Wayland Compositor framework + one or more Qt client applications
  • X11: Qt applications here run with the same xcb platform plugin that is used in a typical desktop Linux setup

We are now going to take a look at the status of eglfs because this is the most common option, and because some of the other approaches rely on it as well.

Eglfs Backends and Support Levels

eglfs has a number of backends for various devices and stacks. For each of these the level of support for multiple screens falls into one of the three following categories:

  • [1] Output management is available.
  • [2] Qt applications can choose at launch time which single screen to output to, but apart from this static setting no other configuration option is provided.
  • [3] No output-related configuration is provided.

Note that some of these, in particular [2], may require additional kernel configuration via a video argument or similar. This is out of Qt’s domain.

Now let’s look at the available backends and the level of multi-display support for each:

  • KMS/DRM with GBM buffers (Mesa (e.g. Intel) or modern PowerVR and some other systems) [1]
  • KMS/DRM with EGLDevice/EGLOutput/EGLStream (NVIDIA) [1]
  • Vivante fbdev (NXP i.MX6) [2]
  • Broadcom Dispmanx (Raspberry Pi) [2]
  • Mali fbdev (ODROID and others) [3]
  • (X11 fullscreen window – targeted mainly for testing and development) [3]

Unsurprisingly, it is the backends using the DRM framework that come out best. This is as expected, since there we have a proper connector, encoder and CRTC enumeration API, whereas others have to resort to vendor-specific solutions that are often a lot more limited.

We will now focus on the two DRM-based backends.

Short History of KMS/DRM in Qt

Qt 5.0 – 5.4

Qt 5 featured a kms platform plugin right from the beginning. This was fairly usable, but limited in features and was seen more as a proof of concept. Therefore, with the improvements in eglfs, it became clear that a more unified approach was necessary. Hence the introduction of the eglfs_kms backend for eglfs in Qt 5.5.

Qt 5.5

While originally developed for a PowerVR-based embedded system, the new backend proved immensely useful for all Linux systems running with Mesa, the open-source stack, in particular on Intel hardware. It also featured a plane-based mouse cursor, with basic support for multiple screens added soon afterwards.

Qt 5.6

With the rise of NVIDIA’s somewhat different approach to buffer management – see this presentation for an introduction – an additional backend had to be introduced. This is called eglfs_kms_egldevice and allows running on the automotive-oriented Jetson Pro, DRIVE CX and DRIVE PX systems.

The initial version of the plugin was standalone and independent from the existing DRM code. This led to certain deficiencies, most notably the lack of multi-display support.

Qt 5.7

Fortunately, these problems got addressed pretty soon. Qt 5.7 features proper code sharing between the backends, making most of the multi-display support and its JSON-based configuration system available to the EGLStream-based backend as well.

Meanwhile the GBM-based backend got a number of fixes, in particular related to the hardware mouse cursor and the virtual desktop.

Qt 5.8

The upcoming release features two important improvements: it closes the gaps between the GBM and EGLStream backends and introduces support for advanced configurability. The former covers mainly the handling of the virtual desktop and the default, non-plane-based OpenGL mouse cursor which was unable to “move” between screens in previous releases.

The documentation is already browsable at the doc snapshots page.

Besides the ability to specify the virtual desktop layout, the introduction of the touchDevice property is particularly important when building systems where one or more of the screens is made interactive via a touchscreen. Let’s take a quick look at this.

Touch Input

Let’s say you are creating digital instrument clusters with Qt, with multiple touch-enabled displays involved. Given that the touchscreens report absolute coordinates in their events, how can Qt tell which screen’s virtual geometry the event should be translated to? Well, on its own it cannot.

From Qt 5.8 it will be possible to help out the framework. By setting QT_LOGGING_RULES=qt.qpa.*=true we enable logging which lets us figure out the touchscreen’s device node.  We can then create a little JSON configuration file on the device:

{
    "device": "drm-nvdc",
    "outputs": [
      {
        "name": "HDMI1",
        "touchDevice": "/dev/input/event5",
      }
    ]
}

This will come handy in any case since configuration of screen resolution, virtual desktop layout, etc. all happens in the same file.

Now, when a Qt application is launched with the QT_QPA_EGLFS_KMS_CONFIG environment variable pointing to our file, Qt will know that the display connected to the first HDMI port has a touchscreen as well that shows up at /dev/input/event5. Hence any touch event from that device will get correctly associated with the screen in question.

Qt on the DRIVE CX

Let’s see something in action. In the following example we will use an NVIDIA DRIVE CX board, with two monitors connected via HDMI and DisplayPort. The software stack is the default Vibrante Linux image, with Qt 5.8 deployed on top. Qt applications run with the eglfs platform plugin and its eglfs_kms_egldevice backend.

drivecx_small

Our little test environment looks like this:

disp_both

This already looks impressive, and not just because we found such good use for the Windows 95, MFC, ActiveX and COM books hanging around in the office from previous decades. The two monitors on the sides are showing a Qt Quick application that apparently picks up both screens automatically and can drive both at the same time. Excellent.

The application we are using is available here. It follows the standard multi-display application model for embedded (eglfs): creating a dedicated QQuickWindow (or QQuickView) on each of the available screens. For an example of this, check the code in the github repository, or take a look at the documentation pages that also have example code snippets.

A closer look reveals our desktop configuration:

disp2

The gray MouseArea is used to test mouse and touch input handling. Hooking up a USB touch-enabled display immediately reveals the problems of pre-5.8 Qt versions: touching that area would only deliver events to it when the screen happened to be the first one. In Qt 5.8 this is can now be handled as described above.

disp1

It is important to understand the screen geometry concepts in QScreen. When the screens form a virtual desktop (which is the default for eglfs), the interpretation is the following:

  • geometry() – the screen’s position and size in the virtual desktop
  • availableGeometry() – without a windowing system this is the same as geometry()
  • virtualGeometry() – the geometry of the entire virtual desktop to which the screen belongs
  • availableVirtualGeometry() – same as virtualGeometry()
  • virtualSiblings() – the list of all screens belonging to the same virtual desktop

Configuration

How does the virtual desktop get formed? It may seem fairly random by default. In fact it simply follows the order DRM connectors are reported in. This is often not ideal. Fortunately, it is configurable starting with Qt 5.8. For instance, to ensure that the monitor on the first HDMI port gets a top-left position of (0, 0), we could add something like the following to the configuration file specified in QT_QPA_EGLFS_KMS_CONFIG:

{
  "device": "drm-nvdc",
  "outputs": [
    {
      "name": "HDMI1",
      "virtualIndex": 0
    },
    {
      "name": "DP1",
      "virtualIndex": 1
    }
  ]
}

If we wanted to create a vertical layout instead of horizontal (think an instrument cluster demo with three or more screens stacked under each other), we could have added:

{
  "device": "drm-nvdc",
  "virtualDesktopLayout": "vertical",
  ...
}

More complex layouts, for example a T-shaped setup with 4 screens, are also possible via the virtualPos property:

{
  ...
  "outputs": [
    { "name": "HDMI1", "virtualIndex": 0 },
    { "name": "HDMI2", "virtualIndex": 1 },
    { "name": "DP1", "virtualIndex": 2 },
    { "name": "DP2", "virtualPos": "1920, 1080" }
  ]
}

Here the fourth screen’s virtual position is specified explicitly.

In addition to virtualIndex and virtualPos, the other commonly used properties are mode, physicalWidth and physicalHeight. mode sets the desired mode for the screen and is typically a resolution, e.g. “1920×1080”, but can also be set to “off”, “current”, or “preferred” (which is the default).

For example:

{
  "device": "drm-nvdc",
  "outputs": [
    {
      "name": "HDMI1",
      "mode": "1024x768"
    },
    {
      "name": "DP1",
      "mode": "off"
    }
  ]
}

The physical sizes of the displays become quite important when working with text and components from Qt Quick Controls. This is because these base size calculations on the logical DPI that is in turn based on the physical width and height. In desktop environments queries for these sizes usually work just fine, so no further actions are needed. On embedded however, it has often been necessary to provide the sizes in millimeters via the environment variables QT_QPA_EGLFS_PHYSICAL_WIDTH and QT_QPA_EGLFS_PHYSICAL_HEIGHT. This is not suitable in a multi-display environment, and therefore Qt 5.8 introduces an alternative: the physicalWidth and physicalHeight properties (values are in millimeters) in the JSON configuration file. As witnessed in the second screenshot above, the physical sizes did not get reported correctly in our demo setup. This can be corrected, as it was done for the monitor in the first screenshot, by doing something like:

{
  "device": "drm-nvdc",
  "outputs": [
    {
      "name": "HDMI1",
      "physicalWidth": 531,
      "physicalHeight": 298
    },
    ...
  ]
}

As always, enabling logging can be a tremendous help for troubleshooting. There are a number of logging categories for eglfs, its backends and input, so the easiest is often to enable everything under qt.qpa by doing export QT_LOGGING_RULES=qt.qpa.*=true before starting a Qt application.

What About Wayland?

What about systems using multiple GUI processes and compositing them via a Qt-based Wayland compositor? Given that the compositor application still needs a platform plugin to run with, and that is typically eglfs, everything described above applies to most Wayland-based systems as well.

Once the displays are configured correctly, the compositor can create multiple QQuickWindow instances (QML scenes) targeting each of the connected screens. These can then be assigned to the corresponding WaylandOutput items. Check the multi output example for a simple compositor with multiple outputs.

The rest, meaning how the client applications’ windows are placed, perhaps using the scenes on the different displays as one big virtual scene, moving client “windows” between screens, etc., are all in QtWayland’s domain.

What’s Missing and Future Plans

The QML side of screen management could benefit from some minor improvements: unlike C++, where QScreen, QWindow and QWindow::setScreen() are first class citizens, Qt Quick has currently no simple way to associate a Window with a QScreen, mainly because QScreen instances are only partially exposed to the QML world. While this is not fatal and can be worked around with some C++ code, as usual, the story here will have to be enhanced a bit.

Another missing feature is the ability to connect and disconnect screens at runtime. Currently such hotplugging is not supported by any of the backends. It is worth noting that with embedded systems the urgency is probably a lot lower than with ordinary desktop PCs or laptops, since the need to change screens in such a manner is less common. Nevertheless this is something that is on the roadmap for future releases.

That’s it for now. As we know, more screens are better than one, so why not just let Qt power them all?

The post Qt Graphics with Multiple Displays on Embedded Linux appeared first on Qt Blog.

Your data, your code, your cloud…your choice!

The Internet of Things, can mean, well…so many things. So can platform independence. For many people, a cloud platform, often provided as a service, is an essential part of an IoT offering. For others, flexibility is more important – the flexibility to run your solution on any cloud – or the flexibility to run it internally on your own network on your own servers, because you’re paranoid and believe your competitors are watching you (and you know they are), or even worse, maybe someone is going to try to hack your solution, bring it down and put a serious dent in your up-time track record. Regardless, when developing an IoT solution – the choice should be yours and you should be in charge of your own data.

Qt Top 5 Considerations IoT infographicI was previously involved in the development an IoT strategy for a company operating within the industrial automation space, where we initiated the same IoT project with a third party platform as a service provider (PaaS) – to be part of our offering to our end customers – twice. Yes, twice! Twice, because we were working with the wrong providers and because we came to the same conclusion both times. Twice, because the providers were offering their solution on their cloud and they wanted to rent it to us so we could re-rent it to our end customers.  It didn’t sound right and they would never allow us to move the solution to other cloud platforms or host the solution in any other format. And we could forget about making drastic changes to the back-end system and if we were to make any minor change we had to use their consultants ($$$). In other words, it would have never been our solution – it would have been theirs and they would own the data and eventually most likely reap all the revenue potential once we were locked in. We wanted it to be our solution and our end customers wanted it to be theirs. Flexibility, ownership, cross-platform and cash money being the key words here.

We even tried to pitch the solution to our end customers, but they weren’t buying our story. When we reported the customer feedback to the IoT/PaaS vendor, they replied that our end customers “were being conservative” (no, they weren’t – they were just being smart). They wanted flexibility and control over their own solution and their own data. They valued security. They didn’t want to have some sort of closed software agent sending data from their devices where they couldn’t see what was being sent and to where it was being sent. One of our key customers, who we pitched the solution to, even went to the measure of making us sign a paper stating that no such “IoT software” existed on their equipment and that we would never, ever, EVER connect them to any cloud, which wasn’t their own choice and on which they could not see what data was being sent and where it was being sent to. Period! So we stopped the project. Twice. With the software we created with Qt we didn’t have this problem and you won’t either. With Qt it will be your solution, on your platform of choice and we are not forcing you onto any cloud. It is not that we don’t like the cloud. We do. We just think the choice of how you want to host your IoT solution should be yours and we have developed tools to make that simpler for you. Qt is also open, so you know what is going on and can make sure your data remains yours and you know where it is sent. There is also a bunch of other benefits you can achieve by using Qt in your IoT development. If you want to learn more about the software requirements and other important stuff you should be considering before choosing an IoT platform, read our whitepaper: “Building the Internet of Things and How Qt Can Help”. 

The post Your data, your code, your cloud…your choice! appeared first on Qt Blog.

Internet of Things: Why Tools Matter?

With the Internet of Things (IoT) transformation, it’s obvious that the amount of connected devices in the world is increasing rapidly. Everywhere around our daily lives we all use more and more of them. In addition to being connected, more devices get equipped with a touch screen and a graphical user interface. We have all seen this around us and many Qt users are also deeply involved in creating software for these devices. To bring in some numbers, the Gartner group has estimated that the amount of connected devices will grow to a whopping 20.7 billion by 2020 (and some predict even higher growth, up to 30 billion devices).

Not only is the number of devices growing, but the complexity and amount of software is also increasing rapidly. For example, today’s passenger car can have over 100M lines of code, and this is expected to triple in the future as the functionality of automotive software increases. Cars are on the high side of complexity, but even the simplest connected devices need a lot of software to be able to handle the requirements for connectivity, security and to match the growing usability expectations of consumers.

Here is how the estimated growth of connected devices looks in a line graph:

iotdevices

What is inside these devices? What kind of software drives the connected devices? What kind of skills are needed to build these? It is estimated that 95% of today’s embedded systems are created with C/C++, and that this is not significantly changing in the foreseeable future. Then, on the other hand, according to a study there were 4.4M C++ developers and 1,9M C developers in 2015 in the World. An older study by IDC from 2001, shows that the number of C++ developers was estimated to be 3M back then. This means the number of C++ developers has been growing steadily around 3% per year and is expected to continue with a similar trend – or at least within a similar range.

So, a visualization of C++ developer growth provides the following graph:

cppdevelopers
The estimated number of devices, most of which will be done with C and C++, is already growing with much faster pace than the amount of C++ developers and the growth is expected to get even higher. Due to the increased complexity of functionality, the amount of software needed in the devices is also growing. Although some of the new devices will be very simple in functionality, on average the devices get more and more complex to meet consumers’ requirements.

Now, comparing these two trends together gives us an interesting paradox: How can the few millions of C++ developers match the requirement to build the dozens of billions of connected devices in the future?

Putting these two graphs together, we can clearly visualize the paradox (and a possible solution):

developes_vs_iotdevices

 

So how does this add up? Do we expect a 2020 C++ developer to write 20 times more code than a decade ago? That does not work. Even if all the C++ developers would focus into embedded, with no one creating and maintaining software for desktop and mobile applications, there still may not be enough developers. C++ developers can’t be easily trained from other professionals – programming is a skill that takes years to learn and not everyone can master.

So, Something needs to be done to facilitate two things: Enabling the C++ developers to be more productive and also helping the non-C++ developers to create the devices.

Therefore, the approach for creating embedded software needs to be adapted to the new situation. The only way to cope with the growth is to have good tools for embedded device creation and to increase the reuse of software. It is no longer viable to re-invent the wheel for each product – the scarce programming resources have to be targeted into differentiating functionality. Organizations will have to prioritize and focus into where they add value the most – anything that can be reused should not be created inhouse. Using tools and frameworks like Qt is the only viable approach to create the envisioned devices. The old Qt tagline: “Code less. Create more. Deploy Everywhere” is more relevant today than it has ever been. Qt has a solid track record from embedded, desktop and mobile development, making the creation of applications easy in any platform and also across multiple platforms.

It is likely that even reuse of software assets is not enough. It is also necessary to increase productivity of the C++ developers and to extend the personnel creating the software beyond the ones who master C++. Using the widely renowned and well-documented Qt API functionality and excellent development tools, C++ developers are more productive than before. Qt also provides an easy-to-use declarative QML language and visual design tools for user interface creation, growing the amount of people who can create software for embedded beyond the C++ developers. There are already over million developers familiar with Qt, and new developers across the world are taking it into use every day.

With the QML language, visual UI design tools and functionality for embedded devices does not mandate C++ skills for every developer in the team. It will still be necessary to have core C/C++ developers when making embedded devices, but others can help as well. Using Qt allows both non-C++ developers to create some of the needed functionality and the C++ developers to be more productive.

To increase developer productivity and to extend the developer base, Qt offers otherwise unseen ease of embedded development. Qt provides many of the common development boards supported out of the box, one click deployment to target device, built-in device emulator, on target debugger, performance analyzer, visual UI designer and many more tools in the integrated development environment. With the integrated tools and extensive API functionality, developing with Qt is unlike traditional embedded development. Qt makes embedded development almost as easy as creation of desktop or mobile applications.

The future is written with Qt.

To learn more about the latest developments of Qt, join us at the Qt World Summit October 18-20th 2016 in San Francisco, USA.

We’re also hosting an online panel discussion with industry experts around IoT and software in general September 27th. Register today for the webinar for an interesting fireside chat!

The post Internet of Things: Why Tools Matter? appeared first on Qt Blog.

Qt World Summit 2016 San Francisco Conference App: Behind The Scenes

Qt World Summit 2016

Meet me at this years Qt World Summit 2016 in San Francisco

qtws16_sfo

I’ll speak about development of upcoming Qt World Summit Conference App running on

  • BlackBerry 10 (Qt 4.8, Cascades)
  • Qt 5.7 (Qt Quick Controls 2)
    • Android
    • iOS
    • Windows 10

My Session

See how easy it is to develop cross-platform mobile Apps using Qt 5.7+ and new Qt QuickControls 2

qtws16_session_ekke

BlackBerry 10 Cascades Development ?

Already have BlackBerry 10 Apps (Cascades) ? Learn how to save your investment: most C++ Code für Business Logic, REST / Web Services, Persistence (SQLite, JSON) can be re-used and the app architecture is similar using Qt SIGNALS – SLOTS concept.

cu in San Francisco


Filed under: BB10, C++, Cascades, mobile, Qt

QtCon wrap up

QtCon16_Logo

First, a huge Thank You to everyone who was at QtCon!

We had an incredible time in Berlin. First the training day by KDAB and then three conference days packed full with topics ranging from how to set up an open source organisation to fine tuning Qt graphics.

Second. a shout out to the communities that we had the pleasure to work with to create QtCon, FSFE, KDE and VideoLAN, and of course to our partners KDAB, you guys rock!

Last but definitely not least, Thank You obviously to all the volunteers from the different communities!

The magic of QtCon

When we originally got together to plan QtCon, we envisioned it as a meeting of communities, one event where everyone can come. This is something we achieved. At the end of the event, every one of the community representatives made the same comment; meeting new and interesting people was the best part. Chatting about new things over coffee or lunch, walking from a deep dive technical session to the social impact of open source was something that only happens when we have different communities mix. By the end of the event, I believe everyone headed for home with a feeling that getting together is something we need to do more often.

The Keynotes were amazing! Please take the time to hear what Raul, Leslie and Julia had to say in their talks. The take-home message for me was that software has changed the world and we need to understand the change on every level. For Qt this means that we need to be sensitive to these changes and understand the impact we have in society.

The Qt Specific topics covered everything happening in and around Qt – from the technical details to overall community issues.

The most awaited Qt session was naturally the talk on the status and future of Qt by Chief Maintainer Lars Knoll. The talk outlined the bigger trends in Qt, and where biggest development pushes are expected to be. Lars also talked about how he sees the next releases of Qt going forward. These topics continued in corridor discussions and during the evening party on Friday.IMG_20160902_161511

My personal favourite talk was an ‘unconference session’ that was reserved on location about Qt QUIPs, a way to arrange and manage the information related to the Qt project. I’m looking forward to seeing QUIPs in action, but it will naturally take a while for the developers to get all the bits and pieces together.

The Qt session videos will be available soon on the QtStudios YouTube channel. However if you are really hungry to get at the videos, in the QtCon schedule the talks that were in the bigger rooms already have the links added to the talk descriptions. For example The Qt Project Status talk video is here. The incredible speed at which the videos got online is entirely due to the hard and efficient work of the CCC Video Operations Center, hats off to them!

In conclusion, I met old friend, new and interesting people, heard cool talks and had a good time. I’m sure the other attendees did too.

See you in coming events!

P.S. Qt World Summit is coming up soon 😉

The post QtCon wrap up appeared first on Qt Blog.

Squish tip of the week: Automating Multiple Applications with Multiple Squish Installations or Editions

Automating Multiple Applications with Multiple Squish Installations or Editions

Did you know that it is possible to use multiple Squish editions in a single test script?

The following example describes the setup and workflow for such scenario utilizing Squish for Qt and Squish for Web.

  1. Install Squish for Qt.
  2. Install Squish for Web.
  3. Create a Squish for Qt test suite with the Squish for Qt IDE.
  4. Create a Squish for Web test suite with the Squish for Web IDE.

  5. Share the objects.map file across both test suites (Learn how to share an Object Map).
  6. Decide which of the two test suites should be the main test suite. In our example, we choose the Squish for Qt test suite.
  7. Continue with Recording
  8. Continue with Replay

Note: The information above describes the setup for Squish for Qt and Squish for Web but the instructions are not limited to these Squish editions.

Related topics

Creating Certified Medical Devices with Qt

by Matthias Hölzer-Klüpfel [Medical Devices Consultant] (Qt Blog)

Many modern medical devices provide a graphical interface to the user. In dialysis machines, for example, touch screen interfaces to set up the treatment parameters and to monitor the treatment progress are commonplace. Qt is a viable technical solution to implement those interfaces, so it is used in quite a number of medical devices.

When designing and implementing a medical device, however, you have to do more than to find a good technical solution. You have to analyze the risks associated with your device, and you have to make sure that your system design and development is appropriate for that risk. That is not an easy task, but there are laws, regulations and standards that provide guidance on the required development process for medical device software. Important guidance documents are:

If you develop software for a medical device that will be marketed in the EU and the US, you will have to follow those guidelines. They are mainly concerned with the process of designing, implementing, verifying and testing your own device software. But they also influence the use of third-party software like Qt in your device. If your third-party software, or SOUP (“Software of Unknown Provenance” in terms of IEC 62304), may contribute to a hazardous situation, i.e. might lead to harm to the patient, you have to minimize that contribution and make sure that the chosen third-party software is appropriate.

If we continue the example of a dialysis machine, one of the functions of the therapy – besides cleaning the blood of the patient – is to remove excess water from the body of the patient. Depending on the physical condition of the patient, up to four liters of water may be removed in a typical therapy session. But that is just the maximum amount, a patient might need less water removal, or none at all. The problem is that you have to enter the right amount of water to remove via the user interface, and it is critical that you do not remove more than that amount, as removing too much water might lead to a circulatory collapse and might severely harm the patient. Input of safety-critical values is a typical critical user interface function in medical devices, as well as the output of safety-critical values, e.g. the oxygen saturation of a patient’s blood.

Another critical user interface function that is common in medical devices is alarms. Imagine that during a dialysis therapy, the device detects that there is an air bubble in the blood line (which, when infused back into the patient, might lead to embolism). What the device probably should do is to stop the therapy, sound an alarm sound and display a visual warning to the operator of the device to take appropriate actions.

Obviously, if one of those functions fail to work correctly, the patient may be harmed. Now a manufacturer might ask some basic questions:

  • 1. What can we do to prevent the harm to the patient?
  • 2. May we use Qt to implement those safety-critical user interface functions?
  • 3. Do we need a validated toolkit to build a safety-critical user interface?

Let’s start with the first question. It can only be answered by performing a detailed risk analysis. The standard ISO 14971 provides guidance on how to do this. In the example of the air-in-line alarm, we start with the hazard (the air bubble), determine the potential harm (which – in the worst case – is the death of the patient) and try to estimate the probability of the harm (for the sake of the example, let’s assume an air bubble once per 24 hours of treatment). If we combine those assumptions and estimates, we will find that the risk (the combination of the severity of the harm and the probability of its occurrence) is not acceptable. Thus we need to do something to reduce the risk. We might decide to add an air-bubble-detector into the system, and to add an alarm function to the user interface. When a bubble is detected, the system stops the therapy and raises the alarm to request the user to take appropriate action.

This is a reasonable first step, but not the end of our analysis. What happens if the alarm is not displayed? This could be caused by a problem with the display driver, or a failing LCD backlight, or by an unexpected failure of the GUI toolkit. A medical device needs to be safe even in the presence of a single fault in the system. So having an alarm system that might fail because of a single reason is not acceptable. Typical devices would therefore add another redundant and diverse alarm mechanism, e.g. a flashing LED that can be activated even when the GUI is not working properly. With this second channel, the alarm can be indicated even with a failure in the GUI or a failure in the LED mechanism. And this is generally considered to be safe. Of course, there is a cost – additional hardware.

There are other examples of diversity in graphical user interfaces: If we display a critical numerical value, we might be concerned that loading the correct font fails. Remember, we have to assume a first fault like a damaged font file. We can add some redundancy and display a bar graph visualizing the numerical value in addition to the number. Even if the numbers are not displayed correctly, the bar graph will present the information to the user. Sometimes you will see an old-fashioned LCD screen next to a touch screen on a medical device. This is a secure (if not pretty) way to add redundancy to the display system. The important point is that the resulting risk, even with a failure in the GUI, has to be acceptable.

Now we can tackle the second question: May we use Qt for the GUI of a safety critical medical device? Principally, the choice of technologies is up to the system designer. None of the standards will tell you to choose one toolkit over the other. The manufacturer of the medical device needs to make sure that it is safe, according to what has already been mentioned. But in addition to that, the IEC 62304 and the OTS require that we make a conscious decision about the choice third-party software or SOUP. In addition to the mentioned risk analysis, we need to make sure that:

  • The toolkit provides the functionality and performance that we depend on
  • The device provides the support necessary to operate the toolkit within its specification
  • The toolkit performs as required for our system

So a device manufacturer will have to provide evidence of these claims, i.e. will have to document the requirements to Qt, analyze and document the requirements imposed by Qt on the system and you will have to perform some degree of testing in the system to prove the requirements are met. And the manufacturer needs to set up a monitoring process to regularly check the bug list of the third-party software component and to assess if any new bugs impose additional risks to the patients. All of these points might be subject to an audit by a notified body or the FDA.

Very often the following question will be asked: Where can we buy a GUI toolkit that has already been validated to be suitable for use in safety-critical medical devices? Unfortunately, there is no such thing as a pre-validation for medical devices. As the starting point of third-party component validation is focused on the risk analysis, only the manufacturer of the device can do the qualification, because only the manufacturer can identify the risks. Therefore, IEC 62304 and the FDA regulations do not define a certification process for third-party software (SOUP). The best way a vendor can support a medical device manufacturer therefore is by providing good documentation of its development process and proof of internal testing, which allows the manufacturer to asses if it is appropriate for the planned application.

If you use a commercial license of Qt, contact The Qt Company and request a description of the QA practices and test report of the Qt version you intent to use. These documents are readily available and support your qualification effort.

To summarize, if you plan to use Qt for safety-critical functions in a medical device, make sure to:

  • 1. Identify all risks that might be caused by failures of the user interface
  • 2. Try to mitigate those risks by means outside the user interface, e.g. by redundant inputs and outputs
  • 3. Build redundancy into the user-interface itself to protect against single-fault failures
  • 4. Carefully select the software components you use to implement the user interface
  • 5. Document the rationale for your decision that Qt is appropriate for your device so it can be reviewed by external auditors

If you follow those steps, you will be able to design your device with a modern user interface, and still meet all the safety requirements.

About the Blog Post Author:

Matthias Hölzer-Klüpfel is an independent consultant, trainer and contractor concerned with development processes and project management for medical device software. He co-founded the association “International Certified Professional for Medical Software Board e.V.” which provides the foundation for a certified education program for medical device software development.

You can reach Matthias via matthias@hoelzer-kluepfel.de if you have any further questions.

Earlier Blog Posts about Functional Safety with Qt:

If you are interested in hearing more about Functional Safety, there is a talk at Qt World Summit by Tuukka Turunen about ‘Creating Functional Safety Certified Systems with Qt’.

The post Creating Certified Medical Devices with Qt appeared first on Qt Blog.

Qt 5.8 Alpha released

I’m happy to let you know that we have now reached our first milestone towards the release of Qt 5.8. The Alpha version of Qt 5.8 is now ready, and can be downloaded from download.qt.io or your Qt Account. As a new minor release, Qt 5.8 comes with a lot of new features as well as many bug fixes and improvements. We’ll go through all the new features in more detail as we get closer to the release. For now, let me just mention some of the biggest changes.

New graphics architecture

With Qt 5.8, the graphics architecture for Qt Quick has undergone a larger rewrite. The goal was to remove the tight dependency of Qt Quick onto OpenGL that we have had since Qt 5.0, and make the architecture more agnostic with regards to the graphics API that is being used. The new infrastructure has been used to create a vastly improved Software rendering backend for Qt Quick, and a backend based on DirectX 12.

QML caching

The QML engine has also seen some major improvements with a new caching infrastructure, that can cache the QML files in a precompiled binary form. This infrastructure does help to significantly speed up loading of QML applications once the binary cache has been created. It also helps reduce memory consumption. Ahead of time compilation of Qt Quick continues to be supported through the commercial Qt Quick Compiler.

Qt Lite Project and configurability

Even though Qt is split up into many modules, it is a large framework with many features. Many of our customers are using only parts of them, and have been asking for an option to create tailored builds of Qt for their use case. This is especially important for embedded devices, where both RAM and Flash storage are often limited.

To accommodate this, we have over the last 6 months done significant work on our build infrastructure to give our users much more fine grained control over the way how Qt is being built. This is what we called the Qt Lite Project. The basic infrastructure for this is now in place with the 5.8 Alpha, but we will be doing some more work on it while moving towards the Beta release.

With Qt 5.8, we will add a new tool to Qt for Device Creation, that will make it easier to tailor your Qt build and remove all the pieces of functionality that you are not using in your embedded project. From initial measurements, we expect that you will be able to reduce the size of a statically linked Qt Quick application by up to 70% compared to Qt 5.6.

New modules

The Wayland Compositor, SCXML and Serial Bus modules have now graduated from Technology Preview to being fully supported. In addition, we added Qt Speech and Qt Network Authentication (featuring OAuth support) as new Technology Previews.

Timeline

With the Qt 5.8 Alpha being released, we are now focusing fully towards finalizing a couple of remaining items, and plan to have the beta ready for you towards the beginning of October and Qt 5.8.0 final by end of November.

If you would like to hear more about all the cool new things coming with Qt 5.8, we will have in-depth talks about all of them at the Qt World Summit in San Francisco.

I hope you’ll enjoy the Qt 5.8 Alpha. Please download it from download.qt.io or your Qt Account, and don’t forget to give us feedback by writing to the mailing lists or reporting bugs.

The post Qt 5.8 Alpha released appeared first on Qt Blog.

In 45 Minutes: from Scratch to App for Android, iOS, Windows 10

As you know last months I evaluated Qt 5.7 and new Qt Quick Controls 2 for x-platform mobile App development.

Qt Con Conference App

You can see a first App live at Google Play, Apple App Store or Amazon App Store: Search for ‘QtCon’:

qtcon_google_play

The Application is available Open Source at Github.

Blog with some more details: here.

Next Conference App for Qt World Summit in San Francisco will also be available from Windows App Store (Windows 10) and BlackBerry World (BlackBerry 10)

Talk at Code Talks in Hamburg

I will demonstrate the power of Qt 5.7 / Qt Quick Controls at Code Talks in Hamburg:

in 45 Minutes from Scratch to App

ekke_codetalks

BlackBerry 10

Perhaps you’re asking “And what about your BlackBerry 10 Development, ekke ?

Nothing has changed – I’m still developing business Apps for BlackBerry 10 – and the good thing: I can re-use most of the C++ / Qt Code for Android / iOS / W10🙂 Also App Architecture and events (Qt SIGNALS – SLOTS concept) are similar.


Filed under: BB10, C++, Cascades, mobile, Qt

Cutelyst 0.13.0 released!

cutelyst-logoCutelyst the Qt web framework just got a new release, 0.13.0.

A new release was needed now that we have this nice new logo. 

Special thanks to Alessandro Longo (Alex L.) for crafting this cute logo, and a cool favicon for Cutelyst web site.

But this release ain't only about the logo, it's full of cool things: 

When I started Cutelyst a simple developer Engine (read HTTP engine) was created, it was very slow and mostly an ugly hackery but helped work on the APIs that matter, I then took a look at uWSGI due some friend saying it was awesome and it was great to be able to deal with many protocols without the hassled of writing parsers for them.

Fast forwarding to 0.12.0 release and I started to feel that I was reaching a limit on Cutelyst optimizations and uWSGI was holding us back, and it wasn't only about performance,  memory usage (scalability) was too high for something that should be rather small, it's written in C after all. 

It also has a fixed number of requests it can take, if you start it with 5 threads or process it's 5 blocking clients that can be processed at the same time, if you use the async option you then have a fixed number of clients per process, 5 process * 5 async clients = 25 clients at the same time, but this 5 async clients are always pre-allocated which means that each new process will also be bigger right from launch.

Think now about websockets, how can one deal with 5000 simultaneous clients? 50 process with async = 100? Performance on async mode was also slower due complexity to deal with them.

So before getting into writing an alternative to uWSGI in Cutelyst I did a simple experiment, asked uWSGI to load a Cutelyst app and fork 1000 times and wrote a simple QCoreApplication that would do the same, uWSGI used > 1GB of RAM and took around 10s to start, while the Qt app used < 300MB of RAM and around 3s. So ~700MB of RAM is a lot of RAM and that was enough to get me started.

Cutelyst-wsgi, is born, and granted the command line arguments are very similar to uWSGI and I also followed the same separation between socket and protocol handling, of course in C++ things are more reusable, so our Protocol class has a HTTP subclass and in future will have FastCGI and uWSGI ones too.

Did I say uWSGI before 2.1 doesn't support keep-alive? And that 2.1 is not released nor someone knows when it will? Cutelyst-wsig supports keep-alive, http pipelining, is complete async and yes, performs a little better. If you put NGINX in front of uWSGI you can get keep alive support, but guess what? the uwsgi protocol closes the connection between the front server so it's quite hard to get very high speeds. Preliminary results of TechEmpower Benchmarks #13 showed Cutelyst hitting these limits as others frameworks were using keep-alive properly.

Thanks to this new Engine the Engine API got several improvements and is quite stable now. Besides it a few other important changes were made as well:

  • Change internals to take advantage of NRVO (named return value optimization)
  • Improved speed of Context::uriFor() making Cutelyst now require Qt 5.6 due a behavior change in QUrl
  • Improved speed and memory usage of Url query parser 1s faster in 1m iterations, using QByteArray::split() is very convenient but it allocates more memory and a QList for the results, using ::indexOf() and manually getting the parts is both faster and more memory efficient but yes, this is the optimization we do in Cutelyst::Core and that makes a difference, in application code the extra complexity might not worth it.
  • C++ for ranged loops, all our Q_FOREACH & friends where replaced with for ranged loops
  • Use of new reverse and equal_range iterators
  • Use QHash for storing headers, this was done after several benchmarks that showed QHash was faster for all common cases, namely if it keept the values() in order like QMap it would be used in other places as well
  • Replaced most QList with QVector, and internally std::vector
  • Multipart/form-data got faster, it doesn't seek() anymore but requires a not sequential QIODevice as each Upload object point to parts of the body device.
  • Add a few more unit tests.

Thanks to the above the core library size is also a bit smaller, ~640KB on x64.

I was planning to do a 1.0 after 0.13 but with this new engine I think it's better to have a 0.14 version, and make sure no more changes in Core will be needed for additional protocols. 

Download here enjoy!

New Forum theme and security notice

Hello,

Last week we updated the Qt Forum to the latest version of NodeBB.

We had been planning the upgrade for a while, but had to do the upgrade on a quick notice, as a bug that leaked user emails was found in the forum. Thanks to Justin Clift for pointing out the issue to us!

This means that it was possible for someone to find out user emails from the forum. For those users who have their email as public, this is not a issue, but some of you want to keep your email to yourself. The bug meant that these email addresses could also be found.

No other data was available through the bug, and as we are using a central sign in service, no account information could leak from the forum.

So if you have gotten more email spam than normally this might be one cause.

We are sorry for the leak, but in our defence, we did not know of it, and patched the system in under a day of becoming aware of the issue.

But on to the upgrade itself.

With the upgrade we changed to the new default theme used by NodeBB. It looks quite different from the old theme, and has already gotten some for and against feedback. I personally am getting used to the look and feel, and after the initial shock, I like it. That’s a personal opinion, your mileage may vary, and please do tell us in the comments.

Due to the rushed upgrade some small things still need tweaking, the colours are a bit off from the Qt green, that will be fixed as soon as I find the time for it.

The reasoning for updating the theme, is that we can now follow the NodeBB upgrades faster, as we do not need to customise the theme as much as before. This will bring the improvement faster to you.

As an example new feature we now have chat rooms instead of one-to-one chats on the forum. To create a room, you can start a chat, and from the chat window settings add other users. At least for the Forum regulars this is quite an improvement.

So what do you think of the new Qt Forum look? Please tell us in the comments or drop by the forum to share your opinion.

Updated to credit Justin for finding the leak, thanks again!

The post New Forum theme and security notice appeared first on Qt Blog.

Fast-Booting Qt Devices, Part 4: Hardware Matters

Welcome back!

A while ago, I posted three parts of Fast-Booting Qt Devices blog post series where we showcased 1,5 second boot-time, optimized the Qt application and finally showed you how we optimized the entire Linux stack. Today, we will show you that hardware selection and hardware architecture in general can have a big impact on the actual startup time even when using the same CPU. To demonstrate this, we have two boards with NXP i.MX6 Quadcore CPU. One is a board geared towards software development, and the other is a system-on-module board aimed to be used in the production as well.

So, let’s a have a small Battle of the Boards! :)

On the left side, we have the NXP SABRE  i.MX 6 Quad Development Board:

  • NXP i.MX 6 Quadcore processor, running at 1GHz
  • 1GB DDR3 RAM
  • 8GB eMMC

On the right, we have Toradex Apalis i.MX 6 Computer on Module:

  • NXP i.MX 6 Quad core processor, running at 1GHz
  • 1GB DDR3 RAM
  • 4GB eMMC

Both boards are running exactly the same Qt Cluster demo, kernel configurations and u-boot.

Toradex Computer on Module is a clear winner with 19% (294 ms) faster startup time. Our earlier fast-boot example with the NXP SABRE resulted in a very good 1560 ms from power up to display of the first full screen Qt Quick frame. Now, with the Toradex board, we got an even faster 1266 ms.

Where does the difference come from?

  • Powering up of the board is faster with Toradex module
  • Kernel is able to access eMMC earlier resulting into a faster kernel startup time

So, when designing your embedded devices, remember that hardware selection does matter too. If you need to reach blazing fast startup time, it certainly helps to have fast memory and memory bus, well optimized bootloader and kernel, as well as of course a powerful chip that can quickly crunch through the libraries you need to load. The rest is then up to your software–even with the optimized hardware you can ruin your boot-up time with a sloppy software design. For those tips, check out the earlier posts in this series.

If you are interested in hearing more, I will be talking about fast-boot of Qt based devices at the Qt World Summit in San Francisco, October 18-20. We are looking forwards to seeing you there, and hearing your feedback!

 

The post Fast-Booting Qt Devices, Part 4: Hardware Matters appeared first on Qt Blog.

Goodbye, Q_FOREACH

Q_FOREACH (or the alternative form, foreach) will be deprecated soon, probably in Qt 5.9. Starting with Qt 5.7, you can use the QT_NO_FOREACH define to make sure that your code does not depend on Q_FOREACH.

You may have wondered what all the fuss is about. Why is there a continuous stream of commits going to into Qt replacing Q_FOREACH with C++11 ranged for-loops? And why does it take so many commits and several Qt versions to port away from Q_FOREACH? Can’t we just globally search and replace Q_FOREACH (a, b) with for (a : b) and be done with it?

Read on for the answers.

What is Q_FOREACH?

Q_FOREACH is a macro, added for Qt 4, that allows to conveniently iterate over a Qt container:

Q_FOREACH(int i, container)
    doSomethingWith(i);
Q_FOREACH(const QString &s : functionReturningQStringList())
    doSomethingWith(s);

It basically works by copying the second argument into a variable called QForeachContainer, and then iterating over it. I’m only mentioning this for two reasons: First, you will start seeing that internal QForeachContainer at some point in deprecation warnings (probably starting with Qt 5.9), and, second, yes, you heard correctly, it copies the container.

This copying has two effects: First, since the copy taken is essentially const, no detaching happens when iterating, unlike if you use the C++98 or C++11 alternatives:

for (QStringList::const_iterator it = container.begin(), end = container.end(); it != end; ++it)
   doSomethingWith(*it);
for (const auto &s : container)
   doSomethingWith((*it);

In both cases the (explicit or implicit) calls to begin() and end() cause a non-const container to detach from shared data, ie. to perform a deep-copy to gain a unique copy of the data.

This problem is well-known and there are tools to detect this situation (e.g. Clazy), so I won’t spend more time discussing it. Suffice to say that Q_FOREACH never causes detaches.

Except when it does.

Q_FOREACH is Convenient^WEvil

The second effect of Q_FOREACH taking a copy of the container is that the loop body can freely modify the original container. Here’s a very, very poor implementation that takes advantage of this:

Q_FOREACH(const QString &lang, languages)
    languages += getSynonymsFor(lang);

Of course, since Q_FOREACH took a copy, once you perform the first loop iteration, languages will detach from that copy in Q_FOREACH, but this kind of code is safe when using Q_FOREACH, unlike when you use C++11 ranged for-loops:

for (const auto &lang : languages)
    languages += getSynonymsFor(lang); // undefined behaviour if
                                       // languages.size() + getSynonymsFor(lang).size() > languages.capacity()

So, as we saw, Q_FOREACH is convenient—if you write code.

Things look a bit different if you try to understand code that uses Q_FOREACH, because you often can’t tell whether the copy that Q_FOREACH unconditionally takes is actually needed in any particular case, or not. A loop that plain falls apart if the container is modified while iterating is much easier to reason about than a Q_FOREACH loop.

And this brings us to porting away from Q_FOREACH.

Towards a Q_FOREACH-Free World

Things would be pretty simple if you could just globally search and replace Q_FOREACH (a, b) with for (a : b) and be done with it. But alas, it ain’t so easy…

We now know that the body of a Q_FOREACH loop is free to modify the container it’s iterating over, and don’t even for a minute think that all cases are so easy to recognize as the example with the languages above. The modification of the container may be several functions deep in the call stack originating from the loop body.

So, the first question you need to ask yourself when porting a Q_FOREACH loop is:

Does the loop body (directly or indirectly) modify the container iterated over?

If the answer is yes, you also need to take a copy and iterate over the copy, but as the nice guy that you are, you will leave a comment telling the future You why that copy is necessary:

const auto containerCopy = container; // doSomethingWith() may modify 'container' if ....
for (const auto &e : containerCopy)
    doSomethingWith(e);

I should note that in cases where the container modification is restricted to appends, you can avoid the copy (and the detach caused by it) by using an indexed loop:

for (auto end = languages.size(), i = 0; i != end; ++i) // important: cache 'languages.size()'
    languages += getSynonymsFor(languages[i]);

Avoiding Detaching

If your container is a std:: container or QVarLengthArray, you are done. Arguably, Q_FOREACH should never, ever have been used on such a container, since copying those always copies all elements (deep copy).

If your container is a const lvalue or a const rvalue, you are done, too. Const objects don’t detach, not even the Qt containers.

If your container is a non-const rvalue, simply store it in an automatic const variable, and iterate over that:

const auto strings = functionReturningQStringList();
for (const QString &s : strings)
    doSomethingWith(s);

Last, not least, if your container is a non-const lvalue, you have two choices: Make the container const, or, if that doesn’t work, use std::as_const() or qAsConst() (new in Qt 5.7, but easily implemented yourself, if required) to cast to const:

for (const QString &s : qAsConst(container))
    doSomethingWith(s);

There, no detaches, no unnecessary copies. Maximum efficiency and maximum readability.

Conclusion

Here’s why you’ll want to port away from Q_FOREACH, ideally to C++11 ranged for-loops:

  • Q_FOREACH is going to be deprecated soon.
  • It only works efficiently on (some) Qt containers; it performs prohibitively expensive on all std containers, QVarLengthArray, and doesn’t work at all for C arrays.
  • Even where it works as advertised, it typically costs ~100 bytes of text size more per loop than the C++11 ranged for-loop.
  • Its unconditionally taking a copy of the container makes it hard to reason about the loop.

Happy porting!

The post Goodbye, Q_FOREACH appeared first on KDAB.

Embedded Systems Are the Backbone of IoT, but It’s Software That Brings It All Together

Smoking hot terms like Big Data and the Internet of Things or “IoT” have taken their place in conventional business lingo, and it’s practically impossible to avoid these terms — everyone has recognized what developers have seen for many years. New applications for your products, new opportunities for your offering, new customer areas are emerging, and the time to re-think how you apply connectivity, mash-ups and various sensors is going mainstream. As the business potential has started to materialize, we see that the ecosystem around IoT begins to intensify and expand, strengthening the backbone of IoT, as it shifts into high gear.

Qt Top 5 Considerations IoT infographicYou could argue that the Internet of Things is simply the connected embedded system re-coined. These systems are already around us and machine-to-machine (M2M) systems have been chatting to each other for decades. But in addition to just the technical capabilities between embedded devices, IoT also includes the aspect of The Omnipresent Cloud and mobile client access, shifting the way we use these connected embedded systems. And that then enables all the new IoT innovations, but also affects how we need to design these systems, especially from software perspective: Instead of creating a self-contained embedded device with an online connection, we are designing complex and extensible systems with connected sensors, embedded devices, a cloud back-end and mobile clients. *Poof* Embedded software design just became exponentially more complex.

As computers (and sensors) get smaller, smarter and connected, our everyday objects, from clothing to lavatories to cars, get more intelligent. Although hardware has center stage, it’s time to start looking at the software that will bring it all together.

Embedded Development Can Be Modern, Too 

In the past ten years, there has been a tremendous leap in how software is developed. Modern software development in general seems to be about finding new ways of working even more agile, adopting new techniques quickly, abandoning non-working ones, moving rapidly forward with continuously deployed changes and near-realtime iterations in a harmonious telepathy between the customer and a self-guiding and proactive development team.

Modern software development is naturally awesome, but unfortunately, in embedded software development one can too rarely apply any of the stuff the cool kids in the web/mobile world are hyping about. Because of industry-related verification/certification requirements and especially the technical limitations of embedded cross-compilation workflow, I still hear waterfalls in the distance. At the same time, when we’re supposed to create these complex and innovative IoT things with modern touch UIs, we can’t afford to have development cycles that take weeks for each iteration of a simple UI tweak. The markets need to be reached faster! This is what we want to change with Qt—we want to make embedded development as seamless as desktop or mobile development. We want to provide one technology for all embedded and mobile platforms — and enable rapid deployment cycles for the whole IoT system.

Qt libraries give you various UI approaches for creating a unified UX between your embedded and mobile devices. In addition, there are plenty of high-level Qt APIs for creating the engine of your IoT gateways: eg. Bluetooth LE for sensor communication and built-in JSON support for cloud communication. Qt Creator IDE works on all platforms, supports direct deployment to desktop, embedded and mobile targets and includes all the tools for designing, developing, debugging, profiling and analyzing your code. You can do rapid prototyping on your laptop and push the build to your embedded hardware or mobile device to see the changes there.

  • Support multiple devices with or without screens
  • Leverage your core communication libraries between a desktop interface and a mobile gadget
  • Share code with other IoT developers building different parts of the ecosystem

To learn why having an embedded tool that has powerful UX capabilities can make the difference for your business: Read the whitepaper “Building the Internet of Things and How Qt Can Help”. 

 

The post Embedded Systems Are the Backbone of IoT, but It’s Software That Brings It All Together appeared first on Qt Blog.

Qt Creator 4.1.0 released

We are happy to announce the release of Qt Creator 4.1.0.

Flat Dark Theme - Qt Creator 4.1Flat Light Theme - Qt Creator 4.1

Themes

We added Flat Light and Flat Dark themes, complementing the Flat theme which was added in 4.0. They are available in the Environment > Interface > Theme settings. We also added some more editor color schemes which you find in Text Editor > Fonts & Colors.

Editing

Text Editors now behave much better with regards to automatically inserting and skipping characters. If you type a quote or bracket, the corresponding closing character is added. If you remove the opening character, it is removed again. If you type the closing character yourself, it replaces the automatically inserted one. Both of these now only happen as long as the text cursor did not move away from the closing character. You can also configure automatic insertion of brackets and quotes individually in the Text Editor > Completion settings.

C++

Aside from fixing bugs in the code model and static analyzer integration, we also updated our binary packages to use Clang 3.8.1, which also fixes many issues, especially with MSVC. We also added a more recent patch to Clang that makes it work better with MSVC2015 Update 3.

Qt Quick

Both Qt Quick Designer and QML Profiler received many performance improvements. You can now choose a Qt Quick Controls 2 style which Qt Quick Designer uses to render your items. The new Move to Component action moves an item and its contents into a separate file.

CMake

Many bugs were fixed for supporting CMake projects, and the workflow further improved. CMake is only run automatically if Qt Creator is the active application, and you can turn automatic running completely off (Build & Run > CMake). If you set the QML_IMPORT_PATH variable in the CMake cache for your project, Qt Creator picks this up and feeds it to the QML code model, so you can access your QML imports in the editor. (Example CMake code: set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/qml ${CMAKE_BINARY_DIR}/imports CACHE string "" FORCE))

Other improvements

If you turn on the plugin (Help > About Plugins, or Qt Creator > About Plugins on macOS), Qt Creator gains experimental support for the Nim programming language. Many thanks to Filippo Cucchetto for this contribution. It supports syntax highlighting, indentation, coding style settings, and simple project management, including building, running and debugging applications.

All this is just a small excerpt from all the changes and improvements that you find in Qt Creator 4.1.0. Find out more in our change log, or just go ahead, download and try it for yourself!

Get Qt Creator 4.1.0

The opensource version is available on the Qt download page, and you find commercially licensed packages on the Qt Account Portal. Qt Creator 4.1.0 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.1.0 released appeared first on Qt Blog.

Release 2.9.1: Multiplayer Enhancements & Plugin Updates

V-Play 2.9.1 is now available to download. This update improves the V-Play Multiplayer by adding a single player option and a new latency testing feature, as well as general improvements to the multiplayer game example. When you update to V-Play 2.9.1, you can also include the latest Android libraries, Play Services libraries 9.4.0, for all of your V-Play Plugins. This provides your plugins with the most up-to-date functionality on the Android platform.

It also includes fixes and improvements for a number of other V-Play features.

Update Now!

If you’d like to make cross-platform apps and games but haven’t signed up for V-Play yet, you can download the SDK for free.

Multiplayer Enhancements

One Card!

Following the recent release of V-Play Multiplayer, we added a multiplayer game example, ONU, to the V-Play Sample Launcher. ONU is now One Card!, and includes advanced functionality such as single player mode, medals for high-level players and an increased max player level.

onecard-menu onecard-game

One Card! also showcases how you can add monetization features, such as in-app purchases and advertisements, to your mobile game. It’s simple to add these features with the Soomla and AdMob plugins.

V-Play Multiplayer Functions & Properties

In order to make the creation of multiplayer games even easier with V-Play, you can now use some added functions and properties to reduce your development time and improve your testing phase.

The latencySimulationTime property allows you to test the messaging system within your multiplayer game by simulating network latency. This helps you to fix errors coming from delayed messages which occur when players have a poor network connection. This makes debugging your multiplayer game much easier.

The restartGame() and endGame() functions make it possible to restart or end a game at the same time for all players in a game room.

You can now use the createSinglePlayerGame() to turn your multiplayer game into an offline single player game. This function skips the matchmaking phase of game creation and lets the player begin a new game immediately. It prevents messages from being sent and handles everything on the local device.

One Card! Game Demo

You can try out all these new features for yourself. For a sample implementation of these new features, have a look at the “One Card!” Multiplayer Demo. You can also download the official One Card! game on the App Store and Google Play.

iTunes_download_link Google_Play_Badge-1

Updated V-Play Plugins

When you update to V-Play 2.9.1, you can now include the latest Android libraries, Play Services libraries 9.4.0, for all of your V-Play Plugins. This provides your plugins with the most up-to-date functionality on the Android platform.

We’ve also updated the OneSignal, Chartboost and AdMob plugins to their latest versions. If you’re planning to use these plugins on iOS devices, make sure to copy the latest iOS framework from here. This update fixes the video caching issue within the Chartboost plugin that prevented the loading of video interstitials and rewarded videos.

Fixes & Improvements

V-Play 2.9.1 includes fixes and improvements to TexturePacker integration, the V-Play Game Network, and the Theme component. You can find more information on these updates in the V-Play change log.

How to Update

Test out these new features by following these steps
Step 1

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

If you haven’t installed V-Play yet, you can do so now with the latest installer from here.

Step 2

The V-Play Sample Launcher allows you to quickly test and run all the open-source examples and demo apps & games that come with the V-Play SDK, from a single desktop application.

After installing V-Play, you can start the V-Play Sample Launcher from the application shortcut in your V-Play SDK directory.

Sample Launcher-v-play

Now you can explore all of the new features included in V-Play 2.9.1!

For a complete list of the changes to V-Play with this update, please check out our change log!

More Posts like This

How to Make a Game like Super Mario Maker with Our New Platformer Level Editor

super mario level editor blog

16 Great Sites Featuring Free Game Graphics for Developers

game graphics

The 13 Best Qt, QML & V-Play Tutorials and Resources for Beginners

tutorials capture

21 Tips That Will Improve Your User Acquisition Strategy

User Acquisition

The post Release 2.9.1: Multiplayer Enhancements & Plugin Updates appeared first on V-Play Engine.

QtCon: Squish for Qt Training in Berlin

QtCon

On September 1st, as part of the QtCon conference, our partner KDAB hosts a day of training. This training day allows you to gain knowledge in several Qt-related topics, including automated Qt GUI testing with Squish for Qt.

froglogic‘s ISTQB-certified Senior Software Trainer Florian Turck will conduct the full-day Squish for Qt training and share his in-depth experience of effectively using Squish. Seats for the training are still available.

Register for QtCon here:

https://conf.qtcon.org/en/session/new?conference_acronym=qtcon