Qt for Python 5.12 Released

As mentioned in the Qt 5.12 release blog we finally reached the point that we can announce a technology preview free first release of Qt for Python for Qt 5.12. As it has become custom for the project and expected by Python developers, you can install the release via:


pip install PySide2

Additionally, you can get the wheels from Qt’s official download server, or simply get the source code from our Git repository.

Note that Qt for Python is tightly bound to a particular Qt version and does not inherit the LTS flag from Qt 5.12. Our aim for the future is to release Qt for Python at the same time as the Qt version that Qt for Python is based on. Unfortunately, our release process have not reached this point quite yet.

To get started, take a look at the recent webinar ”Develop Your First Qt for Python Application’‘ on how to develop an application from scratch, based on Qt Widgets and different Python modules. You’ll also see some examples on how to continue developing with other Qt for Python components, such as QML and Shiboken.

PySide2 and Shiboken2

The release consists of two modules. The first module, PySide2, provides Python wrappers for most Qt APIs and the second module, Shiboken2, enables users to wrap their own C++ libraries and make them available to the Python world. Internally the PySide2 module depends on Shiboken.

As you might expect, dropping the Technology Preview (TP) label implies a certain compatibility guarantee. This compatibility statement is somewhat different for Qt for Python users compared to C++ guarantees though. It mostly relies on Qt’s source compatibility guarantee as we use a specific syntax to expose Qt’s C++ API. Any Python application written with Qt for Python 5.12 should continue to work with future releases. On the Shiboken side of things, we are still somewhat off target as we continue to carry the TP label.

When looking at the supported platforms, we currently support Python 2.7 and 3.5+ for the three major desktop platforms.

The Future of the Project

Our future roadmap is full of promising ideas and in January we’ll start sorting out the next steps, which will probably include:

  • Simplifying the deployment of PySide2 applications,
  • Provide a smoother interaction with other Python modules,
  • Support other platform like embedded and mobile,
  • and many others.

