Quantcast
Channel: Planet Qt
Viewing all 15410 articles
Browse latest View live

The Qt Company Blog: OPC UA support in Qt 5.11

$
0
0

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

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

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

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

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

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

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

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

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

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

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

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


The Qt Company Blog: Qt 3D Studio 2.0 Beta Available

$
0
0

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

New Runtime & Viewer Application

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

Qt 3D Studio Viewer Profile and Debug view

Qt 3D Studio Viewer Profile and Debug view

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

Improved Data Input

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

Improved Data Input

Improved Data Input

For more details on using Data Inputs please refer to documentation 

Editor Improvements

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

New timeline

New timeline

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

Installation

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

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

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

Cutelyst Framework: Creating RESTful applications with Qt and Cutelyst

$
0
0

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

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

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

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

Let's start by defining the server API:

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

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

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

First we create the server application:

$ cutelyst2 --create-app ServerREST

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

$ cutelyst2 --controller ApiV1

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

#include "apiv1.h"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

After all the implemented methods start the server:

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

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

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

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

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

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

Part 2 - REST Client Application

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

Our interface will be composed of:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

https://github.com/cutelyst/cutelyst

V-Play Engine: How to Support the Notch and Why – THE Developer Guide for iOS & Android

$
0
0

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

 

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

 

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

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

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

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

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

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

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

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

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

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

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

Bigger Screen Size and Safe Area of iPhone X

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

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

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

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

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

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

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

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

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

How Do Existing Apps Look on iPhone X?

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

iOS App with and without iPhone X Support

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

How to Create iPhone X Apps with Xcode

Enable iPhone X Support for Your App

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

Add new launch images to support iPhone X.

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

Position Your Content to the Safe Area Layout Guide

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

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

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

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

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

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

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

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

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

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

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

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

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

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

iPhone X Notch Issue with Hidden StatusBar

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

Android P Developer Preview: Display Cutouts

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

Upcoming Android Devices with Display Cutout

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

How to Test Apps with Display Cutout in Android P

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

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

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

Android P Developer Settings - Display Cutout Simulation

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

Android P Developer Preview with Simulated Display Cutout

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

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

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

Custom Layouts with Safe Area Insets in Android P

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

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

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

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

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

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

V-Play Support for Android P and Display Cutouts

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

import VPlayApps 1.0
import QtQuick 2.0

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

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

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

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

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

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

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

  }
}

 

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

V-Play Support for iPhone X and the Notch

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

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

import VPlayApps 1.0
import QtQuick 2.0

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

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

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

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

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

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

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

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

Optimize your User Interface with Adaptive Layouts

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

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

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

import VPlayApps 1.0
import QtQuick 2.0

App {

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

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

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

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

}

 

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

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

The available safeAreaInsets properties are:

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

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

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

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

import VPlayApps 1.0
import QtQuick 2.0

App {

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

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

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

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

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

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

Support for Display Cutout on Android P Devices

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

V-Play Supports both iOS 11 and Android P.

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

Simulate Safe Area Insets while Developing on Desktop

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

V-Play Device Resolution Simulation on Desktop

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

iPhone X Desktop Simulation with Safe Area Insets

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

 

 

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

More Relevant App Development Resources

The Best App Development Tutorials & Free App Templates

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

App Development Video Tutorials

 

 

Thanks for reading & scrolling that far! :)

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

 

More Posts Like This

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

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

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

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

The Qt Company Blog: Get Started with Qt 3D Studio 2.0 beta 1

$
0
0

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

Pre-built runtime binaries

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

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

Let’s Install

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

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

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

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

q3dsb1inst1

q3dsb1inst2

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

Let’s Design

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

q3dsb1screenshot

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

Let’s Code

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

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

q3dsb1screenshot2
The qmldatainput example in action

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

q3dsb1screenshot3

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

q3dsb1screenshot4

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

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

(replace c:\QtTest as appropriate)

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

Launching this gives us quite impressive results already:

q3dsb1screenshot5

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

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

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

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

Option 1: Direct Attribute Access

q3dsb1screenshot6

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

...
import QtQuick.Controls 2.2