With this context in mind, we appreciate any input you may have for the next release. You can either post it here, in our IRC channel on Freenode (#qt-pyside) or directly to our issue tracker under https://bugreports.qt.io .

 

The post Qt for Python 5.12 Released appeared first on Qt Blog.

Welcome to the 2018 Qt Champions!

Qt Champions

Another year has passed, winter has come so it’s time to celebrate the Qt Champions!

So without further ado:

@christian-ehrlicher was granted the *Rookie of The Year* title. Christian did an impressive number of submissions through this year while beginning only at the end of 2017. He wrote quite a lot of fixes for the model view system as well as test and documentation fixes.

@aha_1980 has again earned the *Quality Assurer* title due to his continuous services on the bug report system as well as doing quality reviews. He’s also actively improving Qt Creator and the QtSerialBus module.

This year’s *Ambassador* title goes to Kazuo Asano who’s a very active IRL Qt promoter in Japan. His various activities including study-sessions, seminar and now a book are doing wonder making Qt known in the empire of the rising sun.

Orgad Shaneh is our *Maverick Of The Year*. He’s the one we can thank for the now famous branch change bot on Gerrit. Bot he implemented as a side project to make the life of the sysadmins and developers easier.

This year’s *Fixer* is Alexander Volkov who’s done a lot of work on the X11/xcb backend that has no secret for him.

@VRonin various helper libraries and examples earned him the *Content Creator* title. His knowledge of Qt’s model view system is also well known and appreciated on the forum.

Due to his extensive presence on several fronts (IRC channel, forums, and more), @GrecKo has well earned the *Community Builder* title.

His many and to the point answers on the forum as well as continuous presence on it made @jsulm the second *Community Builder*.

And last but not least, his friendliness, continuous support, numerous examples and tests through these past years have opened him the door to the hall of fame. Congratulations to @mrjj who becomes the second Qt Lifetime Champion!

Let us all congratulate our Champions!

Many thanks for all the work done with and for the community!

The post Welcome to the 2018 Qt Champions! appeared first on Qt Blog.

Looking towards CES 2019: Predictions and where to find Qt

garmin_iviplatform_ces2018

Hello CES 2019!

One of the main events for automotive industry is less than a month away. Based on the early indicators, this year there will be more emphasis on creating a connected and intelligent vehicle than ever before. New connected experiences and multimodal inputs will be introduced by many companies showcasing at the event. In addition, I predict that we will see a wide range of new vehicle types, other than the standard four wheel vehicle, with displays.

This year The Qt Company and Qt based solutions can be found in multiple places in the event. You can meet The Qt Company with our demos in our private suite 2010 at the Westgate Hotel and at the Genivi event on Tuesday evening. In addition, we are very pleased to have been invited to join Luxoft’s booth, #3107 in the North Hall of the Las Vegas Convention Center, for meetings and quick demos. Together with our partners, we will present high performance visual implementations; integrations for virtual assistants; digital cockpits on different hardware and operating system configurations; and of course the tooling used for all of the solutions.

One thing is sure – our partners and customers will again surprise us with concepts built with Qt that the industry, including us, have not heard of or seen before. If you have a Qt based demo please let us know and remember to use “Built with Qt” icons and stickers!

See you in Las Vegas in January.

 

Want to schedule a meeting with us on site?  Fill out the form here.

The post Looking towards CES 2019: Predictions and where to find Qt appeared first on Qt Blog.

Qt Installer Framework 3.0.6 Released

We are happy to announce the release of Qt IFW 3.0.6. With Qt IFW you can create your own installers for the supported desktop Qt platforms: Linux, Microsoft Windows, and macOS.

3.0.6 is a bug fix release, here are some of the fixes:

  • Fix crash in updater if component does not exist anymore
  • Decrease metadata dowload amount
  • Fix admin query retry in Windows
  • Register virtual component for uninstall

The full list of bug fixes can be found from ChangeLog.

Precompiled binaries for the Installer Framework can be downloaded from Qt Online Installer, sources and binaries can be found also in Qt Download page (open source) or in your Qt Account.

The post Qt Installer Framework 3.0.6 Released appeared first on Qt Blog.

What’s new with the Wayland platform plugin in Qt 5.12?

Wayland is a display server protocol used on modern Linux systems, the Qt Wayland platform plugin lets Qt applications run on Wayland display servers (compositors).

Continuing the trend from the Qt 5.11 release, the Qt 5.12 release contains a substantial amount of improvements.

Window decorations

Old window decorations

Old window decorations

We’ve received quite a few complaints about the looks of our window decorations over the last few years. The message is usually: “They are ugly and don’t look native.”

On Wayland, window decorations are supposed to be drawn by the client by default. Consequently, Qt’s window decorations will probably never look identical to what other toolkits draw. I.e. there is no “native” look with client-side decorations. That is, however, no excuse for them to be ugly.

In 5.12, I’ve updated our default decoration plugin so it looks like something from this decade. It still won’t be “native” looking, but it looks closer much closer to what the other toolkits draw.

New window decorations

New window decorations

The default window background color is now used for the decorations, so it should follow your Qt theme quite nicely.

Window with dark theme

Decorations follow the theme of the window.

Furthermore, we’ve now also added support for support for the Wayland extension, xdg-decoration unstable v1. Compositors implementing this extension can now tell Qt clients that decorations will be drawn server-side instead of client-side. I.e. the decorations for Qt applications and other toolkits can be identical after all. This is also good news for people running tiling compositors. It’s no longer needed to set the environment variable QT_WAYLAND_DISABLE_WINDOWDECORATION on compositors that implement this extension. Toggling window decorations at runtime is now also possible.

server-side window dsecorations

The server-side-decoration QtWayland Compositor example. The bar at the top with the close button is drawn and handled by the compositor.

xdg-shell stable

On Wayland, the shell extension is the part of the protocol that gives meaning to surfaces, i.e. it communicates things like: This surface is a popup-menu, this is a toplevel window, this is its window title and application id, this is how it should be maximized, resized minimized etc.

In other words, a pretty important part of the protocol. The problem is that, while Wayland has been stable for many years, there has been no stable shell extension for the desktop. wl-shell is considered deprecated, and development has continued with the unstable xdg-shell. Unstable protocols have backwards incompatible changes in every release, this means that when a new version is released, it’s essentially a new, although similar, protocol. If we were to simply update our code to the protocol described in the new version, Qt clients would stop working on compositors not supporting the new version.

We’ve solved this by using a plugin architecture for loading a shell integration at runtime depending on what the compositor supports. In other words, each time a new breaking version of xdg-shell is released, we create a new plugin for it. The exciting news this time, is that xdg-shell finally turned stable in December last year, and with it broke backwards compatibility for the last time.

Consequently, Qt 5.12 adds the last and final shell plugin for xdg-shell. This means we can finally deprecate the old unstable xdg-shell plugins and concentrate on making the one stable plugin great.

High DPI cursors

Giant cursor

Support for high DPI cursors has been added. Cursors are now also loaded lazily to significantly reduce the memory footprint on embedded devices that don’t really need them.

Handling maximization and fullscreen on xdg-shell

Implementing fullscreen and maximization properly on xdg-shell required a huge refactor in how resizing works in Qt Wayland. That refactor is now in place, and Qt applications on all supported versions of xdg-shell should now properly switch between fullscreen, maximized and windowed mode.

Forcing a logical DPI of 96

window with tiny fonts

Sometimes compositors report 1px=1mm (a DPI of 25.4) when they don’t have better data available, causing physical DPI to be unreliable.

Quite a few things in Qt depend on the logical DPI, most notably point sized fonts. Previously, we’ve calculated the logical DPI using the physical size and resolution of the screen. This works great in most cases, but sometimes the physical dimensions that compositors provide are wrong, which usually results in tiny unreadable fonts. So in Qt 5.12, we switched to forcing a DPI of 96 by default. The old behaviour can still be restored by setting QT_WAYLAND_FORCE_DPI=physical in the environment.

Fractional scaling

Support for xdg-output unstable v1 was added. It’s a protocol extension for communicating additional information about screens and is needed to implement fractional window scaling on the compositor side. Read the details in David Edmundsons blog post.

The post What’s new with the Wayland platform plugin in Qt 5.12? appeared first on Qt Blog.

How to create QBSPs from Yocto builds

In Qt for Device Creation 5.12.0, we have enabled additional content installation via QBSPs (Qt Board Support Packages). A QBSP combines toolchain, target device images and set of Qt Creator configurations for particular device into a single file that can be easily shared and installed using the Qt online installer or the Maintenance tool. Technically a QBSP is an archived repository created by the Qt Installer Framework, and it’s creation is now fully integrated into the Yocto builds that are used to create the Boot to Qt Software Stack content.

For all the target devices currently supported in the meta-boot2qt layer, you can create a QBSP simply by issuing a bitbake command:

bitbake meta-b2qt-embedded-qbsp

This will first build both the toolchain and the image, and then package those into a QBSP file with the required Qt Creator configurations. The resulting QBSP file is located in tmp/deploy/qbsp/ folder in your Yocto build environment. The QBSP packaging respects the SDKMACHINE variable, so that if you use environment variable SDKMACHINE=i686-mingw32, a Windows toolchain is packaged into the QBSP.

The Yocto integration is implemented in two classes that can be used even if your target device has not been otherwise integrated into the meta-boot2qt layer. By inheriting the classes and setting up the required variables, you can have a QBSP with your own image for your own target device.

qbsp-image.bbclass

The QBSP will need a suitable device image to include in the package and to achieve this you will need to inherit qbsp-image.bbclass in the image recipe you want to use. You can control the content of the package with variable QBSP_IMAGE_CONTENT. By default Boot to Qt images include a .img file and a .conf file used by the Flashing Wizard.

inherit qbsp-image

QBSP_IMAGE_CONTENT = "\
  ${IMAGE_LINK_NAME}.img \
  ${IMAGE_LINK_NAME}.conf \
  "

qbsp.bbclass

qbsp.bbclass is the main class that handles the creation of the QBSP and you can control the various aspects of it through variables. Most important ones are the dependencies to the toolchain and image task using QBSP_SDK_TASK and QBSP_IMAGE_TASK variables.

For the Boot to Qt Software Stack, this is done in the meta-b2qt-embedded-qbsp.bb recipe:

inherit qbsp

VERSION_SHORT = "${@d.getVar('PV').replace('.','')}"
QBSP_NAME = "Boot2Qt ${PV}"
QBSP_MACHINE = "${@d.getVar('MACHINE').replace('-','')}"
QBSP_INSTALLER_COMPONENT = "embedded.b2qt.${VERSION_SHORT}.yocto.${QBSP_MACHINE}"
QBSP_INSTALL_PATH = "/${PV}/Boot2Qt/${MACHINE}"

QBSP_SDK_TASK = "meta-toolchain-b2qt-embedded-qt5-sdk"
QBSP_IMAGE_TASK = "b2qt-embedded-qt5-image"

Rest of the variables are then used to control how the installer shows the component and where they are installed. You can optionally also, e.g., add an EULA to the package, which the user would need to accept before they can install the components. You can find this and all the other information about the QBSP specific variables in the documentation.

The post How to create QBSPs from Yocto builds appeared first on Qt Blog.

Board Support Package and Commercial Build Enablers for Qt Partners

Qt partners can deliver support for Qt on their hardware boards a lot easier. We have improved and created features for Qt Board Support Package (QBSP) and ability to create Qt commercial builds on Yocto. The enablers will be part of both Qt 5.9 LTS and Qt 5.12 LTS.

As a partner, building and delivering open source versions of Qt under (L)GPL is a relatively simple affair: All the sources are available and the open source licensing allows the distribution of the assets as long as the open source licenses are attained with the packages.

Less so with a commercial license. If there was no out-of-box support as part of Qt for Device Creation partners or their customers have had to swap and add files manually. In addition, integrating developer tooling such as Qt Creator or Qt for Visual Studio had to be done manually with the help of documentation.

Sounds like a lot of hassle?

We agree.

That’s why we’ve been working hard to make it easier for Qt partners to create support for Qt embedded targets and test them as part of their own continuous integration and quality assurance processes.

QBSP for a super-easy developer tooling setup

qbsp-001

The QBSP contains all the IDE configurations for deployment, debugging and profiling, as well as the toolchain and embedded target software required for embedded development. In other words, a developer can set up an embedded target on their IDE by simply installing a QBSP package instead of clicking around and manually configuring the environment.

QBSP has been out an about for some time but the feature hardening and documentation have been… <ahem>… fragmented. We spent a fair amount of time this summer to make the feature simple to use for external parties. We have done the initial documentation of QBSP with Yocto-based embedded Linux as a target, but it can just as easily be used with any other target OS.

In addition, we are also using the QBSP feature ourselves in order to deliver to a wider range of Qt for Device Creation embedded targets (but that is another blog post).

Building commercial Qt from Git

We have also enabled an easy way to create commercial Qt builds from Git. This is primarily an enabler intended for operating system and hardware vendors integrating Qt as part of their own continuous integration and testing. In all simplicity, one can now create Qt images with a -commercial switch.

For verification that the Qt build for the hardware was a success and QBSP for the tooling works, we will initially provide partner documentation. The further planned evolution is to provide partners with additional test applications and mechanisms to improve automated testing capability on partner side.

Partner agreement required

The Qt License Agreement 4 explicitly forbids the distribution of commercial Qt or parts of it without a valid license. The rights to distribute Commercial Qt require a partnership agreement between you and The Qt Company. If you are interested in such a partnership agreement, please get in touch with us through https://www.qt.io/contact-us/

The post Board Support Package and Commercial Build Enablers for Qt Partners appeared first on Qt Blog.

From Trunk to Throttle – It’s Software that drives your car

Consumers are demanding great digital experiences in every context of their daily life – from mobile phones through home entertainment and appliances to cars. The automotive industry is quickly moving from a single static display for information sharing to digital cockpits delivering a wide range of services and applications. The pace of change is accelerated not only by external benchmarks such as mobile devices but also industry forerunners, such as Mercedes Benz, Tesla and Audi. All of them have lifted up the expectations for in-car experience. Responding to the increased digital requirements is different than responding to competition with better cup holders*.

The automotive industry must look at the procurement of software differently in the world of digital cockpits. The current processes and practices are optimized for sourcing hardware components globally. Software components are just glued on top of these practices. It has led to situations where software costs are creeping into projects and platforms. In order to build winning digital cockpits automotive OEMs must lift software sourcing to a totally new level. The concept of Software BOM (bill of materials) is at the core of the change. Software BOM should include all the cost related to the product lifecycle – from concepting to deployment and updates. Software decisions also have an indirect impact on hardware cost such as memory (size and quality) and boards (performance and availability), but in this blog series only direct BOM items are covered.

car

The automotive industry today has well-established practices for managing bill of materials. Actually, a typical car project is a fine oiled procurement process of well-defined specifications, bidding practices over multiple rounds and established supplier layers (called tiers). The fundamental idea behind the process is that a car can be departmentalized into small independent units and each unit’s cost can be minimized, resulting in an optimum total cost structure at the end of the day. This is a very good approach when all components are truly independent from each other and do not share anything in common.

A software component, however, has very little independency as everything is connected and often shared. Furthermore, great software is typically the result of several phases from user experience definition and development to final target optimization. Development in one component may have requirements on other components. Thus, software procurement must be seen as a system purchase and not as a component purchase.

There is a simple way to test whether an OEM is mastering Software BOM or not – by just asking one question at the start of production (SOP) ceremony: „What is the software cost per car for this model?“ A black belt is given when you get an answer consisting of a number and currency. All other answers should lead to a change how software decisions are being made.

Would you like to hear more about what is preventing optimized BOM for automotive OEMS. Stay tuned!

Tero Marjamäki
* www.theatlantic.com / cupholders are everywhere

The post From Trunk to Throttle – It’s Software that drives your car appeared first on Qt Blog.

Qt 3D Studio 2.2 Released

We are happy to announce that Qt 3D Studio 2.2 has been released. Qt 3D Studio is a design tool for creating 3D user interfaces and adding 3D content into Qt based applications.  With Qt 3D Studio you can easily define the 3D content look & feel, animations and user interface states. Please refer to earlier blog posts and documentation for more details on Qt 3D Studio.

New material system

One of the great new features in the Qt 3D Studio 2.2 release is the redesigned Material system. Applying material changes to several objects that share the same material can be now done by simply applying the changes to a single material.

New material system

Materials are now part of the Project View

The way that materials are applied when importing 3D models has been greatly improved. Materials are now part of the Project assets tree view and stored as a separate material definition files as part of the project file structure. This enables also sharing materials between projects. For details please refer to the Materials and Shaders documentation for details how to create and manage materials.

Scene View

Creating pixel perfect UI of course requires attention to detail and a lot of pixel peeping. The 2.2 release introduces a zoomable view for Scene Camera.

Scene Camera View

Scene Camera View

All Qt 3D Studio views are dockable so you can place the Scene view anywhere in the view layout or undock the view to a separate window.

Sub-Presentation Handling

We have done also great improvements to the Sub-Presentation management. Sub-Presentations are now part of the Project View which makes it easier to switch between sub-presentations and add sub-presentation content to the main presentation. Please refer to the documentation for details how to use Sub-Presentations in your project.

Compressed Textures

In Qt 3D Studio 2.1 runtime we introduced the compressed texture support in the runtime and now we have added an option to enable the compressed textures in the Editor Presentation settings. Doing the actual compression requires external tools (such as ETCPACK). In the future versions of Qt 3D Studio, we are introducing more integrated workflow for managing and optimizing the project assets.

Stereoscopic rendering (Technology Preview)

We are also excited to introduce Stereoscopic rendering as a new feature to the Qt 3D Studio runtime. Feature can be tested with the Viewer by enabling the Stereo Mode from the View menu.

Strereoscopic rendering

Enabling stereoscopic mode in the Viewer

Supported stereo modes are: Top-Bottom, Left-Right and Anaglyph rendering. Also eye separation can be increased/decreased from the menu. We will be introducing the QML API for controlling the stereo mode properties in the future releases.

Performance optimization for the runtime

We have been working hard to squeeze our more rendering performance from all kinds of embedded devices and the first set of changes are included in the 2.2 release. We consider these changes to be still experimental and for that reason the new rendering pipeline needs to be explicitly enabled when running the Qt 3D Studio based application. You can test the new rendering by setting Q3DS_DRAGON environment variable to 1. We will be getting more into details on what kind of performance improvements we have been seeing in our tests in a separate blog post. Stay tuned.

View3D QML element

In the QML API we have introduce a new View3D items which can be used to display the contents of a single Qt 3D Studio layer in a Qt Quick scene. This allows placing 3D objects in several places in Qt Quick Scene instead of one rectangular 3D view area. You can also do the Scene composition in the Qt Quick side.

Getting started

Qt 3D Studio 2.2 is available through Qt online installer under the Tools section. We also provide standalone offline installers which contain all you need to start designing Qt 3D Studio User Interfaces. Online installer also contains pre-build runtime for Qt 5.12 which is needed for developing Qt applications using Qt 3D Studio UI. Qt online installer and offline installers can be obtained from Qt Download page and commercial license holders can find the packages from Qt Account. Binary packages are available for Windows and Mac. For the first time we are also providing technology preview binary packages for Linux.

Instructions for building the editor & runtime please refer to the README file. If you are targeting for embedded systems with running e.g. RTOS you need to build the Qt 3D Studio runtime component for the target operating system. Qt 3D Studio runtime can be found from the git repository. If you are Qt for Device Creation Boot2Qt images the Qt 3D Studio Runtime and Viewer are included in the images. Please also note that Qt 3D Studio runtime uses Qt 3D module for rendering which means that Qt 3D Studio 2.2 requires Qt 5.12.

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.2 Released appeared first on Qt Blog.

QtCreator CMake for Android plugin

Santa Claus is coming to … wait a minute, it’s not Christmas yet!

I have the pleasure to let you know that KDAB has contributed to Qt with yet another super cool project!

It’s about QtCreator CMake for Android! I know it’s a strange coincidence between this article and The Qt Company’s decision to ditch QBS and use CMake for Qt 6, but I swear I started to work on this project *before* they announced it 🙂 ! This plugin enables painless experience when you want to create Android apps using Qt, CMake and QtCreator. It’s almost as easy as Android Qmake QtCreator plugin! The user will build, run & debug Qt on Android Apps as easy as it does with Qmake.

Before I go into the boring details, let’s see what the requirements are and, more importantly, when it will be available!

Requirements:

  • cmake 3.7 or newer (needed for server support in QtCreator)
  • NDKr18 or newer (only Clang and libc++ shared are supported)
  • Qt 5.12.1 (was too late for this patch to get in 5.12.0)

When will it be available? Well, I started the blog with the Santa on purpose, because, sadly, it’s too late to push it in QtCreator 4.8 and it will be available in the next version (4.9). If you can’t wait for QtCreator 4.9 and you like to try it sooner, you can apply this patch on top of QtCreator’s master branch.

Now back to technical details, in order to build your Qt Android application, this plugin must do some magic:

  • after it builds the C++ bits, it copies all the targets (DynamicLibraries) into “{build_folder}/android/libs/{arch}”
  • generates android_deployment_settings.json, which is needed by androiddeployqt tool

After this step, androiddeployqt will complete your Android Qt APK by copying all the Qt dependencies (libs & resources).

Last but not least, these are qmake features that you’ll not find in cmake:

  • IDE management for ANDROID_PACKAGE_SOURCE_DIR yes, it supports even the same naming as qmake. You’ll need to add the following piece of cmake script to your CMakeLists.txt file:
    if(ANDROID)
        set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android" CACHE INTERNAL "")
    endif()
    

    The CACHE is mandatory, otherwise QtCreator won’t see the variable and it won’t use it

  • IDE support ANDROID_EXTRA_LIBS, you’ll need to add the next piece of CMake script to your CMakeLists.txt file
    if(ANDROID)
        if (ANDROID_ABI STREQUAL "armeabi-v7a")
            set(ANDROID_EXTRA_LIBS ${CMAKE_CURRENT_SOURCE_DIR}/3rd-party/android_armeabi-v7a/ssl/libcrypto.so ${CMAKE_CURRENT_SOURCE_DIR}/3rd-party/android_armeabi-v7a/ssl/libssl.so CACHE INTERNAL "")
        endif()
    endif()
    

    The previous snippet will add libcrypto.so and libssl.so files ONLY for armeabi-v7a android ABI.

Note: KDAB offers training in CMake, including all the latest tips from our trainers, who are all active developers.

The post QtCreator CMake for Android plugin appeared first on KDAB.

Additional Device Creations targets available under Qt Account

We have enabled an improved ability to add new device creation targets to existing Qt releases outside of Qt release schedules. In practice this means, that Qt for Device Creation license holders can find additional embedded target support packages under their Qt Account downloads, additionally to those available under Qt Online Installer and Maintenance tool.

Qt Board Support Package overviewWe have had the ability to upload QBSP (Qt Board Support Package) in to Qt installation through the Maintenance tool for several releases already, but now all the necessary pieces for end to end support are coming together.

QBSP is file format having required toolchains, target hardware firmware, operating system, Qt and Boot to Qt demo application, required configurations for IDE (both Qt Creator and Microsoft Visual Studio) and all other necessary bits and pieces in one package. The QBSP makes adding new target hardware support for embedded developers super easy.

Qt Board Support Package downloads page In future, developers can find additional embedded target support packages, QBSP files for download under their Qt account (account.qt.io). Remember to first select your license (Qt for Device Creation), then product level filter for QBSP downloadables (Qt for Device Creation QBSP) and then the Qt release you are using (Qt 5.12.0 in the above picture).

The big benefit of this model is our ability to open up our delivery channel and QBSP creation for external parties  as well as remove dependency from Qt release schedules and available supported hardware for each release.

The post Additional Device Creations targets available under Qt Account appeared first on Qt Blog.

Cutelyst 2.6.0 released! Now on VCPKG and Buildroot

Cutelyst, a Qt Web Framework has upped to 2.6.0. This release if full of important bug fixes and is the best version when targeting Windows OS so far. It reached 5 years old, 440 stars on GitHub and since the last release has had many users asking questions, reporting issues and making pull requests.

Until now Windows support was a thing I mostly trusted Appveyor compiling and running tests fine, but this changed a bit in this release, I got a freelance job where some terminals would be editing images to be printed on T-Shirts, then they sent their art to a central server which receives and print, so, after I finished the QtQuick application and managed to convince them of running the terminals on KDE/Plasma as it was basically a kiosk full screen application I went on writing the server part.

Using Cutelyst on the server was a perfect match, the process was a Qt Widgets application, that, when linked to Cutelyst::WSGI could start listening all on the same process without issues, every terminal were connected via websockets protocol, which was just awesome, whenever I changed a terminal config I could see it changing instantly on the terminal, QWebSocketServer class could indeed do the same, but, to create the T-Shirt Art Fonts and Pictures needed to be "installed" on the terminal. Now with HTTP capabilities I simply exported all those folders and the whenever I sent a new JSON with config to the terminals, it contained the URLs of all these files which where updated in a blink.

On deploy time it was clear that using Windows on the server was a better option, first I'd need to give support for them on how to configure printers and use the system, also, printer drivers could also cause me troubles, so whatever let's just compile it and get the money.

In order to make things easier I managed to get VCPKG to build a Qt5 for me, in a command line fashion, after that I saw how easy it was to create a package for Cutelyst, it's upstream now, you just need to type:

vcpkg install cutelyst2

This will pull qt5-base package, and get you a working Cutelyst that easy, sadly Qt5 packages didn't work on Linux nor on MacOS (both with issues filled).

Thanks to this project, several Windows related issues have been fixed, still work to do but I have an app on production on Windows now :)