Window {
    ...

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

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

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

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

Option 2: Data Input

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

q3dsb1screenshot8

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

...
import QtQuick.Controls 2.2

Window {
    ...

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

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

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

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

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

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

The Qt Company Blog: QtKNX updates for 5.11

$
0
0

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

API improvements

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

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

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

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

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

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

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

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

ETS KNX project file parsing

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

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

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

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

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

Finally, we can extract the information that was parsed:

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

Other important updates

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

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

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

KDAB on Qt: KDAB at QtDay 2018

$
0
0

QtDay is the yearly Italian conference about Qt and Qt-related technologies. Its 2018 edition (the seventh so far!) will be once more in the beautiful city of Florence, on May 23 and 24. And, once more, KDAB will be there.

I am also glad to announce that my talk has also been accepted: I am going to give an introduction to GammaRay, KDAB’s introspection tool for Qt applications.

You can register to QtDay here. See you in Florence!

The post KDAB at QtDay 2018 appeared first on KDAB.

KDAB on Qt: Browse PDFs in a Qt Widgets application

$
0
0

Some months ago Shawn Rutledge blogged about the new QtPdf module, a Qt wrapper around the PDFium library, which allows you to render PDF documents to QImages. Since that blog post we have invested some more work into the module to make it more useful in your day-to-day projects.

One long-standing bug report against Qt is QTBUG-28886, which is about adding a widget to Qt that can easily render a PDF document. That does not only involve rendering of single pages, but also to provide ways to navigate through the document, so say hello to…

QPdfView

QPdfView is a widget that renders a PDF document that has been loaded through QPdfDocument. It offers a single page and a continuous multi page mode and the user can choose between fit-to-width, fit-in-view or a custom zoom level.

To avoid the UI getting blocked while the PDF document is rendered, the rendering of the single pages is off-loaded to a worker thread.

Getting the code

To test the new features, just clone the QtPdf repository, install it and compile the examples like this:

git clone git://code.qt.io/qt-labs/qtpdf
cd qtpdf
git submodule update --init --recursive
qmake
make
cd examples/pdf/pdfviewer
qmake
make
./pdfviewer

Usage

Using QPdfView is quite simple – loading a PDF document and showing it on screen can be done in a couple of lines now:

#include 
#include 

QPdfDocument *document = new QPdfDocument;
document->load("document.pdf");

QPdfView *view = new QPdfView;
view->setDocument(document);
view->show();

If you want to see a more extensive example, have a look at the examples/pdf/pdfviewer directory in the QtPdf module.

Next steps

At the moment the PDFium version which is shipped with QtPdf is rather outdated, and therefore does not include the latest security fixes from upstream. The blocking factor from upgrading it is PDFium’s build system, which has changed from gyp to gn; the build system integration inside QtPdf hasn’t followed up yet.

Thankfully, Michal Klocek from The Qt Company provided the first patches that allow us to implement a proper integration between qmake and gn, so that compiling the QtPdf module with an up-to-date PDFium version should be much easier in the future.

On the UI side there are many things to do as well, here just a short selection from the top of my head:

  • extend navigation possibilities (e.g. follow links, navigate to sections)
  • add custom QtQuick item to render PDF pages (patches in progress already)
  • extend and improve documentation.

Nonetheless, I hope this module will be useful to the many users who are looking for an easy solution to render PDF documents in their Qt applications!

About KDAB

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

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

The post Browse PDFs in a Qt Widgets application appeared first on KDAB.


Sune Vuorela: Modern C++ and Qt

$
0
0
layout->addWidget(std::make_unique().release());

–’cause raw new’s are bad.

Sune Vuorela: Modern C++ and Qt – part 2.

$
0
0

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

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

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

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

It resulted in code like

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

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

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

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

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

Sune Vuorela: Where KDEInstallDirs points to

$
0
0

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

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

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

and various other options can be set as well.

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

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

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

include(KDEInstallDirs)

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

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

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

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

$
0
0

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

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

Implementing a model class

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

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

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

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

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

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

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

private:
    Storage m_data;
};

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

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

Making the code more robust

The code of the class above has a few issues.

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

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

Therefore, a more correct implementation would look like this:

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

        return m_data.rowCount();
    }

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

        return m_data.columnCount();
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Introducing checkIndex

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

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

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

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

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

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

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

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

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

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

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

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

Conclusions

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

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

About KDAB

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

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

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

KDAB on Qt: QtDay Italy, May 23-24

$
0
0

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

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

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

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

See you in Florence!

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

Sune Vuorela: Managing cooking recipes