I'm still no Windows fan, so I ended up configuring MXE and cross compiling Cutelyst and my application for Windows on Linux with it.

If you are doing embedded stuff, Cutelyst is also available on buildroot.

Besides that Cutelyst 2.6.0 has some other very important bug fixes.

Get it here!

Qt 5.12 LTS Released

Just in time for the end of the year, we have released Qt 5.12 LTS today. This is a long-term-supported (LTS) release that we will support for 3 years to come. We have had a strong focus on quality and fixed more than 2000 bugs since the last Qt LTS version, Qt 5.9.7 – make that over 5000 bugfixes since Qt 5.6.3. Of course, this is only the start, and we will work hard on continuously improving the quality of Qt 5.12 in upcoming patches

Speaking about which, we have improved Qt’s performance and memory consumption, especially within the area of Qt 3D and the QML engine.

But like all major Qt releases, Qt 5.12 LTS also includes a lot of new features. Let’s have a look at some of them.

New modules and platforms

I’m really happy to announce that we will now fully support Qt for Python, making all of the Qt APIs available to Python developers. The tech preview is currently available for you to test, while the official release will follow shortly after Qt 5.12. Qt for Python originates from the PySide project that we have been hosting on qt-project.org for many years. Qt for Python supports most of Qt’s C++ APIs and makes them accessible to Python programmers. In short: Python developers now can also create complex graphical applications and user interfaces. You can find more details in the Qt for Python blog posts.

Qt 5.12 contains the second Technology Preview for Qt for WebAssembly. With Qt for WebAssembly, you can compile a Qt application to run in any modern Web browser. Even though Qt for WebAssembly is still marked as a Technology Preview, it is pretty functional, and we’d like to encourage you to give it a spin and provide feedback. You can find more details about it here.

In addition to supporting two new platforms with Python and WebAssembly, Qt 5.12 also adds full support for two modules, that have been available as Technology Previews in earlier versions:

Qt Remote Objects makes IPC between Qt based processes seamless. It allows exposing the properties, signals and slots of a QObject to another process, independent of where that process runs.

Similarly, the Qt WebGL Streaming Plugin is now also fully supported. This plugin lets you stream the user interface of applications to any modern browser over the network.

Qt QML and Qt Quick

With the new release, we have done some major improvements to the JavaScript engine supporting QML. It has been upgraded from being compatible with ECMAScript 5 to now fully support ECMAScript 7. This enables modern JavaScript and simplifies the integration of Javascript libraries. ECMAScript modules are now also supported and can be loaded both from C++ as well as QML/JS.

We’ve now added a TableView as another type of Item View in Qt Quick. It’s a lot more performant than its previous QQC1 implementation and is filling the last major gaps in our set of Views. Various controls in Qt Quick Controls 2 gained new methods or new functionalities.

The Pointer Handlers of Qt 5.11 are now renamed to Input Handlers and are fully supported as a first-class feature in Qt Quick. The Input Handlers simplify the creation of complex touch interactions, that used to be difficult to do with MouseArea and TouchArea alone. Two new Input Handlers for hovering and dragging items have also been added.

Qt Quick now supports pre-generating distance field textures. Those textures contain the glyphs required to render text in Qt Quick, and pre-generating them at compile time helps improve application startup performance especially on lower end embedded devices.

Qt Core and Network

Qt Core has gained support for CBOR (Concise Binary Object Representation), a binary format that is similar to JSON, but that allows for a lot more data types and flexibility.

We improved QRegularExpression to support wildcard matches, to let us deprecate the old QRegExp class.

In Qt Network, we added DTLS over UDP support. On macOS and iOS, we now support ALPN and HTTP/2 through the TransportSecurity backend, and we added PKCS#8 support in the generic SSL backend.

Qt Gui and Widgets

On Windows, we are now supporting Windows UI Automation, allowing Qt-based UWP applications to operate with accessibility and programmatic UI control tools. We replaced the tablet/touchscreen/touchpad/mouse input with a unified implementation based on the Windows Pointer Input Messages on Windows 8 and newer. Hardware, like the screen digitizer in the MS Surface line, is now supported without special drivers.

We added lots of predefined gradients for QGradient based on https://webgradients.com/. QImage received support for an RGBA64 image format with 16 bits per color channel. These can be read from PNG- and TIFF-based files and can be uploaded to or grabbed from OpenGL.

Also, did I mention the oodles of bugs we exterminated for Qt Widgets?

Other items

The virtual keyboard now supports 13 additional keyboard layouts as well as MyScript handwriting recognition. It now comes with a public extension API that allows you to define your own layout.

Qt Location now contains an updated MapBox plugin and several minor API enhancements. We have upgraded Qt WebEngine to be based on Chromium 69 and to gain support for client certificates.

Qt for Automation has now updated versions of the KNX and MQTT modules supporting newer protocol versions, and we added support for OPC/UA as a Technology Preview.

What’s more, upcoming Qt 3D Studio 2.2 Studio release will be based on Qt 5.12 LTS.

Finally, Qt 5.12 does also come with a new version of Qt Creator. You can find out all about its new features from a separate blog post.

Thanks

I’d like to thank everybody who has contributed to making Qt 5.12 possible. Special thanks go to KDAB for consistently being the largest contributor to Qt (outside of the Qt Company), Thiago Macieira for his work on maintaining Qt Core and Christian Ehrlicher who has been contributing a huge amount of changes to this release.

So, go ahead – download Qt 5.12 from your Qt Account or qt.io/download.  And join the upcoming live webinar with Live Q&A with Tuukka Turunen and myself.

Join Webinar: Meet Qt 5.12 LTS  on 11 December at 6 p.m. CET

 

The post Qt 5.12 LTS Released appeared first on Qt Blog.

Qt Creator 4.8.0 released

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

Programming Language Support

We have added experimental support for the Language Server Protocol (LSP), which adds basic support for various programming languages to Qt Creator.

Language Server Protocol support in Qt Creator 4.8

The Language Server Protocol is a standardized bridge between an editor or an IDE and a programming language. This makes it easy for a programming language to be supported by editors and IDEs: If it provides a server application that speaks this protocol, every editor that implements a language protocol client gains support for code completion, code navigation and code diagnostics for the programming language. And of course the other way round: An editor that implements a language protocol client automatically gains basic support for a various range of programming languages. There are language server implementations for many programming languages already. You can find lists of implementations and their state for example on the official LSP website and on a community driven site.

To set up a language server in Qt Creator, you first need to enable the LanguageClient plugin in Help > About Plugins (Qt Creator > About Plugins on macOS). Then open the language client options, add a language server executable, and specify the MIME type or glob patterns to open with that language server, and any arguments that the server needs to be passed on the command line.

Qt Creator currently supports code completion, highlighting of the symbol under cursor, and jumping to the symbol definition, and integrates diagnostics from the language server. Code highlighting is done through the generic highlighter, since the Language Server Protocol does not provide it.

C++ Support

We updated the Clang code model to LLVM 7.0. We also implemented Follow Symbol for the auto keyword, and completion tooltips now show the available overloads for the selected function. You can export the information that the code model has about your project as a compilation database with the new Build > Generate Compilation Database.

There are several new experimental plugins as well:

Compilation Database Projects

After enabling the CompilationDatabaseProjectManager plugin, you can open compilation databases as projects in Qt Creator. A compilation database is basically a list of files and the compiler flags that are used to compile them. Some build systems and tools are able to generate such databases for use in other tools. This can be an alternative to using a Generic Project, since it feeds better information about compiler flags and include paths to the code model.

Clang Format Based Indentation

Does auto-indentation via LibFormat which is the backend used by Clang Format. Enable the plugin ClangFormat to try it.

Cppcheck Diagnostics

Integrates diagnostics generated by the tool Cppcheck into the editor. Enable the plugin Cppcheck to try it.

Debugging

Qt Creator 4.8 supports simultaneously running multiple debuggers. The debugger tool bar in the Debug mode has an additional pop up menu where you can switch between running debugger instances and the “preset” view which allows to start new debuggers. Each running debugger instance also maintains its own set of views (Locals, Watches, Stack, etc) and their layout.

Get Qt Creator 4.8.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.8.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.8.0 released appeared first on Qt Blog.

Qt 5.11.3 Released with Important Security Updates

Qt 5.11.3 is released today. As a patch release it does not add any new functionality, but provides important bug fixes, security updates and other improvements.

Compared to Qt 5.11.2, the Qt 5.11.3 release provides fixes for over 100 bugs and it contains around 300 changes in total. For details of the most important changes, please check the Change files of Qt 5.11.3.

Qt 5.11.3 contains the following important security fixes:

All these security fixes are included in the upcoming Qt 5.12.0 release.

Qt 5.9.7 released earlier contains all the fixes, except the one for virtual keyboard, which is available as a set of patches here, here and here.

Qt 5.6.3 release can be patched with these security fixes available here, here, here, herehere, herehere and here.

Qt 5.11.3 is the last release of the Qt 5.11.x series. The 5.11 branch is now closed. All bug fixes go into Qt 5.12 and the most important ones are cherry picked into Qt 5.9 LTS.

The recommended way for getting Qt 5.11.3 is using the maintenance tool of the online installer. For new installations, please download latest online installer from Qt Account portal (commercial license holders) or from qt.io Download page (open source).

Offline packages are also available for those can’t use the online installer.

The post Qt 5.11.3 Released with Important Security Updates appeared first on Qt Blog.

Qt Lite updates for Yocto based Embedded Linux users

Yocto Embedded Linux based Boot to Qt images now directly support configurations created with Qt Configure Tool. Qt Lite is a concept and project for Qt supporting ever smaller devices and more nimble binaries. Small usually makes things also fast.

Qt Configuration Tool

New in Qt 5.12 LTS is much requested support for Yocto Embedded Linux based Boot to Qt images to be able to digest the Qt Configure Tool created Qt Lite configurations.

For details on what we have actually done, and how to use this new feature within your project please look in to post about How to use Qt Lite with Yocto.

The post Qt Lite updates for Yocto based Embedded Linux users appeared first on Qt Blog.

How to use Qt Lite with Yocto

During the development cycle of 5.12 we’ve been working on making it easier to use Qt Lite in Yocto builds, especially those using our meta-boot2qt layer.

Qt Configuration Tool now has the ability to export the set of selected Qt Lite features into files that can be used by the Yocto build to build a slimmer Qt.

Qt Configuration Tool is commercial-only and allows you visually explore and toggle different optional parts of Qt after opening an initially configured source tree. It can be used directly to configure that source tree for builds that don’t include features that you don’t need. That configuration can also be exported into a single file that can imported later, which makes sharing the configuration between people easier.

Previously there however wasn’t a clear path to using that in a Yocto-driven build, since meta-qt5 recipes build Qt module by module. New version 1.2 of the tool and the new qt5-features class in meta-boot2qt layer provide that. Both are available in Qt for Device Creation 5.12.

  1. Run ./configure for a qt5 source tree with the necessary options for your
    platform and choosing the commercial license.
  2. Open Qt Configuration Tool and select the build directory from the previous step.
  3. Select/unselect the features you want with the tool.
  4. When the configuration is ready, select “File” > “Export Features for
    Boot2Qt” and pick a folder. A feature file for each module that you’ve made
    changes to is created into that folder.
  5. In your yocto build, for each module that you have a feature file for:
    1. Create a new recipe extension for the module, e.g. “qtdeclarative_git.bbappend”.
    2. Add the line “inherit qt5-features” into that bbappend file.
    3. Put the feature file for the module (e.g. “qtdeclarative.opt”) into a
      features/ directory next to your bbappend file.

Then run your build (bitbake b2qt-embedded-qt5-image if you are basing your build on our example images) and enjoy the slimmer Qt made just for you!

The post How to use Qt Lite with Yocto appeared first on Qt Blog.

Support of Qt 5.6 LTS Ends in March 2019

Support of Qt 5.6 LTS ends in March 2019. If you are still with Qt 5.6 LTS, update to Qt 5.9 LTS or Qt 5.12 LTS is recommended. If you can’t update, extended support is available for an additional fee after the standard support ends. 

Long term supported releases on Qt are supported for three years, thus the support for Qt 5.6 LTS ends in March 2019. Many users have already migrated to later releases, especially to Qt 5.9 LTS. Soon we have also Qt 5.12 LTS available, so those who have not yet switched to more recent versions of Qt are encouraged to do so now.

Qt 5.6 LTS was the first long-term supported Qt 5 release. During its lifetime it has received three patch releases and provided over 2000 bug fixes compared to the earlier Qt 5.5.1 release. Qt 5.6 LTS has been in the ‘Very strict’ phase already quite a while and after Qt 5.6.3 release there have been very little commits to the 5.6 branch. Mostly just the critical security fixes. Qt 5.6.3 will remain the last release of the series, as there will not be any more Qt 5.6 patch releases created.

Qt 5.6 LTS has been a good release, but the more recent long-term supported Qt releases are even better. For example Qt 5.9.7, the latest patch release of Qt 5.9 LTS, contains over 3000 bug fixes that are not part of Qt 5.6.3. Currently in ‘Strict’ phase, Qt 5.9 will still receive new patch releases bringing security updates and other important fixes. The soon-to-be-released Qt 5.12 LTS contains over 2000 bug fixes that are not part of Qt 5.9.7 release – and over 5000 bug fixes more than Qt 5.6.3 release. Of course there are also a lot of great new features as well as performance improvements provided by the new versions of Qt.

If you can not switch to c++11 compiler or use a platform no longer supported after Qt 5.6 LTS, Extended support is available. Especially if your Qt 5.6 LTS based application or device is actively maintained after March 2019, purchasing extended support is highly recommended. Extended support can be purchased both for Standard as well as Premium Support. To learn more about Extended support, please contact our Support team and ask about it.

 

The post Support of Qt 5.6 LTS Ends in March 2019 appeared first on Qt Blog.

Handwriting, the essential input method for a successful User Experience

What is the aim of human-machine interfaces (HMI), if not to facilitate users in their primary tasks? Since 2011, MyScript has been conducting User Experience (UX) studies to define what users need to interact with their devices seamlessly.  In the case of cars, HMIs have greatly enhanced the driving experience, and many options are now available for drivers to enjoy their journeys behind the wheel. But no matter what car manufacturers’ focus is on, safety and reducing the driver’s distraction is always a top priority. MyScript’s studies for in-car UX revealed that drivers are not fully satisfied with a single input method and that on the road, handwriting is often the only solution that can clear out communication obstacles between users and their cars.

Along these lines, the Qt Virtual Keyboard offers to activate a handwriting recognition mode as an additional out-of-the-box input method solution.

qt-avenueMyScript focuses on user satisfaction to provide the best handwriting solution for car HMI. We leverage our artificial intelligence technology to adapt to the way people handwrite while driving: letters and/or fragments of words written in cursive or handprint, on top of each other or even without any spaces in between – our technology recognizes all these writing styles.

Critical situations where MyScript’s handwriting recognition (HWR) will be beneficial include:

When voice falls short

Voice control is a natural input method when conditions are good, but noisy environments, an unusual voice, speakers or microphones already taken by another action are some common situations where voice won’t do.

Plus, only handwriting has been authorized by U.S. regulatory bodies as an alternative to voice to interact with a car interface while driving. In the absence of it, drivers must stop the vehicle to use their keyboards.

For these reasons, manufacturers like Honda (Acura) or Audi have chosen our technology to equip their latest car models.

When touch surfaces are small­

Typing on small surfaces can be complicated and take time, while handwriting removes all frustrations. As a result, we power many connected devices with tiny surfaces, the smallest of all being the Samsung Galaxy Watch, with its one-inch display.

When mixing input types is inevitable

Use cases depend on the device, the form factor and the target field. As the Qt Virtual Keyboard offers different input modes (text, digits, emails with a variety keyboard layouts), MyScript can constrain its recognition engine, and therefore boost its accuracy by taking into account the context and the expected type of result.

Good news for developers, they can configure MyScript’s HWR as needed

MyScript’s handwriting recognition is totally flexible. Our engine relies on three main processes taking place simultaneously: symbol classification, segmentation and linguistic analysis. Information is exchanged between the three processes to find the most probable recognition result.qt-myscriptengine2

The symbol classification relies on the knowledge of the existing characters related to a text input. Developers select the language with an alphabet knowledge resource that defines the proper set of characters. They can also limit the number of characters with a subset knowledge resource.

The segmentation cuts or groups strokes together. Each group hypothesis is meant to match an existing symbol. For instance, it can group strokes to form a Chinese character or it can cut a single stroke in multiple characters in English cursive writing. In case of superimposed text, the segmentation unstacks strokes to form characters. Developers can configure the desired handwriting style with the appropriate alphabet knowledge resource.

The linguistic analysis relies on a set of words and grammars that rule the way the existing symbols can be combined to make up meaningful content. MyScript provides tools for developers to create specific linguistic knowledge resources that will match the expected use case e.g.: navigation, media, etc.

The combination of QT’s virtual keyboard with MyScript’s handwriting recognition technology offers the most efficient and adaptative IME. It is available for a total of 71 languages including all 40 languages offered in the Qt VK.

Have a project in mind? Start your own evaluation:

  • Download our contribution code and guidelines
  • Send us an e-mail at qt@myscript.com to get a MyScript Text SDK certificate with free access to our tools and support

The post Handwriting, the essential input method for a successful User Experience appeared first on Qt Blog.

Qt Visual Studio Tools 2.3.0 Released

A new development release of the Qt VS Tools, version 2.3.0, is now available to download in the the Qt download page.

Important changes include:

For details of what is included in this version, please refer to the change log.

This development release will not be published to the Visual Studio Marketplace. We will continue working on the upcoming official release, to be published to the VS Marketplace, which will include a few additional features and bug-fixes.

The post Qt Visual Studio Tools 2.3.0 Released appeared first on Qt Blog.

KDAB at Embedded Technology in Japan

Embedded Technology in Japan took place earlier this month and we are thrilled about our first participation in this event which attracted more than 400 exhibitors and over 25000 visitors.

We are also thankful to our partners SRA group and ISB Corporation for welcoming us heartily to their booths and for making this cultural experience possible.

IoT and embedded were at the center of the exhibition and we were proud to support our Japanese partners during the event by providing our expertise in C++, Qt and 3D.

If you couldn’t join us, here is some information about what we displayed :

– At the ISB Corporation booth

Nautical Navigation infotainment demo – our luxury sailboat dashboard demo

See our video here…

– At the Software Research Associates Inc. (SRA Group) booth

OPW mPro measuring station customer showcase for the management, monitoring and automation of precision measurement systems in the context of quality control.

See more here…

Finally both booths will show our brand new 3D product that we premiered there:

Kuesa is a product that provides an integrated and unified workflow for designers and developers to create, optimize and integrate real time 3D content in a 3D or hybrid 2D/3D Qt application. Kuesa includes plugins, tools and libraries that are available for both embedded and desktop applications.

Read more about Kuesa here…

Thanks to everybody who joined us there and see you next year!

The post KDAB at Embedded Technology in Japan appeared first on KDAB.

QtKnx: tutorial and updates

In this tutorial we will demonstrate how to write a KNX client requesting a local device management procedure to a KNX server. We will be using the QtKnx module that comes with the Automation package.

Sequence diagram

The following diagram presents the sequence of KNX messages exchanged between the client and the server.

no-title-2

The third message in the sequence contains the actual management procedure request. In this tutorial the client is initiating a property read request. It is not until the fifth message, that the client receives the property read confirmation encapsulated in a DEVICE_CONFIGURATION_REQUEST.

Server implementation

First, the server needs a QUdpSocket to listen for incoming connections from the KNX client.  We need to call the QUDPsocket::bind() operation to achieve the expected behavior. The server will listen on port 3671 and the client on 3672. Here is the server code for this part:

serverSocket = new QUdpSocket();
serverSocket->bind(QHostAddress("0.0.0.0"), 3671);

The server is now able to listen for incoming connections but the logic for processing incoming management messages is missing. Therefore, we need to connect to the QUdpSocket::readyRead signal that will be triggered every time a new datagram arrives on the bounded network interface. Translated into code this shall look something like this:

QObject::connect(serverSocket, &QUdpSocket::readyRead, 
    [&]() {
    while (serverSocket 
            && serverSocket->hasPendingDatagrams()) {
        auto datagram = serverSocket->receiveDatagram();
        auto data = QKnxByteArray::fromByteArray(datagram.data());
        auto knxNetIpframe = QKnxNetIpFrame::fromBytes(data);

        handleFrame(knxNetIpframe);
}
});

The function handleFrame used above contains the logic for managing KNX messages received. Simplifying the implementation it could look like this:

void handleFrame(QKnxNetIpFrame &frame) {
    switch (frame.serviceType()) {
        case QKnxNetIp::ServiceType::DisconnectResponse: {
            // ...
            break;
        }
        case QKnxNetIp::ServiceType::ConnectRequest: {
            // ...
            break;
        }
        case QKnxNetIp::ServiceType::DisconnectRequest: {
            // ...
            break;
        }
        case QKnxNetIp::ServiceType::DeviceConfigurationRequest: {
            // ...
            break;
        }
        case QKnxNetIp::ServiceType::DeviceConfigurationAcknowledge: {
            // ...
            break;
        }
        default:
        break;
    }
}

For example, when a disconnect request is received the server answers back with a disconnect response, at the same time the server terminates.

auto frame = QKnxNetIpDisconnectResponseProxy::builder()
            .setChannelId(200)
            .setStatus(QKnxNetIp::Error::None)
            .create();

serverSocket->writeDatagram(frame.bytes().toByteArray(),
                        QHostAddress(ipClient),
                        3672);

QCoreApplication::quit();

If a Connect Request arrives the server will respond with a Connect Response:

auto frame = QKnxNetIpConnectResponseProxy::builder()
            .setChannelId(200)
            .setStatus(QKnxNetIp::Error::None)
            .setDataEndpoint(
                QKnxNetIpHpaiProxy::builder()
                .setHostAddress(ipClient)
                .setPort(3672)
                .setHostProtocol(QKnxNetIp::HostProtocol::UDP_IPv4)
                .create())
            .setResponseData(
                QKnxNetIpCrdProxy::builder()
                .setConnectionType(QKnxNetIp::ConnectionType::DeviceManagement)
                .create())
            .create();

The property read is received within a device configuration request message. After acknowledging the property read the server can answer with a property read confirmation. This message is built like this :

auto responseFrame = QKnxDeviceManagementFrame::propertyReadBuilder()
                     .setObjectType(QKnxInterfaceObjectType::System::Device)
                     .setObjectInstance(1)
                     .setProperty(QKnxInterfaceObjectProperty::General::SerialNumber)
                     .setNumberOfElements(1)
                     .setStartIndex(1)
                     .createConfirmation(QKnxByteArray::fromHex("00027c04b550"));

The createConfirmation() method above, receives as parameter the serial number of the KNX server (“0x00027c04b550”).

Client implementation