$
0
0

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

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

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

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

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

There is a way to insert tags into recipes.

I can find them by title.

And I can find recipes by ingredients.

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

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

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

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

KDAB on Qt: KDAB at SIGGRAPH 2018

$
0
0

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

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

Meet us at SIGGRAPH 2018!

The post KDAB at SIGGRAPH 2018 appeared first on KDAB.


KDAB on Qt: Browse PDFs in a Qt Widgets application

$
0
0

Some months ago Shawn Rutledge blogged about the new QtPdf module, a Qt wrapper around the PDFium library, which allows you to render PDF documents to QImages. Since that blog post we have invested some more work into the module to make it more useful in your day-to-day projects.

One long-standing bug report against Qt is QTBUG-28886, which is about adding a widget to Qt that can easily render a PDF document. That does not only involve rendering of single pages, but also to provide ways to navigate through the document, so say hello to…

QPdfView

QPdfView is a widget that renders a PDF document that has been loaded through QPdfDocument. It offers a single page and a continuous multi page mode and the user can choose between fit-to-width, fit-in-view or a custom zoom level.

To avoid the UI getting blocked while the PDF document is rendered, the rendering of the single pages is off-loaded to a worker thread.

Getting the code

To test the new features, just clone the QtPdf repository, install it and compile the examples like this:

git clone git://code.qt.io/qt-labs/qtpdf
cd qtpdf
git submodule update --init --recursive
qmake
make
cd examples/pdf/pdfviewer
qmake
make
./pdfviewer

Usage

Using QPdfView is quite simple – loading a PDF document and showing it on screen can be done in a couple of lines now:

#include 
#include 

QPdfDocument *document = new QPdfDocument;
document->load("document.pdf");

QPdfView *view = new QPdfView;
view->setDocument(document);
view->show();

If you want to see a more extensive example, have a look at the examples/pdf/pdfviewer directory in the QtPdf module.

Next steps

At the moment the PDFium version which is shipped with QtPdf is rather outdated, and therefore does not include the latest security fixes from upstream. The blocking factor from upgrading it is PDFium’s build system, which has changed from gyp to gn; the build system integration inside QtPdf hasn’t followed up yet.

Thankfully, Michal Klocek from The Qt Company provided the first patches that allow us to implement a proper integration between qmake and gn, so that compiling the QtPdf module with an up-to-date PDFium version should be much easier in the future.

On the UI side there are many things to do as well, here just a short selection from the top of my head:

  • extend navigation possibilities (e.g. follow links, navigate to sections)
  • add custom QtQuick item to render PDF pages (patches in progress already)
  • extend and improve documentation.

Nonetheless, I hope this module will be useful to the many users who are looking for an easy solution to render PDF documents in their Qt applications!

About KDAB

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

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

The post Browse PDFs in a Qt Widgets application appeared first on KDAB.

KDAB on Qt: KDAB at Italian Cpp 2018

$
0
0

KDAB is proud to be bronze sponsor at Italian C++ Conference, the largest conference in Italy specifically focused on C++ development for professionals, students and businesses using C++.

It’s free, organized by the Italian C++ community, and there’s Italian icecream to think about too… It’s an offer you can’t refuse 😉

Sign up and see you in Milan in June!

The post KDAB at Italian Cpp 2018 appeared first on KDAB.

The Qt Company Blog: Optimizing the QML compiler pipeline

$
0
0

Qt QML is our engine to run and execute QML, the language used to create Qt Quick based user interfaces. Qt QML does not have any dependencies on graphical things, and in addition to the QML language support, it features a Javascript engine that is compliant with ECMAScript 5.1.

As the foundation for our Qt Quick user interface technology, the module is core to many of our users. Internally, it mainly consists of two parts. A compiler pipeline used to compile QML and ECMAScript down to binary data structures and bytecode/assembly and a runtime that assists in executing the generated code. This talk will focus on the first part.

The compiler pipeline that we used in Qt QML until version 5.10 was growing increasingly complex in recent Qt versions.

Below, you can see a simplified picture of the old compiler pipeline.

unknown

We basically started off by sending QML and Javascript code into a Lexer and Parser, which created an Abstract Syntax Tree (AST) for the code being compiled. This AST was then sent into a class called Codegen, that generated an Intermediate Representation (IR) out of the AST. The IR was then sent through various optimization stages, doing dead code elimination, some limited type deduction, and other tricks.