Initially, the client needs an instance of QKnxNetIpDeviceManagement. This class abstracts us from having to create and handle the local device management connection.

QKnxNetIpDeviceManagement devManager;

When the devManager instance emits the connected signal the client will send the KNX property read frame. This is done here:

QObject::connect(&devManager, &QKnxNetIpDeviceManagement::connected,
    [&] () {
    auto frame = QKnxDeviceManagementFrame::propertyReadBuilder()
                .setObjectType(QKnxInterfaceObjectType::System::Device)
                .setObjectInstance(1)
                .setProperty(QKnxInterfaceObjectProperty::General::SerialNumber)
                .setNumberOfElements(1)
                .setStartIndex(1)
                .createRequest();
                devManager.sendFrame(frame);
});

The client establishes the connection to the KNX server by calling connectToHost() on the device management object instance. This call requires a QKnxNetIpHpai parameter that contains the ip and port of the server, as seen in this code:

QLatin1String ipLocal (ipClient);

devManager.setLocalAddress(QHostAddress(ipLocal));
devManager.setLocalPort(3671);

QLatin1String ipServer ("127.0.0.1");

devManager.connectToHost(QKnxNetIpHpaiProxy::builder()
                        .setHostAddress(QHostAddress(ipServer))
                        .setPort(3671)
                        .create());

 

QtKnx updates in 5.12

Stay tuned for the coming 5.12 release. This time it will come with a lot of
new changes:

  • Added support for KNXnet/IP Core v2: extending discovery functionality and support for secure communications using TCP.
  • Included support for KNXnet/IP Tunneling v2: added new structures, properties and messages.
  • Introduced a KNXnet/IP router class for supporting KNX routing. We also included a new example for it.
  • Enabled security configuration in IP sub networks over system broadcast communication mode.
  • Started enabling support for KNXnet/IP Security: encryption of KNXnet/IP traffic.
  • And lastly, we spend a great effort expanding the documentation with all the new features and examples.

Please give us your feedback!

The post QtKnx: tutorial and updates appeared first on Qt Blog.

KDAB Talks at Qt World Summit Berlin

KDAB is presenting two great talks at Qt World Summit. At 13:30, you can get an in-depth look at a new concept for designers and developers with James Turner.

At 14:30, Milian Wolff will be presenting some of KDAB’s renowned opensource tools, some of which, like Hotspot, he created himself.

Streamlined integration of 3D content straight from 3DS Max and Blender into Qt3D

with James Turner

Qt 3D is now established as the ideal 3D rendering engine for cross platform applications needing to integrate 3D content with 2D interfaces in a seamless way. The scene graph lets developers import and control geometry and materials, while the frame graph can be used to build advanced rendering  effects with ease.

 However, just as in the case of 2D content, best results are achieved when designers and developer share a common experience and toolset. Yet the tools used to author 3D scenes, the geometry, the materials, the lighting, the animations, are all very different from what most developers are familiar with.

In this talk, we introduce techniques and principles which make the collaboration between designers and developers smoother. We identify the major pain points and highlight tools and patterns for addressing each of them. We will look at data formats, model conditioning, runtime integration and rendering effects in order to produce compelling applications integrating 3D content with a traditional 2D interface.

We will illustrate all these concepts with a running example.

KDAB’s Opensource Tools for Qt

with Milian Wolff

Richard Feynman is considered one of the greatest physicists, largely because he was able to build lots of practical mathematical tools that greatly simplify the analysis of complex phenomena, thus making them accessible and useful to many.

KDAB maintains its position as the leading Qt consulting firm, partly because of the huge effort KDAB’s top-class engineers put into R&D projects to build great tooling for Qt applications. This tooling has helped countless other engineers solve bugs in their code, fix performance issues and prevent more problems from slipping into codebases.

The cherry on top of all this Qt goodness is that KDAB publishes its tooling under Opensource licenses!

Come to this talk if you want to discover how KDAB’s awesome Opensource Tools for Qt can help you.

View the full agenda here. Sign up for Qt World Summit here.

The post KDAB Talks at Qt World Summit Berlin appeared first on KDAB.

Qt Creator 4.8 RC released

We are happy to announce the release of Qt Creator 4.8 RC!

Find out about what is new in our blog post about the Beta. Please prefer using the bugtracker for reporting remaining issues.

Get Qt Creator 4.8 RC

The opensource version is available on the Qt download page, and you find commercially licensed packages on the Qt Account Portal. Qt Creator 4.8 RC is also available under Preview > Qt Creator 4.8.0-rc1 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.8 RC released appeared first on Qt Blog.

A Speed-Up for Charting on Embedded

I’d like to talk about a common problem that we have seen come up in several projects, namely how to plot large datasets over time in an efficient manner using Qt. This seems to be a general issue, especially in embedded situations and is affecting many people. Because of this, I thought we’d share one approach that we have found to work well in some situations, maybe it helps you out in your project.

Problem: Waveform Graphs of Large Data Sets

We have a situation where we are accumulating more than 500.000 samples of sensor data. The data is appended over time to a huge array.

We want to visualize this growing amount of sensor information as a waveform graph:

To intelligently render this on low-profile hardware, we cannot visit all the data points in a single render pass, but we need to cheat. Instead of drawing lines between all the hundreds of thousands of data points, we draw each vertical pixel column as one line reaching from the minimum sample to the maximum sample.

With this method, we only need to render a few hundred lines instead of hundreds of thousands to reach the same visual result.

To pull off this trick, however, we need to query minmax(beginIndex, endIndex) to obtain the range of values for which to draw a line very efficiently and very often. For this, I developed a MinMaxTree data structure which can offer high speeds for this query. The effective API of such a data structure can look like this:

template <class T> class MinMaxTree
{
public:
    explicit MinMaxTree();
 
    void append(T value);
    MinMax<T> getMinMaxInRange(size_t rangeBegin, size_t rangeEnd) const;
// ...
};

This API allows you to insert a single data sample to store new sensor data. It also lets you retrieve the minimum and maximum given begin and end indices, which we can then use to render a line in our waveform.

Crafting an Append-Only Min–Max Tree as a Search Index

Remembering computer science classes, I figured that reusing prior calculations can save a lot of work (dynamic programming). In addition, given very large data sets, trees can cut your query times tremendously by intelligently arranging data or—to put it differently—by allowing us to skip a vast amount of data quickly.

The solution I explain in this blog post uses both approaches at their best.

Here is the tree I modeled on top of the data:

The tree summarizes ranges of data points in the underlying array. I designed the tree nodes to contain the minimum and maximum values of their range. Since parent nodes represent the data of their left and right children, they contain the minimum and maximum of their combined ranges. Finally, the root node contains the minimum and maximum values of the entire data set.

Because I want to keep the tree small and profit from caching effects, each node represents a sub-range or “bucket” of the array. The bucket size can be adjusted to match the cache sizes of the hardware best. This keeps the tree flat while still enabling fast linear scans inside the bucket.

Appending a Value, Updating the tree

There are two tasks that come with insertion: updating the tree and, optionally, extending the tree.

When appending a value, it needs to update the overlying tree structure. When inserted, the value needs to find and update its respective tree leaf, which, in turn, must inform its parent node and so on. I hope that it’s easy to see that if a node’s minimum or maximum do not change, it does not need to inform its parent node. Using this optimization, the average-case complexity of insertion is very low. The code snippet below illustrates this recursive “bubbling up” of a value trough the tree:

template<T>;
void MinMaxTree<T>::bubbleUpMinMax(T value, size_t treeIndex)
{
    //updates and returns true, if we altered minmax in the node
    auto minmax = [&](T value) -> bool
    {
        auto &node = m_treeOntopOfBuckets.at(treeIndex);
        const auto oldmin = node.min;
        const auto oldmax = node.max;
        node.min = std::min(value, node.min);
        node.max = std::max(value, node.max);
        return (value < oldmin || value > oldmax);
    };
 
    //we are at the root, break recursion
    if (treeIndex == m_treeCapacity/2)
    {
        minmax(value);
        return;
    }
    //update node and optionally bubble up further
    else
    {
        if (minmax(value))
            bubbleUpMinMax(value, parent(treeIndex));
    }
}

The second problem when inserting a value is that our tree structure might need to grow, because the new value breaches the capacity of the existing tree. Here, the tree needs to extend “sideways” to leave its complete old structure intact and form a new node on top. For this, I

  1. double the trees size and mirror its current structure to extend its reach,
  2. make a new root,
  3. copy the data from the old root into the new root.

Now that we have doubled the tree size, we can again insert data until we need to expand again.

A note on the default values inside our nodes: I initialize all nodes with the highest possible value as minimum and lowest possible value as maximum.

template<T> MinMax{
    T min = std::numeric_limits<T>::max();
    T max = std::numeric_limits<T>::lowest(); 
    //it’s not ::min(), this costed me hours
};

So when actual real values enter the array, they will change min and max, because they are different to these default extremes.

BE WARNED! std::numeric_limits::min() represents the smallest positive representation of a value, not the lowest possible number. I learned it the hard way.

Indexing: Squeezing the Tree into an Array

In our case, I wanted to optimize the tree accesses and its growth without using a pointer implementation that would link a node to its children using pointers.

Instead, I adopted a commonly used trick to squeeze heaps into arrays, by letting the left child of an element be at 2 × index and the right child at 2 × index + 1. While it seems that I could have used this approach for this project as well, growing the tree would require me to insert and make space at many places. Instead, I went with an infix indexing method, putting the tree into an array in a “left node–root node–right node” order like this:

This is nice for several reasons:

  • It eliminates the need for the use of pointer chasing.
  • Nodes and their parents are fairly close (in the lower tree).
  • Expanding the tree is just doubling the array in size.
  • The root node will be in the middle of the array.

To have convenient ways of accessing rightChild and leftChild as well as the parentNode from a certain index, we have to look at the binary representation of our indices. Note how the parent index, for instance, always is the next higher “pure” power of 2. It would be a bit cumbersome to explain all the magic bit in text form, instead the code tells it best:

leftChild Find lowest set bit, unset it, and set the one-lower bit

template<T>
size_t MinMaxTree<T>::leftChild(size_t index) const
{
    int lsb = ffs(index);
    index &= ~(1UL << (lsb-1));
    index |= 1UL << (lsb-2);
    return index;
}

rightChild Find lowest set bit and set the one-lower bit

template<T>
size_t MinMaxTree<T>::leftChild(size_t index) const
{
    int lsb = ffs(index);
    index |= 1UL << (lsb-2);
    return index;
}

parentNode Find lowest set bit, unset it, and set the one-higher bit

template<T>
size_t MinMaxTree<T>::parent(size_t index) const
{
    int lsb = ffs(index);
    index &= ~(1UL << (lsb-1));
    index |= 1UL << lsb;
    return index;
}

All Functions use the glibc-provided intrinsic ffs, which can be found in <strings.h> (FindFirstSet to identify the lowest-significant set bit). On Windows, the intrinsic BitScanForward can be used to accomplish this. Similarly, I wrote a function to return the actual range in our data array a particular node covers.

Querying a Range

Now that we have all tools in hand, we can finally implement the range query itself.

We recursively query the tree nodes, starting from root downward. We check how a node’s range relates to our query range and query its children for the minimum and maximum, according to the following few cases:

Case 1: The node’s range is outside of  the query range → Return the uninitialized min/max.

Case 2: The node’s range is fully enclosed in the query range → That’s the best case, we just return the node’s min/max.

Case 3: The node’s range is partly inside, partly outside the query range or the node covers more than the range and we can split → Split, query left and right, and combine the results.

Case 4: The node’s range overlaps and we are at a leaf node → We need to scan through the bucket.

template<T>
MinMax<T>::queryNode(size_t nodeIndex, size_t rangeBegin, size_t rangeEnd) const
{
    // […] calculate Node Range, store in NodeBegin, NodeEnd  
 
    // node outside range, return empty MinMax()
    //               |------range----|
    //  |---node---|           or     |---node---|
    // this should never happen, but safe is safe
    if ((nodeEnd < rangeBegin) || (nodeBegin > rangeEnd))
        return MinMax<T>
 
    // range spans node fully, return nodes' MinMax
    // |---------range-----------|
    //      |------node------|
    if ((rangeBegin <= nodeBegin) && (rangeEnd >= nodeEnd))
        return m_treeOntopOfBuckets[nodeIndex];
 
    // node cuts range left or right or both
    //       |------range----|
    //  |---node---| or |---node---| or
    //     |--------node-------|
    if ((nodeBegin <= rangeBegin ) || (nodeEnd >= rangeEnd))
    {
        const MinMax<T> leftMinMax = queryNode(leftChild(nodeIndex), rangeBegin, rangeEnd);
        const MinMax<T> rightMinMax = queryNode(rightChild(nodeIndex), rangeBegin, rangeEnd);
        MinMax<T> resultMinMax;
        resultMinMax.min = std::min(rightMinMax.min, leftMinMax.min);
        resultMinMax.max = std::max(rightMinMax.max, leftMinMax.max);
        return resultMinMax;
    }
     
    // Node is leaf, re-scan its bucket for subrange
    //              |---------range-----------|
    //  |----node(leaf)----|   or   |----node(leaf)----|
    if( nodeIndex % 2 == 1)
    {
        MinMax<T> scanResult;
        for(size_t i = std::max(nodeBegin, rangeBegin); i <= std::min(nodeEnd, rangeEnd); i++)
        {
            scanResult.min = std::min(m_dataInBuckets[i], scanResult.min);
            scanResult.max = std::max(m_dataInBuckets[i], scanResult.max);
        }
        return scanResult;
    }
}