As a next step, the optimized IR was then sent into one of two Instruction selection backends (Isel), that generated either Bytecode or Assembly (and some binary data stored in the Compilation Unit) out of the IR.

Together, this was a rather long and complex pipeline. The drawbacks of it were a rather high cost for compiling QML/JS, leading to relatively long startup times. In addition, there was no way to mix and match bytecode and assembly. It was either one or the other.

Other Javascript engines (such as v8 and JavascriptCore) have lately been moving over to a different pipeline, where you directly generate Bytecode out of the AST and then use that Bytecode as a basis for the JIT. There are several advantages to such an approach. First, you gain a platform-independent representation of your QML/JS in bytecode format. Startup is much faster, as parsing QML/JS to generate the bytecode is a very fast step. You can rather easily collect tracing information on the generated bytecode for a second stage JIT compiler, that then generates fully optimized assembly.

Last summer, we did a small research session and tried a similar approach for Qt QML. We got extremely far with only two days of work and could see that this would lead to huge simplifications in our internal compiler pipeline.

Because of this, we then sat down and implemented the new pipeline we had prototyped with the goal of having it ready for Qt 5.11. The picture below gives you an idea how the new pipeline is looking.

unknown-1

With this new pipeline, we now directly generate Bytecode from the Codegen, completely skipping any intermediate representation. This bytecode is platform independent and can be executed directly. Where we see hot code paths (currently functions that are executed often enough), we invoke a JIT that compiles the bytecode down to assembly.

At the same time, we’ve been completely reworking our bytecode format and the interpreter to boost its performance. Our main goals here were to generate a very compact bytecode format to save RAM, disk space and have an efficient and fast interpreter on top. We are pretty happy with the results we achieved, showing that the new interpreter is almost twice as fast as the old one, and achieves around 80-90% of the performance of the old JIT. The bytecode is also very compact, using up significantly less memory than the old format. Here’s a short example showing you the bytecode of a simple function:

function add(x, y) {
return x + y;
}

=== Bytecode for "add" strict mode false
1 0: 0a 06 LoadReg a2
2: 6a 05 Add a1, acc
4: 00 Ret

As you can see, the generated bytecode is just 5 bytes, loading argument 2 into the accumulator, adding argument 1 to it, and then returning the result.

Once we had the new interpreter implemented, we then went ahead and added a relatively simple hotspot JIT on top of the interpreter, to further optimize frequently executed functions. The JIT doesn’t yet use any tracing information or other optimizations, but already beats the performance of the JIT we had in 5.10. The graph below gives you an overview of the performance improvements when running our v8-bench performance test suite (higher numbers are better). New Interpreter/JIT refers to the interpreter in Qt 5.11, old Qt 5.9.

 

qml-compiler-pipeline

These improvements allowed us to rework out QML caching and ahead-of-time compiling infrastructure. Both now cache the generated Compilation unit and the Bytecode on disk, instead of trying to generate assembly. This leads to significantly smaller binaries keeping the fast startup times. And with the fast, new interpreter, and the hotspot JIT this beats the old QML compiler in runtime performance.

As a side-effect, we now unified things, and made the ahead-of-time QML compiler available in the open source version of Qt as well. But be aware, that by using the compiler you will be tying yourself to the exact patch level version of Qt you’re using, as we are not guaranteeing that the bytecode format will stay compatible between versions. The transparently generated .qmlc/.jsc files however do contain a version check, and will get updated whenever the underlying .qml/.js files or the patch level version of Qt changes.

Simplifying the compiler pipeline also enabled us to simplify and clean up other parts of our code base. We re-architectured the calling convention and the way we set up stack frames when calling JS/QML functions saving a lot of overhead when invoking functions.

One place where this can be seen is in a small benchmark where we do recursive function calling to compute a Fibonacci series. That benchmark became almost 3 times as fast in Qt 5.11 compared to earlier Qt versions.

Moving forward towards Qt 5.12 and later, we have more good stuff coming. There is research ongoing towards a tracing JIT, and we’re also working on updating our engine to fully support Ecmascript 7. But more on those topics in a future blog post.

The post Optimizing the QML compiler pipeline appeared first on Qt Blog.

KDAB on Qt: Heaptrack v1.1.0 release

$
0
0

After more than a year of work, I’m pleased to release another version of heaptrack, the Linux memory profiler! The new version 1.1.0 comes with some new features, significant performance improvements and – most importantly – much improved stability and correctness. If you have tried version v1.0 in the past and encountered problems, update to the new v1.1 and try again!

Notable Changes

The most effort during this release cycle was spent on improving the correctness of heaptrack. The initial version suffered from bugs that could lead to corrupted or truncated data files. Heaptrack v1.1 is generally much better in this regard, and you should be able to use it in more situations than before. Furthermore, attaching heaptrack to an already-running process will catch more allocations and thus produce more accurate data. To verify the quality of the heaptrack code base, more tests have been added as well. These tests also finally enable us to use Valgrind or the Sanitizers on most of the heaptrack code, which wasn’t possible previously.

Additionally, some important new features have been added which greatly improve the usability of heaptrack:

  1. When extended debug information is available, stack traces now include inlined frames.
  2. Split debug information in separate files is now supported.
  3. Compressed debug information is properly handled.
  4. The embedded flamegraph view is now searchable.

Finally, quite some work went into optimizing heaptrack to further reduce its overhead. The initial version was quite good already from a performance point of view, but version 1.1 is even better! Most notably, the analysis of large data files is now often much faster. This is in great parts due to the new optional dependency on zstd. This fantastic state-of-the-art compression algorithm greatly reduces the CPU overhead during recording while compressing the heaptrack data. But not only that – decompression at analysis time is significantly reduced compared to the standard gzip compression. In case you wonder: Data files are now often slightly smaller too!

Last but not least, heaptrack v1.1.0 can be downloaded as a portable AppImage which should run on most 64bit Linux systems in use these days!

Download heaptrack v1.1.0

If possible, wait for your distribution to provide you with an updated package for heaptrack v1.1.0. Otherwise, download the AppImage, make it executable and run it. If neither of these two options works for you, grab the sources and compile the code for your target platform:

Many thanks to the various people who contributed to this release. Please continue to hand in your patches, preferably via KDE’s phabricator instance or via heaptrack on GitHub. Bugs can be reported on bugs.kde.org.

If your company needs commercial support for heaptrack, then get in touch with us at KDAB. We offer workshops and trainings specifically about profiling and debugging on Linux.

The post Heaptrack v1.1.0 release appeared first on KDAB.

The Qt Company Blog: Qt 5.11 released

$
0
0

Slightly ahead of our planned schedule, we have released Qt 5.11 today. As always, Qt 5.11 comes with quite a few new features as well as many bug fixes to existing functionality. Let’s have a look at some of the cool new features.

Qt Core and Network

A lot of work on small details has happened in Qt Core. As an example, some of our tools classes got new rvalue reference overloads and we filled in some missing methods for better STL compatibility. Our item model has received a couple of new features, for details have a look at this blog post.

In Qt Network, ALPN and thus HTTP/2 negotiation are now supported on iOS. QNetworkRequest gained a Http2DirectAttribute to start an HTTP/2 connection without first negotiating.

One of the larger updates in Qt Core went into our Unicode support. QChar, QString, QTextBoundaryFinder and our algorithm for bidirectional text are now fully compatible with Unicode 10.

Qt GUI and Widgets

A major focus area for Qt 5.11 has been the accessibility support on Windows. It got completely rewritten and is now based on Microsoft UI Automation, not on the old Microsoft Active Accessibility framework, leading to a vastly improved accessibility support on Windows.

Some major work has also gone into improving the widget styles on Windows to better support High-DPI displays. The print dialog on Linux has also received a major overhaul, now featuring much better support for all the CUPS provided options.

Qt Widgets itself has received numerous bug fixes and support for quick text selection by mouse in QLineEdit.

Together, this gives a very nice update for all our Desktop users.

Qt QML

Some larger changes have been happening under the hood of our QML engine. We have completely rewritten the compiler pipeline, that parses and compiles QML. The new pipeline brings some major improvements in performance and maintainability.

The new pipeline always compiles QML to a platform-independent bytecode. The engine will cache this bytecode in .qmlc files. You can also generate the bytecode ahead of time, using the qmlcompiler feature (which is now also available in the open source version).

The new bytecode interpreter has a vastly improved performance over the old version. It reaches around 80-90% of the performance of the JIT in Qt 5.10 in most of our test cases. A new hotspot JIT has been added on top of that, beating our old JIT in pretty much all areas.