Results

Visualizing 300.000 data points took more than 2 seconds with the naïve approach (drawing lines from point to point) on the embedded test hardware, while this approach brought down the time for queries to about 3 ms, such that the pure line rendering now even accounts for the bigger part of the cost (6 ms). We again have reached levels below the juicy target of 16 ms.

Further Optimization: Find Lowest Common Parent

In a similar setup, my colleague James Turner found that many of our node visits actually were searching down the tree for the lowest common node covering the full range. In these cases, we often ended up splitting the node in its two children, one of which containing the range fully and the other not containing the range at all.

This initial search down the tree took most of the node visits, while the actual desired min max scan (collecting all the nodes containing the range) was less than that.

So instead of searching from the top, beginning at the root node, I now calculate the left and right leaves, then determine the lowest common node spanning the full range, and perform the query from there (which is a simple loop on bit operations).

I hope, you found this useful. I am happy to hear your comments about this solution. At KDAB, we do these kind of optimizations specific to low-end hardware all the time, ask us if we can help you or check out our Profiling Workshop to learn how to find and tackle performance bottlenecks in your own projects.

The post A Speed-Up for Charting on Embedded appeared first on KDAB.

Firebase Tutorial Android & iOS: Create an App with Realtime Database and Login

Mobile apps need a backend. They store settings & data, high scores, check licenses and generate statistics. All these use cases have one thing in common: they use a central database.

Coding a full-blown backend takes a lot of time. Think about end-to-end security, communication interfaces and database structure. When you then get to details like concurrent access, it gets tricky.

Luckily, Google Firebase takes care of all these issues for you. It’s a ready-to-use cloud-hosted database with full authentication support. In contrast to a traditional SQL database, Google Firebase stores JSON data sets (-> NoSQL). This gives you more flexibility in your data structure.

On top of that, you can subscribe to real-time data changes. You’ll get notified about updates made to the data, for example by other users. The service does offer a simple REST API. But the most efficient communication is a publish & subscribe model via websockets.

That sounds complicated? Google offers a separate SDK for each platform. With V-Play & Qt, you don’t need to worry about platform differences. V-Play includes a cross-platform Google Firebase Realtime Database plugin. The same QML / JavaScript-based API works for both Android & iOS.

Getting Started

In this Firebase tutorial, you’ll complete the full journey from start to end. You start with a project template of Qt Creator. Next, you’ll set up the Firebase service in the cloud. Another important task is user authentication. Most impressive: live database updates from & to your cross-platform app.

Firebase-Create-Entry

The scenario is a simple shopping list. It’s a generic app that includes everything most apps need. Authentication, plus adding, updating and deleting items. Once you understand the concepts, it’s easy to adapt them to your own scenario.

If you’re impatient, skip right to the final project source code on GitHub.

Watch this Tutorial on YouTube

You can also watch the video version of this tutorial on YouTube. It is very much in-depth and covers every single step of the process.

Master-Detail UI for your Cloud Backend

Curious to dive right into the cloud database? Well, you will need your “app package name” for Android and the “iOS bundle ID” when setting up Firebase.

Thus, start with the app and make your life easier. Open Qt Creator and create a new project. Use the “V-Play Apps” > “Master-Detail Application”. This gives you great boilerplate code for any list-type app.

master-detail-app-wizard

In step 2, choose the kits for the target platforms: Android and/or iOS.

Take special note of the “V-Play Project Properties” page (step 3). Here, you define the app identifier, which you will also need for the Firebase setup. In this case, choose com.vplay.ShoppingList.

new-app-wizard-3-project-properties-app-identifier

Google offers different Firebase samples for individual platforms & tools. With V-Play, you run the same code across Android & iOS. Activate the “Google Firebase” plugin. It includes ready-made cross-platform code to interact with the Google cloud!

new-app-wizard-4-google-firebase-support

Live Testing on Android & iOS

If you target both Android and iOS, you’ll want to test your app on both platforms. V-Play Live immediately deploys and executes any code changes on any connected phone. You can even connect and test on iOS phones while developing on Windows. You save an incredible amount of time: no more re-building, deploying and testing.

v-play-live-run-button

To get started, download the V-Play Live app from the app store: Android / iOS. Next, make sure your development computer and the phone are on the same local network. Start the V-Play Live app on your phone and connect it to your Live Server. If your Live Server is not running yet, click on “Live Run” in Qt Creator, to start developing with live code reloading!

V-Play Plugin License

Your app currently shows a watermark that you’re running a trial of the Firebase plugin. That’s fine for your first testing steps! To get rid of the trial watermark and the license reminders, you need the V-Play Indie license. If you do not have an Indie license, you can continue using the Firebase plugin in trial mode, without generating a license key.

Authorization works through a license key for your app. Go to https://v-play.net/upgradeLicense. Select the “Google Firebase” plugin. Next, click the green “Generate License Key” button at the bottom of the page.

firebase-plugin-license

Next, enter your app identifier (e.g., “com.vplay.ShoppingList”). The suggested version “1” is correct – it’s the default in every new project.

v-play-license-key

Copy the new license key to your code, add it to the licenseKey property in your Main.qml file. The watermark disappears. This video shows the original Master-Detail sample app. When inserting the license key to the code, the app instantly reloads – without the watermark. Afterwards, you see a brief demo of the initial app functionality.

mater-detail-app-add-license-key

Create the Firebase Project

Congratulations, your master-detail app is running on the phone! Now, it’s time to create the Google Firebase Realtime database. This serves as complete lightweight backend for the shopping list example app.

To create a Firebase account, go to the Firebase homepage. Login with your Google Account to see the empty console. The project you create runs great with the free account. You don’t need to worry about payments.

First, click on “Add project”.

firebase-console-new-project

Give your project a name to recognize it in your console: “ShoppingList”. The “Project ID” is auto-generated with a number, as it needs to be globally unique. You can customize the ID if you like. Note that your users will never see this ID, though – so don’t spend too much time here.

firebase-new-project-wizard-shoppinglist

Click on “CREATE PROJECT”. In a few seconds, the project dashboard greets you with the overview:

firebase-dashboard-shoppinglist-qt

Connect Your App to Firebase

Your shopping list app stores the items in the cloud. Grant your app access to the Firebase project. Click on the big circle for your target platform: iOS or Android.

Enter the package name again. The optional “app nickname” is only for internal use inside your dashboard.

firebase-register-android-app

The Firebase wizard now prompts to download the config file. Download this file and store it somewhere on your computer.

firebase-console-new-project-config-file

The major parts of the config file look like this. They contain all the information you need to connect your app to Firebase.

{
  "project_info": {
    "project_number": "766025596428",
    "firebase_url": "https://shoppinglist-vplay.firebaseio.com",
    "project_id": "shoppinglist-vplay",
    "storage_bucket": "shoppinglist-vplay.appspot.com"
  },
  "client": [
    {
      "client_info": {
        "mobilesdk_app_id": "1:766000006428:android:a28d200000001c88",
        "android_client_info": {
          "package_name": "com.vplay.ShoppingList"
        }
      },
      "api_key": [
        {
          "current_key": "AIzaSyCvAzxxxxxxxxxxxxxxxxxEXg-cv8TikY0"
        }
      ]
    }
  ],
  "configuration_version": "1"
}

For your V-Play project, you could use this config file. But it’s easier to copy the API keys to the plugin config, as you will see below. So, skip steps 3 + 4 of the Firebase wizard.

In Qt Creator’s “Projects” view, right-click the “qml” folder. Select “Add new…”. Choose the “V-Play Apps” -> “Item” template.

firebase-data-model

In the following “Item details” dialog, enter:

  • File name: DataModel
  • Path: create a new sub-folder in your project’s qml folder, called “model”

The generated file is almost empty. Change the default generated ID from “item” to “dataModel”. As you are using the Firebase plugin, add the following line to the import section at the beginning of the file:

import VPlayPlugins 1.0

The FirebaseConfig QML element encapsulates all connection settings – for both Android and iOS. Add it to your item. Your data model now looks like this:

import VPlayApps 1.0
import QtQuick 2.0
import VPlayPlugins 1.0

Item {
  id: dataModel

  FirebaseConfig {
    id: fbConfig

    projectId: "<your project ID, from project_info | project_number, e.g., 82701038584 or shoppinglist-vplay>"
    databaseUrl: "<your database URL, from project_info | firebase_url, e.g.,: https://shoppinglist-vplay.firebaseio.com>"

    apiKey: Qt.platform.os === "android"
            ? "<your Android API key, from client | api_key | current_key>"
            : "<your iOS API key>"

    applicationId: Qt.platform.os === "android"
                   ? "<your Android application ID, from client | client_info | mobilesdk_app_id>"
                   : "<your iOS application ID>"
  }
}

Firebase Database Setup

Your app will store a list of items in the database. Firebase is a JSON-based NoSQL database. What does it do?

This is what your database will look like:

database-structure

The database is a tree of items. Each can have children and any structure. That makes the database much more flexible than tables in traditional SQL.

Some of the structure is pre-defined by Firebase; some is coming from your app. A quick overview, before you dive in:

  1. shoppinglist-vplay: the root node of the entire database (shown in yellow).
  2. users: each user is going to have a private shopping list. After all, you don’t want to buy items that a stranger added, right? Thus, the next node is “users”. It contains a list of user UIDs. The database itself doesn’t store any further information about the user’s identity. You can look this up in the “Authentication” section of your Firebase project dashboard:
    firebase-authentication-user-list
  3. shoppinglist-user: the root node of the individual shopping list. This is what a logged-in user sees. It contains several items, one for each item to buy. Here, it’s currently milk and apples.

Create the Cloud Database

In your browser, return to the Firebase dashboard. Select “Database” on the left. Next, click on “Get Started” in the “Realtime Database” block. The Cloud Firestore is currently still in beta. That’s why it’s not recommended for production use yet. We will take a closer look in a future tutorial.

firebase-create-new-realtime-database

Next up is the “Security rules for Realtime Database” dialog. It’s a good idea to start with proper authentication right away, instead of plugging it in later.

Firebase Authentication

Your app needs to recognize, differentiate and securely authorize users. The Firebase Authentication service makes this easy. It supports multiple authorization providers: Facebook, Google Account, Twitter, GitHub and even a phone-based user authentication per SMS.

Firebase even lets you use “anonymous” authentication. This means the user does not have to do any authentication step in order to use the Firebase Database.

To get started, we will use the Email / Password variant. Firebase takes care of managing users and even supports sending password reset emails.

To activate it, go to the Authentication section (1) of your Firebase dashboard.

firebase-authentication-sign-in-provider

Next, choose “Sign-In Method” (2). Click on “Email/Password” (3) to expand this section. Enable it (4) and save the changes (5). In the “Templates” section, you could further customize the behavior. E.g., a custom confirmation email text when a user signs up.

Firebase Login from Your Client App: Architecture

V-Play simplifies the authentication process. The engine includes a predefined item FirebaseAuth that handles the cloud communication.

The app architecture is clear:

  • The App is the main QML item that owns all the other items and ensures they communicate with each other
  • DataModel is a direct child of the App. It is a layer that handles the authentication and shopping items (your data). It abstracts the Google Firebase. The rest of your application does not need to worry about the backend or any cloud communication.
    Its onLoggedIn slot triggers navigating from the LoginPage to the ShoppingListPage.
    • FirebaseAuth is an item provided by V-Play. It communicates with the Firebase cloud. It provides convenient signals and slots. These integrate the relevant events into your app.
    • FirebaseConfig is what we’ve already created. It contains basic settings, like the API key, configuration, …
  • NavigationStack handles all the visible pages.
    • LoginPage is initially visible. It contains the user interface to enter username and password. Plus, you can trigger new user registrations for the Firebase backend.
      Its onLogin slot executes when the user taps the button to login / register.
    • ShoppingListPage shows all the shopping items, which you’ll retrieve from the Firebase database. It is only visible after successful authentication.

Google-Firebase-Authentication-Architecture-Qt-Qml