For more details, have a look at the separate blog post here.

Qt Quick and Qt Quick Controls

In Qt Quick, we’ve expanded our support for loading compressed textures in the Image element and now support both .ktx and .pkm container file formats. This feature helps cut down on application startup time and memory consumption by storing images in a format that is directly digestible by the GPU. For more details have a look at this blog post.

Qt Quick Controls 2 has received lots of smaller features and bug fixes. Examples are auto-repeat properties for Buttons, better positioning support for ScrollBars and better styling support for SpinBoxes.

Qt Location

Qt Location is also an area where many cool things have been happening. The largest new feature is probably the experimental support for turn-by-turn navigation. But there is more. Qt Location now has an experimental API to create map objects that are not bound to QQuickItems. The performance of MapPolyline objects has seen large improvements and layers are now working in combination with Map items. In addition, we made the Routing and Places API extensible and added a new WayPoint element. Finally, the MapBox plugin gained support for geocoding and Places.

Qt Webengine

As has become standard in our feature releases, we’ve updated the Chromium version underneath Qt Webengine to Chromium 65. In addition, we now support embedded DevTools without requiring the use of a separate browser, an installable cookie filter and quota permissions.

Qt for Device Creation

All new functionality mentioned above is of course also available in Qt for Device Creation. In addition, we’ve been working on improving some embedded-specific features.

One new feature here is support for hardware-based graphics layers, currently available as a Technology Preview for platforms supporting VSP2 hardware compositing. This can be used for features such as Video underlays and helps improve performance and reduce power consumption. We are aiming to extend the support to more platforms and hardware combinations in future releases.

Qt SerialBus has received improvements to its CAN Bus support. The KNX module has received some larger updates. In addition, Qt 5.11 will feature a new module that adds support for OPC/UA. This module is available as a Technology Preview in Qt 5.11.

Other items

qdoc now uses libclang to parse C++ giving us much better support for modern C++ in our documentation. Qt Serialbus and Bluetooth have now improved support for CAN bus and BTLE.

With Qt 5.11, we have also removed support for some older compilers and platforms. MSVC 2013, QNX 6.6 and macOS 10.10 are no longer supported.

Qt 3D and Qt 3D Studio

We are working hard to get the second release of Qt 3D Studio ready for you. This second release comes with a fully rewritten runtime, that’ll be based on top of Qt 3D. This will give all of you a better and deeper integration into the rest of Qt when using Qt 3D Studio to create 3D user interfaces.  With this work, Qt 3D has also received numerous new features, performance improvements, and bug fixes. Qt 3D Studio 2.0 is currently in beta, and we are working hard to get the final release out within the next few weeks.

Qt for Webassembly and Python

With Qt for Webassembly, we are working towards filling the last large gap in our cross-platform story, allowing our users to target the web and browsers as a platform for Qt applications. The first version has been released as a Technology preview today, please check out the separate blog post for further details.

In addition, to the above, we are actively working on supporting Qt on Python . The first release of it is planned for June, and we’ll keep you posted with more details.

Thanks to the Qt Community

Qt 5.11 adds a lot of new functionality and improvements. Some of them would not have been possible without the help of the great community of companies and people that contribute to Qt by contributing new functionality, bug fixes, documentation, examples or bug reports. There are too many people to mention everybody in detail, but I’d like to especially thank Thiago Maciera from Intel for his ongoing work on maintaining Qt Core. From our partner basysKom, I’d like to thank Jannis Voelker and Frank Meerkötter for their work on OPC/UA. From our partner KDAB, I’d like to thank Albert Astals Cid for his work on CUPS printing, Sean Harmer and Paul Lemire for their ongoing work on Qt 3D and many others for helping maintain different parts of Qt. Thank you!

Get the new version

As usual, Qt 5.11 will be supported for one year. If you need longer support periods, Qt 5.9 is our current LTS release and will be supported until June 2020. Extended lifetime support can of course always be purchased from The Qt Company if required. Our next release after Qt 5.11, Qt 5.12 is planned for November and will again be a long-term supported release.

You can download Qt 5.11 from your Qt Account or www.qt.io/download. I hope you’ll like and enjoy the new release!

 

The post Qt 5.11 released appeared first on Qt Blog.

Viewing all 15410 articles
Browse latest View live