Firebase Authentication: Callbacks from the Cloud

You start by adding the FirebaseAuth item to your DataModel. It is simple to use: assign an ID and give it a reference to the config item you created before. Also, add two signals (“loggedIn”, “loggedOut”) to your DataModel. They inform the app about the user’s login status.

signal loggedIn
signal loggedOut

FirebaseAuth {
  id: auth
  config: fbConfig

  onLoggedIn: {
    if(!success) nativeUtils.displayMessageBox(qsTr("Login failed"), qsTr("Reason: %1").arg(message), 1)
  }
  onUserRegistered: {
    if(!success) nativeUtils.displayMessageBox(qsTr("Register failed"), qsTr("Reason: %1").arg(message), 1)
  }

  onAuthenticatedChanged: if(authenticated) dataModel.loggedIn()
}

FirebaseAuth offers three important slots for reacting to cloud responses:

  1. onLoggedIn: fired after the loginUser request has finished. This is a good place for you to check if there was an issue with the login.
  2. onUserRegistered: like the login, but for a finished registerUser request.
  3. onAuthenticationChanged: the most important status change: is the user logged in? With this generic slot, your app is flexible no matter how the user logged in. All that matters is if he is logged in at the end. In that case, our DataModel emits the loggedIn signal to let the app switch to the main data model page.

Firebase: Triggering Login, User Registration and Logout

Now, your app already handles the status change responses coming from Firebase. But, you still need to trigger the login! The FirebaseAuth item includes convenient methods for triggering authentication tasks.

Your DataModel.qml encapsulates the communication with Firebase. So, you include simple methods that forward the requests to Firebase.

function registerUser(email, password) {
  auth.registerUser(email, password)
}

function loginUser(email, password) {
  auth.loginUser(email, password)
}

function logoutUser() {
  // logout is instant and always works (there is no callback)
  auth.logoutUser()
}

You might wonder why you should do this. After all, the new methods are an exact replica of the existing. Once you expand your app, you might want to surround these calls with extra checks. E.g., you could test if the email address is valid. So, it’s a good idea to think of a good architecture right from the start.

Firebase Login Flow in the App

The example app already includes two sample pages for Firebase, which we will not use however. They are a concise essence of what you can do with Firebase. In our sample, we use Firebase as part of the complete app architecture.

Create a new page: LoginPage.qml. It’s will be a simple page with 2 text boxes and a button. A checkbox switches between login and new user registration. Copy the source code from the GitHub sample into your new page.

Important for the concept is that the page emits a signal once the user taps the button: “login(bool isRegister, string email, string password)”. The parameters include everything Firebase needs to perform the login.

Main.qml wires this signal to your DataModel. This connection establishes the link from the UI to the Firebase cloud. Replace the current contents of Main.qml with:

import VPlayApps 1.0
import QtQuick 2.5
import "model"

App {
  id: app
  licenseKey: "<The V-Play Plugin license key you generated earlier>"

  DataModel {
    id: dataModel
    onLoggedIn: stack.push(shoppingListPage)
  }

  NavigationStack {
    id: stack
  
    LoginPage {
      id: loginPage
  
      onLogin: {
        if(isRegister) {
          // Call the user registration method from our data model,
          // which then forwards the request to Google Firebase
          dataModel.registerUser(email, password)
        } else {
          // Similar approach sending a user login request to Firebase.
          dataModel.loginUser(email, password)
        }
      }
    }
  }

  Component {
    id: shoppingListPage
    MasterPage {
      // User navigated back in the UI - send logout request to Firebase
      onPopped: dataModel.logoutUser()
    }
  }
}

In the code snippet above, you see that the App also owns the DataModel item with id “dataModel”. The “App” item connects your app’s components. Here, you establish a direct connection: LoginPage’s “onLogin”-slot -> methods of the DataModel (registerUser / loginUser).

Once the login process completes, the “onLoggedIn” slot within the DataModel pushes the “shoppingListPage” to the navigation stack. Remember: that’s the ID of the MasterPage from the template.

With this approach, navigating back in the Android / iPhone-UI pops the page. This automatically triggers the logout process in Firebase. Your app also returns to the previous page on the navigation stack – the LoginPage.

Test your app! You can already register a new user in Google Firebase and log in:

firebase-app-login

Firebase Realtime Database & Pricing

The Firebase Realtime Database is a NoSQL DB. It’s efficient and low-latency, and especially targeted towards mobile clients.

The Realtime Database stores all data in a JSON tree. Unlike a SQL database, there are no tables and rows. That makes Firebase efficient for simple and rather flat data. It’s the ideal target for many apps, like our shopping list example.

What about pricing? You get charged for bandwidth and storage. The free “Spark Plan” already grants you 100 simultaneous connections, 1 GB of data storage and 10 GB / month data transfer. Upgrades to the “Flame Plan” and the “Blaze Plan” give you even more data allowance. Google has a good comparison table, highlighting the differences between different Firebase plans.

Firebase Database Structure & Live Updates

The following video shows a screen recording of what’s happening behind the scenes:

  1. Left: A new user registers. You see his identifier (the email address). It’s linked to a unique UID (“lC27Aha…”).
  2. Right: Then, the user adds two items to his shopping list: Milk and Apples. Each change made by a client flashes in color – in real-time!

Firebase-Register-New-User-Create-Database-Entry

The hierarchy of the JSON model is as follows:

  1. shoppinglist-vplay: root node of your database. Its name is the project ID you used when creating the Firebase project.
  2. users: added through the authentication part. Keeps data separate for each registered user. The key is the UID of the user. The database itself doesn’t contain the email-address of the user.
  3. shoppinglist-user: root database key, accessible by the individual logged in user. The name is set by the application, as you will do in the next step.
  4. <JSON entries>: in the shopping list scenario, you can use the timestamp as the unique key. The node contains two children:
    1. Timestamp (where you could save the last modification time)
    2. Actual item to buy (string)

This is the default hierarchy, based on customizable rules. But, you have full control to customize every aspect.

Connect to the Firebase Realtime Database

The interface to Firebase is powerful. All connected clients get real-time updates. Plus, it offers full offline-support. When the user goes online again, the changes sync to the cloud.

V-Play includes a single item that works across Android and iOS. Especially for multi-platform scenarios, you’ll love this.

The FirebaseDatabase QML type offers methods to retrieve and update the JSON tree in the Firebase cloud. Callbacks inform you whenever the items changed and when operations complete.

In your app architecture, you set up a data flow from the user interface to the Firebase database in the cloud:

Firebase-Realtime-Database-Add-Data

A “+” button in the navigation bar (1) triggers an input dialog (2). It sends the new shopping item name to the DataModel. The DataModel abstracts the Firebase Realtime database (3). The FirebaseDatabase item from V-Play performs the cloud interaction (4).

Whenever the model data in the cloud changes, your app gets a callback (5). This updates the cached list of shopping items (6).

Firebase Database Configuration & Item Storage

Add the following code snippet to your DataModel:

// Stores a list of all shopping items for the user
property var shoppingItems: ({})

// Name of the root node for the user's shopping items in the Firebase database
readonly property string dbKeyAllShoppingItems: "shoppinglist-user"

FirebaseDatabase {
  id: database
  config: fbConfig

  realtimeUserValueKeys: [dbKeyAllShoppingItems]

  // If the last shopping item gets deleted, the database returns null
  // the plugin then gives success==false, so don't check the success parameter
  onRealtimeUserValueChanged: if(key === dbKeyAllShoppingItems) shoppingItemsLoaded(value)
  onFirebaseReady: console.log("db ready")
  onWriteCompleted: console.log("write completed")
}

function shoppingItemsLoaded(value) {
  // When the last item is deleted, firebase deletes the whole structure, returning null
  dataModel.shoppingItems = value || {}
  console.log(JSON.stringify(dataModel.shoppingItems))
}

The FirebaseDatabase item (with id database) requires a reference (config) to the generic Firebase connection configuration item with your app keys.

Firebase Realtime Updates

Your app registers for real time updates by adding keys to the realtimeUserValueKeys property.

The realtimeUserValueChanged signal fires every time the monitored keys change. E.g., by another family member sharing your shopping list account. The signal is also emitted when the connection to the database is ready after a successful login. So, it’s the only method we need to retrieve & update the shopping list items!

The shoppingItemsLoaded(value) function then assigns the items to a public property of the DataModel. It also ensures the list never gets null by using an empty array “{}” in case no shopping items have been created so far.

For debugging, you can print the raw JSON data to the console. During development, this helps to see what Firebase transmits to your app. In the video example above, this would be:

{"1529230812085":{"date":1529230812085,"text":"Milk"},"1529230821894":{"date":1529230821894,"text":"Apples"}}

Prepare the Shopping List Page (MasterPage)

The V-Play wizard already created the basic structure of a master list / detail app. You can use this as a base for customizing it to the shopping list scenario.

You need the following functionality:

  • List of shopping items
    • Tap an item to navigate to the detail page. You can edit the item there.
    • Swipe the item to the left to reveal the delete button.
  • “Add” (+) button. Creates a new shopping item.

Add Shopping Items

You assign the keys of the dataModel.shoppingItems array as the model for the list view. The “ListPage” instantiates rows for each item in the model.

The minimal code of the MasterPage:

import VPlayApps 1.0
import QtQuick 2.5
ListPage {
  id: masterPage
  title: qsTr("Shopping Items")
  
  model: Object.keys(dataModel.shoppingItems)
  
  signal addNewShoppingItem(string text)
  
  rightBarItem: IconButtonBarItem {
    icon: IconType.plus
      
    onClicked: {
      InputDialog.inputTextSingleLine(app,
        "What to add to the list?", // message text
        "Input here",               // placeholder text
        function(ok, text) {
          if(ok) {
            masterPage.addNewShoppingItem(text)
          }
        })
    }
  }
}

You start with adding shopping items to your Firebase Realtime Database. The “+” button appears in the navigation bar. You achieve this through the rightBarItem, provided by the base Page QML type. Make your life even easier by using the predefined IconType.plus symbol. Thanks to V-Play’s multi-platform support, the button is always placed in the correct screen area for Android and iOS.

To enjoy even more pre-built functionality, use the ListPage QML type as base item of this QML file. “ListPage” derives from the more generic Page type. On top of the generic Page, it includes a full-screen AppListView item. It’ll contain all your shopping items. Plus, it even offers advanced features like fully-animated pull-to-refresh.

When the user taps the “+” button, your app shows a simple single-line text entry dialog (InputDialog).

Store Shopping Items in the Firebase Realtime Database

For a good architecture, you send the user’s new shopping item via a signal to the DataModel. So, define a signal addNewShoppingItem(string text) in the ListPage (with id masterPage). The callback function of the InputDialog then emits the signal. It sends the text entered by the user as parameter.

Now, connect the MasterPage’s signal to the DataModel’s slot. Like before for the login, define it in Main.qml. Extend your previous MasterPage definition in Main.qml:

Component {
  id: shoppingListPage
  MasterPage {
    onAddNewShoppingItem: dataModel.addShoppingItem(text)
    // User navigated back in the UI - send logout request to Firebase
    onPopped: dataModel.logoutUser()
  }
}

Again, the most interesting code is in DataModel. It stores the new shopping item in the Firebase Realtime Database. Add this method to your DataModel:

function addShoppingItem(text) {
  var time = new Date().getTime()
  var shoppingItem = {
    date: time,
    text: text
  }
  console.log("Adding item...")
  // Use date milliseconds as unique ID in DB
  database.setUserValue(dbKeyAllShoppingItems + "/" + time, shoppingItem, loadingFinished)
}

function loadingFinished() {
  console.log("Loading finished")
}

The addShoppingItem function constructs an object “shoppingItem”. The method database.setUserValue() serializes it to JSON. Next, it’s sent to the Firebase database in the cloud. The setUserValue() method has three parameters:

  1. The root node in the user’s JSON tree is “shoppinglist-user”. As the key, you can re-use the time stamp; you can be certain that it’s a unique identifier.
  2. Contains the key/value pairs to store in the database.
  3. Your simple shopping list app doesn’t show that an operation is in progress. You could activate an animation when you send the data. Stop it again when you receive the loadingFinished callback. To get started, log the info to the console.

List Shopping Items in Your App

Your app already adds items to the real time database in the cloud. The last major feature is the UI to show the shopping items!

Back in MasterPage.qml, extend the code of ListPage with a delegate. The delegate instantiates for each individual item in your shopping list.

delegate: SwipeOptionsContainer {
  id: container

  // modelData == key of shopping item in data model
  readonly property var shoppingItem: dataModel.shoppingItems[modelData] || {}

  SimpleRow {
    width: parent.width

    text: container.shoppingItem.text || ""
    detailText: new Date(container.shoppingItem.date).toLocaleString() || ""
  }
}

The SwipeOptionsContainer QML item supports swipeable list rows in Android and iOS apps. In the next step, you will add the feature to delete the item through the swipe gesture.

Usually, list items have a very simple structure: one or two lines of text, plus an optional image. The V-Play item SimpleRow provides a ready-made layout. The three corresponding properties are: text, detailText and icon.

There’s one simple trick you need to be aware of. How to access the entire individual properties of the currently shown item? The model you assigned to the ListPage only contained the keys. But, the line needs to access the full data of the shopping item! This includes the name and the date.

Where can you get the complete data? It’s stored in the DataModel. Thus, you access it based on the key stored in the list view model. The relevant item data is then available through the readonly property shoppingItem. Its declaration is part of the delegate you inserted a moment ago. This is the relevant line, for reference:

readonly property var shoppingItem: dataModel.shoppingItems[modelData] || {}

Here, you see your app in action:

Firebase-Create-Entry

After the user logs in to the app on the phone, he adds an item with the text “V-Play” to the shopping items list. Thanks to the real-time database features, the item immediately appears in the web view. Google highlights it in green to make you aware of the change.

Even more amazing: real-time changes also work in the other direction. Try deleting a shopping item in the database view on the web. It’ll immediately disappear on the smartphone. No extra code was necessary. In DataModel, V-Play’s FirebaseDatabase item emits a signal every time the remote database changes. In your app, you reload the data based on its new contents.

Delete Items from the NoSQL Firebase Database

Your app already handles real-time updates from the web. Now, the final extension for you to write: let the user delete the shopping items from the phone!

The SwipeOptionsContainer for the ListPage items contains useful out-of-the-box functionality. Like many other advanced apps, users can swipe the item to a side. In your QML, you specify the item to appear. In this case, choose a SwipeButton with red background color and an “X” icon. Now, whenever the user swipes and clicks on the delete button, its onClicked slot executes.

rightOption: SwipeButton {
  anchors.fill: parent

  backgroundColor: "red"
  icon: IconType.remove

  // Date is also the unique ID
  onClicked: {
    container.hideOptions()
    masterPage.deleteShoppingItem(container.shoppingItem.date)
  }
}

In the onClicked slot, you must inform the real-time database about the deleted item. For this, add a second new signal for the ListPage item in the MasterPage:

signal deleteShoppingItem(real id)

As parameter, your code sends the ID of the item to delete. Remember – we used the creation date as unique ID!

The app must forward the signal to the data model. This architecture keeps the view separated from the model. So, extend the MasterPage component in Main.qml to forward the signal. For reference, this is what the complete component definition looks like now:

Component {
  id: shoppingListPage
  MasterPage {
    onAddNewShoppingItem: dataModel.addShoppingItem(text)
    onDeleteShoppingItem: dataModel.deleteShoppingItem(id)
    // User navigated back in the UI - send logout request to Firebase
    onPopped: dataModel.logoutUser()
  }
}

Like adding a shopping item, the signal triggers a JavaScript function in the data model. To stick to the naming scheme, call it deleteShoppingItem(id).

As a final step, jump into DataModel.qml and add the function implementation. It’s only one line and resembles the call to add an item. The only difference: instead of setting the item data as value in the database, you now send null. The result: the item is deleted.

function deleteShoppingItem(id) {
  database.setUserValue(dbKeyAllShoppingItems + "/" + id, null, loadingFinished)
}

The animation below shows how deleting item on the phone works. Again, the left side shows the real-time database view of Firebase on the web. Items instantly disappear in the web view when the user has deleted them on the phone.

Firebase-Delete-Entry-VPlay-Qt

Going Further

Your cross-platform shopping list app is powerful:

  • It features an efficient UI to create new items.
  • Delete items through an intuitive swipe gesture.
  • All changes immediately sync to & from the cloud database.
  • Share the login with your family. Everyone will be up-to-date.

For shopping lists, it’s not needed too often. But, for other use cases you might also want to include functionality to edit items. As a bonus, we’ve added the necessary code to the full example on GitHub. Check it out to see how modifying existing items works! Also, the open source example is a great reference, as it includes extra code comments.

By combining the Firebase real-time database with Qt and V-Play, you gain support for user authentication and shared NoSQL-databases with a few lines of code. If you’d also like to store larger files in the cloud, check out the FirebaseStorage QML type.

 

 

 

More Posts Like This

 

qt-machinelearning-tensorflow-Teaser
Machine Learning: Add Image Classification for iOS and Android with Qt and TensorFlow

Qt AR: Why and How to Add Augmented Reality to Your Mobile App
Qt AR: Why and How to Add Augmented Reality to Your Mobile App

vplay-2-17-0-firebase-cloud-storage-downloadable-resources-and-more
Release 2.17.0: Firebase Cloud Storage, Downloadable Resources at Runtime and Native File Access on All Platforms

The post Firebase Tutorial Android & iOS: Create an App with Realtime Database and Login appeared first on V-Play Engine.

Composing AST Matchers in clang-tidy

When creating clang-tidy checks, it is common to extract parts of AST Matcher expressions to local variables. I expanded on this in a previous blog.

auto nonAwesomeFunction = functionDecl(
  unless(matchesName("^::awesome_"))
  );

Finder->addMatcher(
  nonAwesomeFunction.bind("addAwesomePrefix")
  , this);

Finder->addMatcher(
  callExpr(callee(nonAwesomeFunction)).bind("addAwesomePrefix")
  , this);

Use of such variables establishes an emergent extension API for re-use in the checks, or in multiple checks you create which share matcher requirements.

When attempting to match items inside a ForStmt for example, we might encounter the difference in the AST depending on whether braces are used or not.

#include <vector>

void foo()
{
    std::vector<int> vec;
    int c = 0;
    for (int i = 0; i < 100; ++i)
        vec.push_back(i);

    for (int i = 0; i < 100; ++i) {
        vec.push_back(i);
    }
}

In this case, we wish to match the push_back method inside a ForStmt body. The body item might be a CompoundStmt or the CallExpr we wish to match. We can match both cases with the anyOf matcher.

auto pushbackcall = callExpr(callee(functionDecl(hasName("push_back"))));

Finder->addMatcher(
    forStmt(
        hasBody(anyOf(
            pushbackcall.bind("port_call"), 
            compoundStmt(has(pushbackcall.bind("port_call")))
            ))
        )
    , this);

Having to list the pushbackcall twice in the matcher is suboptimal. We ca do better by defining a new API function which we can use in AST Matcher expressions:

auto hasIgnoringBraces = [](auto const& Matcher)
{
    return anyOf(
        Matcher, 
        compoundStmt(has(Matcher))
        );
};

With this in hand, we can simplify the original expression:

auto pushbackcall = callExpr(callee(functionDecl(hasName("push_back"))));

Finder->addMatcher(
    forStmt(
        hasBody(hasIgnoringBraces(
            pushbackcall.bind("port_call")
            ))
        ) 
    , this);

This pattern of defining AST Matcher API using a lambda function finds use in other contexts. For example, sometimes we want to find and bind to an AST node if it is present, ignoring its absense if is not present.

For example, consider wishing to match struct declarations and match a copy constructor if present:

struct A
{
};

struct B
{
    B(B const&);
};

We can match the AST with the anyOf() and anything() matchers.

Finder->addMatcher(
    cxxRecordDecl(anyOf(
        hasMethod(cxxConstructorDecl(isCopyConstructor()).bind("port_method")), 
        anything()
        )).bind("port_record")
    , this);

This can be generalized into an optional() matcher:

auto optional = [](auto const& Matcher)
{
    return anyOf(
        Matcher,
        anything()
        );
};

The anything() matcher matches, well, anything. It can also match nothing because of the fact that a matcher written inside another matcher matches itself.

That is, matchers such as

functionDecl(decl())
functionDecl(namedDecl())
functionDecl(functionDecl())

match ‘trivially’.

If a functionDecl() in fact binds to a method, then the derived type can be used in the matcher:

functionDecl(cxxMethodDecl())

The optional matcher can be used as expected:

Finder->addMatcher(
    cxxRecordDecl(
        optional(
            hasMethod(cxxConstructorDecl(isCopyConstructor()).bind("port_method"))
            )
        ).bind("port_record")
    , this);

Yet another problem writers of clang-tidy checks will find is that AST nodes CallExpr and CXXConstructExpr do not share a common base representing the ability to take expressions as arguments. This means that separate matchers are required for calls and constructions.

Again, we can solve this problem generically by creating a composition function:

auto callOrConstruct = [](auto const& Matcher)
{
    return expr(anyOf(
        callExpr(Matcher),
        cxxConstructExpr(Matcher)
        ));
};

which reads as ‘an Expression which is any of a call expression or a construct expression’.

It can be used in place of either in matcher expressions:

Finder->addMatcher(
    callOrConstruct(
        hasArgument(0, integerLiteral().bind("port_literal"))
        )
    , this);

Creating composition functions like this is a very convenient way to simplify and create maintainable matchers in your clang-tidy checks. A recently published RFC on the topic of making clang-tidy checks easier to write proposes some other conveniences which can be implemented in this manner.

Getting Started With Qt for WebAssembly

by Morten Johan Sørvig (Qt Blog)

We’ve previously blogged about some of the features of Qt for WebAssembly. In this blog post we’ll take a look at how to get started: building Qt, building your application, and finally deploying the application.

If you would like to know more about this topic, then please join me for the Qt for WebAssembly webinar on November 27th.

Emscripten

The first step is installing emscripten. Please refer to the emscripten documentation for how to do so, and also note that Qt requires a unix host system: GNU/linux, macOS, or Windows subsystem for Linux. When done you should have a working em++ compiler in the path:

$ em++ --version
emcc (Emscripten gcc/clang-like replacement) 1.38.16 (commit 7a0e27441eda6cb0e3f1210e6837cae4b080ab4c)

Qt for WebAssembly applications are also Emscripten-based applications. Qt makes use of many of its features and so can application code.

Qt

Next, install the Qt 5.12 sources, for example using the online installer:

qtmaintenancetoolsources

Build Qt from source and specify that we are cross-compiling for wasm using emscripten:

$ ~/Qt/5.12.0/Src/configure -xplatform wasm-emscripten -nomake examples -prefix $PWD/qtbase
$ make module-qtbase module-qtdeclarative [other modules]

This Qt build is different from standard desktop builds in two additional ways: It is a static build, and does not support threads. Depending on how your application is structured and which features you use this may pose a problem. One way to find out is to make a separate “-static -no-feature-thread” desktop Qt build, and then debug/fix any issues there. The reason this may be preferable is that the build-debug cycle is usually faster on desktop, and you have a working debugger.

Your Application

Finally, build the application. Qmake is the currently supported build system.

$ /path/to/qt-wasm/qtbase/bin/qmake
$ make

This will produce several output files:

Name Producer Purpose
app.html Qt HTML container
qtloader.js Qt JS API for loading Qt apps
app.js emscripten app runtime and JS API
app.wasm emscripten app binary

Here, the app.wasm contains the majority (if not all) of the application and Qt code, while the .js files provide loading and run-time support.

The .html file provides the html page structure which contains the application as a <canvas> element. The default version of this file displays a Qt logo during the loading and compile stage and contains a simple HTML page structure which makes the application use the entire browser viewport. You will probably want to replace this with application-specific branding and perhaps integrate with existing html content.

For qtloader.js our intention is to have a public and stable API for loading Qt-based applications, but we are not there yet and the API in that file is subject so change.

The files are plain data files and can be served from any http server; there is no requirement for any special active server component or plugin. Note that loading from the file system is not supported by current browsers. I use Python http.server for development, which works well.

When deploying applications we do recommend using a server that supports compression. The following table gives an indication of what the expected file sizes (for the main .wasm file) are:

Qt Modules gzip brotli
Core Gui 2.8MB 2.1MB
Core Gui Widgets 4.3MB 3.2MB
Core Gui Widgets Quick Charts 8.6MB 6.3MB

gzip is a good default choice as compressor and is supported by most web servers. brotli provides a nice compression gain and is supported by all wasm-enabled browsers.

Slate

The final result of all this should be your application running in a web browser, here represented by the Slate app created by my colleague Mitch. Slate is a Qt Quick Controls 2 based image editor.

slate-wasm

A live version is available as well. If you’ve looked at this demo before the news is that it should be actually usable now: local file access is possible and there are few or none visual glitches.

For those that are attending Qt World Summit in Berlin next month: I look forward to seeing you there. If you a are not going then let me link to the webinar once again.

edit: Modified configure string in build instructions to include -nomake examples, since it will currently fail on the threading examples as some have noted in the comments. This will be fixed in Qt 5.12.1.

The post Getting Started With Qt for WebAssembly appeared first on Qt Blog.