Perfect Debugging Experience with QtCreator on Android

While I was working on a yet-to-be-announced super secret and cool Qt on Android project, I had to do a lot of debugging. This way I found that debugging Qt apps on Android using QtCreator was ok, but it had some issues, which was kinda frustrating.

  • First issue was that I could not debug on an Android 8 device.
  • Second issue was that, even if the debugger was almost ok for debugging Qt apps, debugging Qt itself was not that good.

Long story short, these problems will be fixed starting with QtCreator 4.6.1 (was too late for 4.6.0) or 4.7, and I also paved the way for using lldb if necessary, though, gdb works perfectly for me. And in the (distant) future MAYBE even being able to do java debugging from QtCreator as well!

Keep reading if you are interested in technical details.

How the debugging worked until now: it used a handshake technique:

  • The application built for debugging bundles gdbserver into the apk.
  • We start the application from QtC with some special params.
  • The app checks these params, it starts gdbserver, it creates a socket, then it waits for QtCreator to connect to this socket.
  • QtCreator uses adb to forward gdbservers and the socket port to your host.
  • QtCreator tries to connect to the socket created by your application. When it succeeds to connect to that socket it attaches host gdb to gdbserver. At this moment all the application's .so files are loaded and gdb will search for their symbols on the host side. It sets the breakpoints.
  • At the end it signals the java application (using the previous socket) that it can continue the execution.

How it works now: it's using the same technique that Android Studio uses:

  • The application built for debugging bundles gdbserver into the apk.
  • The application is started in debug mode (we add "-D" param to adb shell am start).
  • The default wait for debugger dialog appears which waits for a jdb connection.
  • QtCreator uses "adb shell run-as" to search for gdbserver and it starts it.
  • QtCreator uses adb to forward gdbservers and the socket port to your host. At this moment no .so files are loaded by your application.
  • QtCreator connects to gdbserver.
  • QtCreator uses jdb to attach to the java debugger and it signals the application to continue the execution.

At first glance, both ways look similar, but .... there is a big difference :)

  • First and foremost the application doesn't need the handshake hack, this means that we can soon drop that code from Android Qt apps.
  • The second difference, which makes the debugging perfect, is at the point when we attach gdbserver to the application. As you can see, in the first way we attach gdbserver to the application after we load all .so file, this means that all breakpoints to static vars constructors or to JNI_Onload will not work, because these functions are already called by the linker.
  • Now, because QtCreator is in control of the gdbserver part, with some effort it can search for lldbserver instead, and start it.
  • Last but not least, because it's using jdb to start the application, it might be possible to use it also to debug the java part of the application!

The downside of the new way is that the start up is a little bit slower, because instead of loading the symbols for all the .so files at once, it will load them one by one as they are loaded by the application, which on my Ryzen 1700X is from 2 to 5 seconds slower.

If you can't wait for QtCreator 4.6.1/4.7 you can cherry-pick the following two patches and rebuild QtCreator yourself:

In the end I want to thank The Qt Company folks who helped me in testing these patches on all platforms and on as many devices as we had!


About KDAB

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

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

continue reading

The post Perfect Debugging Experience with QtCreator on Android appeared first on KDAB.

Announcing Virtlyst - a web interface to manage virtual machines

Virtlyst is a web tool that allows you to manage virtual machines.

In essence it's a clone of webvirtmgr, but using Cutelyst as the backend, the reasoning behind this was that my father in law needs a server for his ASP app on a Win2k server, the server has only 4 GiB of RAM and after a week running webvirtmgr it was eating 300 MiB close to 10% of all available RAM. To get a VNC or SPICE tunnel it spawns websockify which on each new instance around 20 MiB of RAM get's used.

I found this unacceptable, a tool that is only going to be used once in a while, like if the win2k freezes or goes BSOD, CPU usage while higher didn't play a role on this.

Choosing a web interface for KVM/libvirt is no easy task, I have used Archipel and while it's a nice app it is a pain to install, OpenStack is also overly complicated, and had a button labeled as "Terminate" button that deleted the instance entirely. A simple tool that's specially simple to install was what I needed, and in fact is what a bunch of people need, here at work, OpenStack was also discarded due the hard installation process and a mix of virsh/virt-manager is used.

Since webvirtmgr is a DJango app, using it's html templates was a breeze, Grantlee didn't work with them out of the box, it has a few missing features but one can work around those, libvirt API is also quite well documented so development was quite fast, it took me 3 weeks but could easily be reduced to less than 2 if I had a bit more time.

So Virtlyst v1.0.0 is out, it uses less than 10MiB of RAM, and implements the VNC/SPICE web socket proxy in the same process thus each connections increases a almost nothing of memory usage. The software is already in production, and has all features of webvirtmgr except the migration part, that I plan to add in a future release.

Following the steps of some developer fellows I also created a Patreon account, so if you like what I do and would like to support my work please consider becoming a Patron.

Enough said, go get it!

https://github.com/cutelyst/Virtlyst/archive/v1.0.0.tar.gz

Five days left

I use to joke that the last week before foss-north is the worst – everything is done, all that is left is the stress.

This year, we have the broadest program yet. 25 speakers talking about everything from community policies, GPU isolation, blockchain, historical KDE software, retro computers, IoT, Android, SailfishOS, bug triaging, crowd funding, software updates, yocto, home automation, design to sub-atomic particles.

You can still get a ticket (and make sure to bring a friend) at foss-north . Welcome!

New in Qt 3D 5.11: Generalized Ray Casting

The 5.11 release of Qt 3D is mostly about speed and stability but it also introduces a number of new features.

One of them is generalized ray casting which can be used to find objects intersecting a 3d ray.

Object Picking

Available since 5.6, QObjectPicker can be used to detect mouse interactions with an entity. As the user moves the mouse and presses the buttons, events will be emitted by the component. This can be used to change properties of a entity based on the events, highlighting it when the mouse enters, scaling it up when a button is pressed, moving it when the mouse is dragged, etc.

By default, only mouse buttons will trigger events (if the mouse overlaps the geometry). This is done for performance reasons since computations can be expensive (see below). However, this can be changed by setting properties hoverEnabled, to detect when the mouse enters or leaves the entity, and dragEnabled, to detect when the mouse moves across the surface of the geometry.

When the mouse is pressed on an entity with a QObjectPicker component, that component will "grab" the mouse and only that object will be considered for picking events, until the mouse button is released.

When a hit is found, the generated event will contain information about the point of the geometry under the mouse. In particular, it will contain the coordinates of the mouse (in screen space) where the hit was made, the state of the buttons. But it will also include the coordinates of the point on the surface of the geometry both in local and in world coordinates.

By now it should be obvious that QObjectPicker, like MouseArea, is most suited to give behaviours to object in the scene, should as changing the scale to make them bigger when the mouse hover over them, or changing the colour when the object user "selects" the object by clicking on it.

While is very useful in its own right, it has several limitations:

  • It is dependent on mouse events: picking is implemented by casting a ray through the scene (details below) but there is no API to construct an arbitrary ray and test for objects intersecting it.
  • If the component is attached to an internal node of the scene graph, child objects will also be tested for hits but the resulting event does not contain any information about which child was actually hit.
  • There is no event generated when no hits occur.

Ray Casting

Picking as described above is implemented by casting a ray through the scene and looking for objects which intersect the ray. This is roughly how the process works:

  • For each mouse event, compute a ray between the near and far planes and transform it to world space.
  • Traverse the scene graph and look for every entity which has an object picker and where the bounding volume intersects with the ray.
  • If primitive picking is enabled (see below), traverse every primitive (triangle, line or point) to find which ones intersect with the ray.
  • Once all the hits are collected, sort them by distance to the origin of the ray.
  • Generate events for the closest hit or all of them depending on the settings (see below).

As you can imagine, on complex scene graphs with lots of primitives, this can be expensive. Qt 3D attempts to optimise things by using a bounding volume hierarchy to quickly eliminate entire portions of the scene graph which don't intersect with the ray. It also uses a thread pool to test multiple objects in parallel. Best results can be achieved by properly constructing scene graphs and avoiding single objects with large numbers of triangles.

The algorithm can be controlled globally by using the pickingSettings property of the QRenderSettings class, which is an instance of the QPickingSettings class.

The most important property is the pickMethod:

  • By default it's set to BoundingVolumePicking which is the fastest method: it will only test for bounding volume intersection. While this is very fast, it is also very imprecise. Internally, Qt 3D uses bounding spheres which can grossly exaggerate the actual volume of the object. Also, a small object positioned in front of a large one may be entirely encompassed by the large bounding sphere and thus be unpickable.
  • This property can also be set to TrianglePicking (and since 5.10 to LinePicking and PointPicking) to ask for hit tests to be made with individual primitives. This is of course far more time consuming.

Another important setting is the pickResultMode property:

  • When set to NearestPick (the default), only the closest hit will trigger an event
  • When set to AllPicks, an event will be generated for every intersection. If you imagine picking a sphere, in most cases this will generate two events. Events will be generated from front to back but they will be delivered separately and there is no way of knowing when the last event is received.

There are also settings to control how the face orientation affects picking and a world space tolerance factor to control line and point picking.

Generalized Ray Casting

The ray casting operations described above are those used by the QObjectPicker backend. As explained before, they rely on mouse events in order to compute the ray that will be used to do the hit tests.

But there are many uses cases for more generalized ray casting. Still in screen space, an application may use a specific cursor that can be controlled independently from the mouse cursor (like a gun sight). Or in an VR environment, you may want to find the object at the centre of the screen to implement gaze selection.

Also in a VR setting, you may want to implement a 3d "wand" which is manipulated using the VR controls. A 3d ray with a position, direction and length matching the virtual wand could be used to find intersecting objects. Using action buttons, you could then implement grabbing and dragging the intersecting objects.

QAbstractRayCaster

This is an abstract class that cannot be instantiated directly. If defines common properties for all sub-classes. Note that ray caster components cannot be shared between multiple entities.

The runMode property controls how often ray casting tests are performed. All ray caster instances are disabled by default. When enabled is set to true, a ray casting test will be done at the next frame. If runMode is set to SingleShot (the default), the component will disable itself and no further tests will be performed until it is enabled again. If runMode is set to Continuous, tests will be performed at every frame until the node is disabled.

Controlling what gets picked

The filterMode property and the list of QLayer instances can be used to control which portions of the scene graph are considered when casting rays. You may want to disable picking on certain portions of the scene graph, or use different rays in different sub-graphs.

This can be achieved by using QLayer components and then adding them to the relevant ray caster node. The filterMode will control if the layers enable or disable ray casting and how to evaluate multiple layers.

Remember the QLayer has a recursive property to control if the layer applies to the specific entity only or if it should affect all of its children.

Getting picking results

When a ray caster test completes, the list of results will be assigned to the hits property of the component. This list will be empty if nothing was found. A change notification will always be emitted even if two successive tests produce the same result.

Each entry in the list contains the details of a hit, sorted front to back. It contains:

  • the type of hit (Entity, Triangle, Line, Point) depending on the setting used in QPickingSettings
  • the id and a pointer to the entity containing the geometry
  • the coordinates of the intersection point in local and model coordinates
  • the distance to the origin of the ray
  • the index of the picked primitive
  • the indexes of the points used to build the picked primitive.

While the C++ implementation used a properly typed class, the QML api uses a QJSValue containing an array of javascript objects with the relevant properties included.

QScreenRayCaster

QScreenRayCaster is used to do ray casting queries based on window coordinates without relying on the user using the mouse pointer. A test will actually be performed for every active render target.

The 3d ray is computed by constructing a ray at the specified coordinates between the front and back clipping planes and transforming that ray back in to model coordinates using the relevant camera projection and transformation.

The component has helper methods to trigger a test. All that basically does is enable the component so that a test happens at the next frame.

QRayCaster

QRayCaster defines a ray in the local coordinate system of the entity the component belongs to. This means the actual ray is affected by the world transformation applied to the entity.

The ray has an origin and a direction.

The ray also has a length, any hit further away from the origin will be ignored. If that length is less or equal to zero, the ray is considered to be infinite. Bear in mind that it has an origin and a direction, so it's only half infinite :)

The component also has helper methods to trigger a test, optionally setting the properties of the ray.

Example

Qt 3d source code contains a basic QML example for using both ray caster classes.

    ScreenRayCaster {
        id: screenRayCaster

        onHitsChanged: printHits("Screen hits", hits)
    }

    MouseHandler {
        id: mouseHandler
        sourceDevice:  MouseDevice {}
        onReleased: { screenRayCaster.trigger(Qt.point(mouse.x, mouse.y)) }
    }

    function printHits(desc, hits) {
        console.log(desc, hits.length)
        for (var i=0; i<hits.length; i++) {
            console.log("  " + hits[i].entity.objectName, hits[i].distance,
                        hits[i].worldIntersection.x, hits[i].worldIntersection.y, hits[i].worldIntersection.z)
        }
    }

In the case of the ScreenRayCaster, a test is triggered whenever the mouse button is released.

    RayCaster {
        id: raycaster
        origin: Qt.vector3d(0, 0, 4)
        direction: Qt.vector3d(0., 0., -1.)
        length: 5

        onHitsChanged: printHits("Model hits", hits)
    }

    KeyboardDevice { id: kbDevice }
    KeyboardHandler {
        id: kbHandler
        focus: true
        sourceDevice: kbDevice
        onPressed: {
            if (event.text.toLowerCase() == "a") { raycaster.origin.x -= .1; raycaster.trigger() }
            if (event.text.toLowerCase() == "f") { raycaster.origin.x += .1; raycaster.trigger() }
            if (event.text.toLowerCase() == "s") { raycaster.origin.y += .1; raycaster.trigger() }
            if (event.text.toLowerCase() == "d") { raycaster.origin.y -= .1; raycaster.trigger() }
        }
    }

For the RayCaster, it defines a ray can be moved around the scene using key combinations.

[video width="1016" height="652" mp4="https://www.kdab.com/wp-content/uploads/stories/raycaster.mp4"][/video]

Not the most earth shattering demo :).   But it does exercise all the features of the newly introduced nodes and how to do picking without using QObjectPicker.

Notes

  • These nodes should not be used for rays which change constantly. In particular if the change rate is faster than the actual display rate, the results are undetermined and it will not be possible to correlate results to the actual value to the ray used to produce them.
  • At this time, the screen based ray caster has no way of controlling which render surface to test, they are all tested, including offscreen surfaces. This will be remedied in 5.12.
  • Picking settings are global and cannot be controlled per ray. So you can't have one ray to pick lines and one to pick triangles for example. This will be changed at a later time.

About KDAB

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

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

continue reading

The post New in Qt 3D 5.11: Generalized Ray Casting appeared first on KDAB.

Qt for Python is coming to a computer near you

Some of you – ok, probably most of you – know that Qt is a great C++ framework, enabling developers to create magnificent user interfaces with technologies like QML, Qt Quick Controls, and Qt Widgets. I will further claim that no one is knocked out of their socks when I say that C++ is one of the most widely used programming languages in the world today. The fact that Python is one of the fastest growing programming languages, measured in popularity, is probably also old news in most communities. So, what’s this blog post all about? Well, give it two more minutes.

C++ and Python are both great programming languages, but they are great in different leagues. C++ is the Star Destroyer of the programming universe; it can destroy all your problems, or it can turn out to be your biggest problem if you’re not friendly with it. Therefore it’s sometimes convenient to go for the Millennium Falcon of programming languages, Python. It can easily be maneuvered by anyone, princesses and smugglers alike, and it will get you from Alderaan to Yavin at light speed. And, whether you have taken the entire crew out in the Star Destroyer or blitzing around in The Millennium Falcon, you would like to have a neat user interface. That’s where you need Qt, the R2-D2 of the programming universe, connecting to both Star Destroyer and the Millennium Falcon.

PySide2 – the bindings from Python to Qt – changes skin this spring. We have re-branded it as Qt for Python on a solution level, as we wanted the name to reflect the use of Qt in Python applications. Under the hood it is still PySide2 – just better. While most of us have been idling around – thinking of names, logos, and marketing – a great team of developers has worked hard to bring the actual solution to you. Pretty soon, developers can enjoy all the goodies from Qt in their Python applications, including official technical support, around the globe. Our hope is that Qt for Python will bring Qt to new places, new developers; and new heights.

Qt for Python will be released as a Technology Preview shortly after the Qt 5.11 release as that’s the official Qt version of the first Qt for Python release. We know that many of you are eager to get started – check out the latest snapshots: http://download.qt.io/snapshots/ci/pyside or contact us to kickstart your development project now.

More blog posts will follow in the weeks to come, so stay tuned for more scrumptious details on the technical aspects and features.

The post Qt for Python is coming to a computer near you appeared first on Qt Blog.

Qt 5.9.5 Released

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

Compared to Qt 5.9.4, the new Qt 5.9.5 contains over  100 bug fixes. In total there are around 450 changes in Qt 5.9.5 compared to Qt 5.9.4. For details of the most important changes, please check the Change files of Qt 5.9.5.

Qt 5.9 LTS has entered ‘Strict’ phase in the beginning of February. It continues to receive important bug fixes and significant performance fixes still during the ‘Strict’ phase. Intention is to reduce risk of regressions and behavior changes by restricting the changes to the most important ones. We also continue to create new Qt 5.9.x patch releases, but with slower cadence than earlier.

Qt 5.9.5 can be updated to using the maintenance tool of the online installer. For new installations, please download latest online installer from Qt Account portal or from qt.io Download page. Offline packages are available for commercial users in the Qt Account portal and at the qt.io Download page for open-source users.

The post Qt 5.9.5 Released appeared first on Qt Blog.

Better support for CUPS features in Qt 5.11

During the last couple of months KDAB engineers have been working on improving CUPS printing support for Linux in Qt.

This work has been sponsored by the LiMux project, a big thank you to them for allowing us to spend time improving Qt :).

We started in early December with a series of small commits cleaning up some code, removing some code that was never called [1] and merging several small functions so the code flow is easier to understand and increases maintainability [2][3][4][5][6].

Our big goal was reviving the Advanced options tab that was present in the first versions of Qt 5 but was removed due to usability concerns [7]. Unfortunately this meant that support of advanced options like automatic stapling (see a quirky video of that here: [8]) was lost.

In the Linux world those advanced options are exposed through CUPS [9] and its support for PPD [10] files. The interesting feature of PPD files is that they have a way to describe not only the options but also how they should be grouped, so you can build an automatic UI on top of it relatively easily.

So working towards the goal we started adding a way to be able to access the PPD structures through the QPrintDevice and its Linux backend (QPpdPrintDevice) [11] [12].

Once that was in, we were in a position to restore the old code (improved thanks to code review) to show the Advanced CUPS options in the printing dialog [13]. The code basically traverses the PPD structures returned by CUPS and creates a model containing all the options. Then this model is plugged into an editable tree view. As said previously, one of the reasons it was removed was that some options were shown in two different places creating confusion for the user. That was solved easily through a blacklist, meaning that important options, like the Page Size, that already have their own space in the user interface, would not be shown in the advanced options tab.

PPD files also have a way of describing conflicts between various options, for example, you can't print on Photo quality unless you're using Photo paper. The initial code commit didn't fully  implement this correctly so we had to fix it [14].

Another usability problem the print dialog had is that it was a bit confusing how much of the state it kept, depending on which order you clicked Ok/Cancel and opened/closed it.  Some of the settings would or would not be stored, so we also fixed that :) [15][16].

Not strictly related to PPD and the advanced CUPS options, is a fix we did regarding the handling of Custom page sizes. Printers can define their own page sizes and the support for that was broken, so since we were going through the code, we also contributed a fix for it [17].

Going back to the Advanced options improvements, we added support for Installable Options [18][19]. Those are some options which basically say, if the user installed some add-ons to their
printer like a duplexer or stapler, that enables some of the Advanced options to actually be selectable. For that we also had to contribute a fix to CUPS itself [20] to fix the reported conflicting
options when Installable Options are involved, so make sure you're using CUPS >= 2.3 once it is released, or apply that patch to CUPS manually if you use a printer with Installable Options.

The last change we did for the Advanced tab was to make sure the text that comes from the PPD to describe the options is shown in the correct language (if your PPD has multi language support) [21].

One more feature we implemented in the Qt CUPS printing dialog is arbitrary range printing [22]. Previously one could only say "Print from page 3 to 5", but not "Print page 1, then from 3 to 5 and then page 11". This feature has been implemented in Qt itself, so applications don't need to support it explicitly. Any application that uses the Qt print dialog will gain support for this feature "automagically"!

All these improvements will be released with Qt 5.11. We will soon start to work on some more improvements and bugfixes for the Qt Linux printing dialog for Qt 5.12. Stay tuned!

[training_callout] continue reading

The post Better support for CUPS features in Qt 5.11 appeared first on KDAB.

New Qt Resource Center is Available Now…And the Secrets Are Out!

Qt Resource Center Available Now

The New Qt Resource Center is available now, featuring the latest technology and development insights, videos, get started tutorials, industry case studies and much more!

We collected all of our favorite learning resources in one place to provide you with the ability to get applications and embedded systems created quickly from hello world to new product.

From cool tips like creating ultra-low power Qt applications for the smallest of micro-controllers, or finding the latest communication APIs/modules, all the way to industry expert sessions on rapid prototyping new products — the new Qt Resource Center holds all of our goodies in one place.

Qt Resource Center Topics include, but are not limited to:

A few pieces in the Qt Resource Center that are trending now:

Enjoy and Always Be Learning

Sign up for occasional emails | Try Qt and receive learning materials by email

The post New Qt Resource Center is Available Now…And the Secrets Are Out! appeared first on Qt Blog.

Release 2.16.0: iPhone X Support and Runtime Screen Orientation Changes

V-Play 2.16.0 adds support for devices with notches like iPhone X. This allows to create mobile apps or games that look good on all modern devices and screens. With this update you can also change the screen orientation of your app at runtime. V-Play 2.16.0 comes with many improvements and fixes and is free to use.

Why You Should Update Your iOS App to Support iPhone X

The iPhone X features a big edge-to-edge display with a notch for the front camera and speaker. Also, hardware buttons at the front no longer exist. They got replaced by on-screen buttons and gestures provided by the OS.

Edge-to-edge Display iPhone X vs iPhone 8

Your existing iOS apps will come with black borders to not overlay areas with a notch or screen gestures:

App Support for iPhone X

To fully support iPhone X and let your app fill the whole screen, you can add an additional launch image for the iPhone X resolution. You should add one image with 2436 x 1125 pixels for landscape mode, and one with 1125 x 2436 pixels for portrait.

Note: The updated V-Play project wizards already come with the right configuration and images. You can create a new project and have a look how the asset catalog is set up.

However, if your app now covers the full screen of the iPhone X, some parts are covered or not accessible:

Fullscreen iPhone X App with Notch

The notch covers the top navigation bar in portrait mode and your page content in landscape mode. For both orientations, the area for the home swipe gesture overlaps your app at the bottom. Also note that the new screen comes with rounded corners.

To solve this problem, your app must know about the safe area of the screen. It is the part of your app, which is not covered by the notch or on-screen gestures:

Screen Inset of iPhone X Page in Portrait Mode

For example, the top navigation bar requires more space on iPhone X when in portrait mode. In landscape mode it looks a bit different. Your app UI then requires margins to the left and right, as well as a small inset at the bottom:

Screen Inset of iPhone X Page in Landscape Mode

How to Create iPhone X Apps with V-Play

V-Play Apps Support for Display Notches and Safe Area

The latest V-Play update 2.16.0 adds support for iPhone X and screens with notches. With V-Play, you do not require any extra code to let your app look good on iPhone X. With only a few lines of code, it is possible to create native iOS apps that look good on every device:

import VPlayApps 1.0
import QtQuick 2.0

App {
 // adds tab navigation
 Navigation {

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

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

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

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

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

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

 }
}

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

Tab and Navigation Bar - iPhone X Support

V-Play components like Navigation and NavigationStack automatically support the safe area. They include extra margins for the tab bar and navigation bar if required. Your V-Play app will look good out of the box when using these components. The Page content also auto-aligns with the safe area of the screen. For devices without notches, your app will not show any extra margins or insets.

Optimize Your App UI for iPhone X

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

  • Configure certain content items within the Page to align with the safe area.
  • Retrieve the actual safe area inset of the screen and layout items as required.

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

import VPlayApps 1.0
import QtQuick 2.0

App {

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

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

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

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

}

Running this app on an iPhone X produces this result:

iPhone X Safe Area - Adaptive Layout

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

The nativeUtils.safeAreaInsets hold the actual safe area inset of the screen in pixels. Devices without notches do not have any insets and thus return 0. For iPhone X, the yellow rectangle will cover the top inset, which includes the status bar. The height is set to match the status bar if no inset is returned by nativeUtils.safeAreaInsets.top. With this simple switch it is possible to still support older devices.

The available safeAreaInsets properties are:

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

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

import VPlayApps 1.0
import QtQuick 2.0

App {

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

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

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

}

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

iPhone X Safe Area - Adaptive Layout - List Cell

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

iPhone X Support for V-Play Games

Prepare Your Games for Displays with Notches

If not taken into consideration, the iPhone X notch or home gesture area can heavily affect the user experience of your game. Let’s say your game uses the bottom screen area to show some touch input controls. The iPhone X does not own a home button, so it uses a small area at the bottom for native touch gestures.

iPhone X UI - Game Controls

Your input controls thus become inaccessible, and your game essentially not playable. You do not want to show such critical game elements in parts of the screen that are not safe.

How to Use the Safe Area in Your Game Scenes

With iPhone X Support for V-Play Games, your game is kept within the safe area out-of-the-box. You can rely on the GameWindow and Scene components to only use the safe area on displays with notches.

import VPlay 2.0
import QtQuick 2.0

GameWindow {
 id: gameWindow

 Scene {
   id: scene

   // fills the full screen
   Rectangle {
     anchors.fill: parent.fullWindowAnchorItem
     color: "lightblue"
   }

   // fills the safe area
   Rectangle {
     anchors.fill: parent.gameWindowAnchorItem
     color: "lightgreen"
   }

   // fills the scene
   Rectangle {
     id: rectangle
     anchors.fill: parent
     color: "lightyellow"

     Text {
       text: "Scene"
       anchors.centerIn: parent
     }
   }

 }
}

The Scene::gameWindowAnchorItem only covers the safe area on devices like iPhone X. With the new Scene::fullWindowAnchorItem, you can choose to use the full screen for some UI elements of your game Scene. The above example covers the full screen with a blue background, but keeps other game elements safe:

iPhone X Game Scene - Safe Area Landscape

The Scene scaling mechanism resizes the Scene to match the game window, which reflects the safe area. To let your game scene fill the whole screen, it is possible to deactivate the Scene::useSafeArea setting:

iPhone X Game Scene - Use Safe Area

To retrieve exact pixel insets of the safe area, you can use the NativeUtils::safeAreaInsets property.

With the default setup, most V-Play games will work fine on iPhone X with few simple additions. For example, to let your background image cover the scene’s fullWindowAnchorItem instead of the game window.

To make your background image big enough to fill the screen of iPhone X, the following sizes are suggested:

Image type Unmodified Scene size (3:2 ratio) Suggested Background Size
sd 480 x 320 694 x 360
hd 960 x 640 1388 x 720
hd2 1920 x 1280 2776 x 1440

You can find a Photoshop template with the suggested background size here.

Simulate iPhone X on Desktop

The addition of iPhone X support also brings a new entry to the resolution simulator on Desktop.

Resolution Menu iPhone X Simulation

The desktop simulation for iPhone X does not only include the correct resolution, it also covers the safe area insets:

iPhone X Desktop Simulation with Insets

This is a huge time-saver when developing for iPhone X. You can test how your UI looks on Desktop and switch resolutions at runtime. No need to deploy your app to different physical or virtual devices.

Set Screen Orientation At Runtime

You can now set the preferred screen orientation at runtime from within your QML code!

To specify the global orientation you can use the new property NativeUtils::preferredScreenOrientation. E.g. to lock and unlock your app or game to portrait orientation, you can use the following lines of code:

import VPlayApps 1.0
import QtQuick 2.0

App {

 Column {
   AppButton {
     text: "Lock to portrait"
     onClicked: nativeUtils.preferredScreenOrientation = NativeUtils.ScreenOrientationPortrait
   }
   AppButton {
     text: "Reset default orientation"

     // Resets to the orientation defined in AndroidManifest.xml / Project-Info.plist
     onClicked: nativeUtils.preferredScreenOrientation = NativeUtils.ScreenOrientationDefault
   }
 }

}

Runtime Orientation Switch

You can also specify the orientation per page in apps, using Page::preferredScreenOrientation. Use this example code to show a page fixed to portrait mode:

import VPlayApps 1.0
import QtQuick 2.0

App {
 id: app

 NavigationStack {
   id: stack

   Page {
     id: page
     title: "Screen orientation test"

     AppButton {
       text: "Push portrait page"
       onClicked: stack.push(portraitPage)
     }
   }
 }

 Component {
   id: portraitPage

   Page {
     id: page
     title: "Portrait page"
     preferredScreenOrientation: NativeUtils.ScreenOrientationPortrait
   }
 }
}

Orientation Switch - Page-specific Orientation

These properties only have an effect on iOS and Android and override the default screen orientation defined in your project’s Project-Info.plist and AndroidManifest.xml.

New V-Play Live Server for Live Code Reloading

The new V-Play Live Server offers an improved user interface and new features.

New V-Play Live Server UI

With the new AUTO START option, you can disable the desktop client from launching automatically. This is handy if you switch between your projects often, or only want to test your project on mobile.

You can now also clear the log output of each client individually.

Connect and Remove Mobile Clients

To connect your mobile device, you only need to download the V-Play Live Scripting app for Android or iOS, and click on Connect Desktop.

V-Play Live Scripting App Connect Desktop

The Live Server will then show a pending connection request, like this:

New V-Play Live Server Connection Request

If you select Accept, your mobile device will be connected. The Live Server will memorize your device. The next time you connect, the request is accepted automatically.

If you want to remove your device completely, select the REMOVE option in the Live Server:

New V-Play Live Server Remove Mobile Client

Starting the Live Server the for First Time

The first time you start the Live Server, you will see a new welcome screen.

New V-Play Live Server Welcome Screen

If you want to connect any mobile device on Windows, it is very important to allow the Live Server to communicate through your firewall. Your project is transferred over a point-to-point connection between the Live Server and the Live Client. It does not leave your local network.

Update your V-Play Live Scripting App

If you already installed the V-Play Live Scripting app, it is very important to update the app to the latest version. This version of the Live Server uses a different protocol, and is only compatible with the latest version of the Live Scripting app.

New V-Play Live App

We usually recommend to use the latest version of the app anyway, to have access to the latest features. This time, it is mandatory.

More New Features in V-Play 2.16.0

V-Play 2.16.0 includes many more features and fixes like:

Be sure to update to the latest version. For a complete list of the changes, please check out our change log!

How to Update V-Play

Test out these new features by following these steps:

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

V-Play Update in Maintenance Tool

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

 

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

 

 

More Posts Like This

 

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

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

v-play-2-15-0-qt-5-10-qt-creator-4-5-support-firebase-data-structures-and-queries
Release 2.15.0: Upgrade to Qt 5.10 & Qt Creator 4.5 | Firebase Data Structures and Queries & Many Improvements

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

The post Release 2.16.0: iPhone X Support and Runtime Screen Orientation Changes appeared first on V-Play Engine.

Declarative Widgets

Declarative Widgets is a QML plugin that adds Qt Widgets support to QML. This means we can now easily mix the power of QML with the comfort of a Widgets UI on desktop.

 

[code language="javascript"]
import QtWidgets 1.0

MainWindow {
width: 640
height: 400

Label {
text: "Hello Declarative Widgets!"
alignment: Qt.AlignHCenter | Qt.AlignVCenter
}
}
[/code]

Background

Declarative Widgets was born out of a breakfast discussion about how awesome it would be to use QML to describe QWidget-based scenes. If you have ever worked on a Qt Quick project and then switched back to creating a Widgets UI you will understand how frustrating it can be to write and maintain a complex UI in plain C++, or even create and modify UI files in Qt Designer.

The real power of QML, however, is in property bindings. Property bindings allow us to set the value of a property as an expression that is evaluated when ever a property involved in that expression changes. Take the following example:

[code language="javascript"]
import QtWidgets 1.0

GroupBox {
title: qsTr("New Contact: %1 %2").arg(firstName.text).arg(lastName.text)

FormLayout {
LineEdit {
id: firstName
FormLayout.label: qsTr("First Name")
}
LineEdit {
id: lastName
FormLayout.label: qsTr("Last Name")
}
}
}
[/code]

The title property of the GroupBox is updated when the text property of either LineEdit changes. We could build this example in C++, but in QML we don't need to write any boilerplate code to connect to signals or define slots. By using Declarative Widgets we don't need to worry about writing our own UI components either; we can make use of all the existing widgets we developed warm, fuzzy feelings for over the years.

Implementation

To get an idea of how the Declarative Widgets plugin works, lets take a look at how QWidget is integrated into QML.

[code language="cpp"]
qmlRegisterExtendedType<QWidget, DeclarativeWidgetExtension>(uri, 1, 0, "Widget");
[/code]

QWidgetneeds a few tweaks in order to integrate it into QML: there is no default property, the x, y, width and height properties are read-only, and the geometry and visible properties do not have notify signals. Rather than modifying QWidget directly we can useqmlRegisterExtendedType to register an extension object which adds or overrides the properties we need.

[code language="cpp"]
class DeclarativeWidgetExtension : public DeclarativeObjectExtension
{
Q_OBJECT

// repeat property declarations, qmlRegisterExtendedType doesn't see the ones from base class
Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false CONSTANT)

Q_PROPERTY(int x READ x WRITE setX NOTIFY posChanged)
Q_PROPERTY(int y READ y WRITE setY NOTIFY posChanged)
Q_PROPERTY(int width READ width WRITE setWidth NOTIFY sizeChanged)
Q_PROPERTY(int height READ height WRITE setHeight NOTIFY sizeChanged)
Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry NOTIFY geometryChanged)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)

Q_CLASSINFO("DefaultProperty", "data")
}
[/code]

Our extension object, DeclarativeWidgetExtension, derives from DeclarativeObjectExtension which provides us with a default property. A default property is the property to which a value is assigned if an object is declared within another object's definition without declaring it as a value for a particular property. In Qt Quick, the default property is used to construct the visual scene hierarchy, and we do the same with Declarative Widgets to create the QWidget hierarchy, calling QWidget::setParent, QWidget::setLayout, or QWidget::addAction depending on the type of the declared object. Note that we have to redeclare the data property because qmlRegisterExtendedType doesn't see the one from the base class.

To make the read-only properties writable, we override the existing property and provide a WRITE accessor function to make the appropriate change. Let's take a look at the new x property:

[code language="cpp"]
QWidget *DeclarativeWidgetExtension::extendedWidget() const
{
QWidget *parentWidget = qobject_cast<QWidget*>(parent());
Q_ASSERT(parentWidget);
Q_UNUSED(parentWidget);

return parentWidget;
}

int DeclarativeWidgetExtension::x() const
{
return extendedWidget()->x();
}

void DeclarativeWidgetExtension::setX(int value)
{
QWidget *widget = extendedWidget();

if (value == widget->x())
return;

QRect geometry = widget->geometry();
geometry.moveLeft(value);
widget->setGeometry(geometry);
}
[/code]

The READ accessor function simply calls the original READaccessor function on the extended type. However, QWidget does not have an existing setX function so we have to update the x property using QWidget::setGeometry.

Keen observers will notice that we haven't emitted any of the NOTIFY signals that we declared. This is because widgets respond to events delivered to them by Qt as a result of things that have happened either within the application or as a result of outside activity that the application needs to know about. In order to hook into this system, our extension object installs itself as an event filter on the object we are extending. An event filter receives all the events for the target object before the target does, allowing us to observe and react to the events as required.

[code language="cpp"]
bool DeclarativeWidgetExtension::eventFilter(QObject *watched, QEvent *event)
{
Q_ASSERT(watched == parent());
Q_UNUSED(watched);

switch (event->type())
{
case QEvent::Move:
emit posChanged();
emit geometryChanged();
break;

case QEvent::Resize:
emit sizeChanged();
emit geometryChanged();
break;

case QEvent::Show:
case QEvent::Hide:
emit visibleChanged(isVisible());
break;

default:
break;
}

return false;
}
[/code]

In our event filter we simply emit the NOTIFY signals when we receive the appropriate event. In our x property example we receive a QEvent::Move event as a result of our call to QWidget::setGeometry. This is where we emit posChanged.

The geometry and visibleproperties that we overrode to add a NOTIFY signal to simply call the original QWidget READ and WRITE accessor functions. Then, in the event filter we emit the new signals when we receive the appropriate event.

What about QQuickWidget or QWebEngineView?

There are no additional limitations to using QQuickWidget with Declarative Widgets. One of the use cases we came up with for using Declarative Widgets is as a stepping stone to porting existing Qt Widgets applications to Qt Quick. The first step of the port would be to isolate the business logic and replicate the existing UI using Declarative Widgets (we even wrote a tool to generate QML files from .ui files). You could then replace chunks of the UI with QtQuick components displayed in QQuickWidgets.

To see QQuickWidget or QWebEngineView in action take a look through our examples on GitHub.

How do I get it?

The Declarative Widgets source code is available on GitHub: https://github.com/KDAB/DeclarativeWidgets

If you like Declarative Widgets please consider contributing to the project. Adding Qt Widgets support to QML is a large task and whilst we have done most of the ground work there are surely features we have missed. If there are features you need and you are unable to contribute, please get in touch and we will see what we can do about implementing them for you. continue reading

The post Declarative Widgets appeared first on KDAB.

Cutelyst 2.1 Released

Cutelyst a Qt/C++ Web Framework got upped to 2.1. Yesterday I found a bug that although not critical it's important enough to roll out a new release.

As a new feature we have LangSelect plugin to help with auto detection of user language (Matthias).

And some important bug fixes:

  • Fix compilation with Qt 5.11
  • clazy fixes
  • Fix undefined cutelyst2_plugin symbol of uWSGI plugin
  • Fix for IPv6 address binding
  • Fix StoreHtpasswd::addUser if file doesn't exist (Bart)
  • Fix parsing when the url encoded (on body or query) has a key without a value but carries the equal sign (?foo=&bar)

Get it https://github.com/cutelyst/cutelyst/archive/v2.1.0.tar.gz

New Mobile App Development Documentation with QML Live Reloading of Code Snippets

Finding the right resources for a specific mobile app feature or use case can be hard. The new V-Play app documentation helps you to find help super fast. You can browse through the most important use cases and pain points of app development, and test code examples right on your mobile phone. Now you can also save and share your own code snippets from your browser.

New Documentation with All Important Use Cases for App Developers

The new app documentation offers an overview of use cases and features to create your own mobile app. Each topic contains several code examples and extra resources. You can find even more examples in the detailed API documentation.

Most Important Topics to Create Mobile Apps

Here is a list of the most important topics of the new documentation:

Layouts and Position

This topic shows you basic layout concepts and how to position your items properly. You also learn how to create pixel-perfect apps for any resolution and screen density.

Navigation

Learn how to navigate between pages in your app and how to achieve the platform specific look and feel.

Widgets and Controls

This topic gives you an overview of the most important widgets and controls for your mobile app. You can also have a look at many of them with the V-Play Showcase App for iOS and Android.

vplay-app-controls-and-widgets

App Logic with JavaScript, optional C++ and Native Code

While QML with JavaScript is the best choice for the majority of your app, you are not limited to this. You can include C++, Objective C, Swift, Java or Kotlin code in your app, if you want to. This topic gives you an overview about your options.

Themes and Colors

You can apply global theming options to your app, to change the overall look.

Touch, Gestures and User Input

Handle single touches, multi-touch and gestures in your app very straightforward. Various forms of user input are covered in this topic. Let your users add text, select dates and much more.

Animations

The Qt Quick animation framework is extremely powerful, still super easy to use. We prepared various animation examples for you, from a simple spinner to complex movements. Here’s a little example how an animation is done with V-Play:

import VPlayApps 1.0
import QtQuick 2.0

App {
  NavigationStack {
    Page {
      title: "Animated Text"

      AppText {
        id: label
        anchors.centerIn: parent
        text: "Weeeeeeeee"
      }

      // The ParallelAnimation starts all its child animation simultaneously
      ParallelAnimation {
        running: true             // Start automatically
        loops: Animation.Infinite // Repeat endless (unless stopped)
        
        NumberAnimation {
          target: label             // The animated item id
          property: "rotation"      // The animated property
          from: 0                   // Start value. If not defined, the current value is used
          to: 360                   // End value
          duration: 1000            // Duration of the animation
        }
        NumberAnimation {
          target: label
          property: "font.pixelSize"
          from: 0
          to: 40
          duration: 1000
        }
      }
    }
  }
}

 

Images, Photos, Audio and Video

Learn how to use multimedia content in your app, like displaying a video or play music.

Scroll View and List View

This topic shows you how to use list views or pages that can be scrolled. You also learn how to add and remove list items dynamically.

Storage and Databases

Store your data in simple key/value storages, SQLite databases or in the cloud. You can also use the Google Firebase service.

Location and Maps

Display maps in your mobile app, with user position, markers and much more.

Sensors, Camera and other Native Device Features

Access to sensors and other native device features could not be easier. Make full use of mobile devices out of the box.

Charts for Data Visualization

The Qt Charts module gives you access to all different kinds of charts to visualize your data. You can also animate your charts, to give your app that special something.

WebView

If your app needs to display web content, you are in good hands. You can embed and interact with a webview in your app.

Ads, In-App Purchases, Analytics, Notifications and more

Monetize your apps with advertisements or in-app purchases. Add analytics or other services, with the V-Play Plugins.

v-play-native-cross-platform-plugins

Connectivity, Networking, REST and more

Connect to anything. With REST, TCP, UDP, WebSockets, BlueTooth (BT & BTLE), NFC and more. Use the full Qt connectivity and networking features with your app.

Gamification and Messaging

You can use the V-Play social features to connect your users and let them chat. Add gamification elements like leaderboards or mix in any of the game engine components.

More Topics

The documentation covers many more topics, go ahead and check it out!

Check Out The App Documentation

 

Test Online Code Examples on Your Mobile Phone, Edit and Share Code Snippets

With the V-Play Web Editor, you can write QML code snippets with a Cloud IDE. You can view the result on your Android and iOS phone with the V-Play Live Scripting app.

vplay-web-editor-cloud-ide-with-code-snippet-sharing

For convenience you can find a button above all code examples in our documentation and on the blog. Click on it to open the example in the Web Editor. Here is an example that you can try right away (make sure you read this post on your desktop!):

import VPlayApps 1.0
import VPlay 2.0
import QtQuick 2.8

App {
  NavigationStack {
    Page {
      title: "My First App"

      AppButton {
        anchors.centerIn: parent
        text: "Celebrate"
        onClicked: {
          nativeUtils.displayAlertDialog("Yay", "That is so cool!")
        }
      }
    }
  }
}

You can now also save your favorite code snippets, edit and share them. Make sure to be logged in and visit https://v-play.net/web-editor/. Below the editor, you will find a widget to save your code snippet.

vplay-code-snippet-widget

Once you saved your snippet, you are able share the generated URL. It will look something like this:

https://v-play.net/web-editor/?snippet=c0b5e98b

For any saved snippet, you will see the share widget displayed above the editor.

vplay-code-snippet-sharing-widget

Make sure to let your friends and colleagues see your coolest examples. You can also use it to share code snippets in blog posts or forums. The sky is the limit! We also count the snippet views for you, so you don’t miss it if you go viral!

Note: You can also use the editor to share pure Qt Quick QML snippets, without any V-Play components.

Download the V-Play Live Scripting App

The V-Play Live Scripting app is available on Android and iOS. Download it to use Live Code Reloading from your browser or desktop.

Google_Play_Badge-1App Store
ic_launcherV-Play & QML Live Scripting App
Search in App Stores for: “V-Play Live Scripting”

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

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

What are you waiting for? Create your own mobile app with V-Play now!

Create Apps with V-Play

 

 

More Posts Like This

how-to-test-online-code-examples-on-android-and-ios-with-live-code-reloading
Web Editor: Test Online Code Examples on Android and iOS with Live Code Reloading
v-play-2-14-2-how-to-use-vplay-plugins-with-live-reloading

Release 2.14.2: Live Code Reloading with Native Cross-Platform Plugins

v-play-live-reloading-windows-mac-linux-ios-android-qt
Release 2.14.0: Live Code Reloading for Desktop, iOS & Android

The post New Mobile App Development Documentation with QML Live Reloading of Code Snippets appeared first on V-Play Engine.

Qbs 1.11 released

We are happy to announce version 1.11.0 of the Qbs build tool.

What’s new?

Language Improvements

The long-existing list properties qbs.targetOS and qbs.toolchain have been complemented by their scalar counterparts qbs.targetPlatform and qbs.toolchainType, respectively. The new properties make it easier to specify the target platform on the command line and in profiles, while you should still use the existing ones in your project files for purposes such as conditional compilation.

Modules can now declare their own target artifacts using the new filesAreTargets property of the Group item. The next version of Qbs will add the ability to auto-generate such modules from your products. These modules can then be distributed along with the binaries so that other Qbs projects can make use of them by simply declaring a dependency on the module.

In addition to TextFile, we now also have BinaryFile for reading and writing binary files.

C/C++ Support

We have added the property cpp.rpathOrigin, which evaluates to @loader_path on Darwin and $ORIGIN on other Unix-like platforms.

You can now specify flags to be passed to the compiler frontend only when linking via the cpp.driverLinkerFlags property.

The value "c++17" is now properly supported for cpp.cxxLanguageVersion, emitting the /std:c++17 flag when using an MSVC compiler that supports it.

The auto-detection mechanism for GCC-like compilers now considers typical MinGW prefixes, that is, file names such as i686-w64-mingw32-gcc are picked up from the search path.

Command-line Interface

The syntax for specifying configuration names has always been rather confusing, which is why they are now passed using the new config key. For instance, to build your project for two independent configurations called debug and release, you now write:

$ qbs config:debug config:release

As a result, all command-line parameters are now either options, option arguments or key-value pairs.

We have also dropped the requirement that property assignments have to appear after all options. This comes in particularly handy when amending earlier inputs using the shell history.

Documentation

The item and module references were re-designed, resulting in much-improved readability.

Furthermore, we have added a how-to on the topic of pre-compiled headers, and provided missing documentation for our XML support and the Utilities functions.

Other New Features

The “run” functionality as used by the command of the same name now considers an executable’s library dependencies, that is, it adds the paths they are located in to the respective environment variable (PATH on Windows, DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH on macOS and LD_LIBRARY_PATH on other Unix-like systems). This also works when running from Qt Creator.

Try It!

The Open Source version is available on the download page, and you can find commercially licensed packages on the Qt Account Portal. Please post issues in our bug tracker. You can also find us on IRC in #qbs on chat.freenode.net, and on the mailing list. The documentation and wiki are also good places to get started.

Qbs is also available on a number of packaging systems (Chocolatey, MacPorts, Homebrew) and updated on each release by the Qbs development team. It can also be installed through the native package management system on a number of Linux distributions including but not limited to Debian, Ubuntu, Fedora, and Arch Linux.

Qbs 1.11.0 is also included in Qt Creator 4.6.0, which was released this week as well.

The post Qbs 1.11 released appeared first on Qt Blog.

KDAB at Embedded World 2018

Embedded World, the leading exhibition for the international embedded community, just had its 16th edition and is still growing, with more than 1000 exhibitors and over 32,000 visitors from 78 countries in 2018.

Software was more central to the exhibition than ever before, so it’s no wonder this is KDAB’s 8th year in a row exhibiting.

What we showed

At our booth you could see a wide range of client showcases, as well as our C++ and Qt tools, Hotspot, Clazy and GammaRay. And good news! If your device doesn't have a GPU, it's now easier than ever to build a fluid user-interface with Qt Quick on such hardware, as demonstrated by the i.MX6 ULL demo we premiered during Embedded World.

There was a lot of interest in our services around Qt and our Intro to Qt whitepaper. But there was also a notable increase in demand for C++ modernization, due to the evolution of the C++ language reaching a wider part of the embedded community.

Read more and download the C++ modernization brochure.

Read more and download our Intro to Qt whitepaper.

If you couldn't join us, find out more about our demos here.

Next year at Embedded World

According to the organizers, more than 97% of this year’s visitors already confirmed they will come again in 2019, so don’t miss the next edition and the opportunity to stop at our booth to see the latest C++/Qt/OpenGL innovations.

Save the dates for Embedded World 2019: 26-28 February, in Nuremberg, Germany.

We sure won’t miss it!

  continue reading

The post KDAB at Embedded World 2018 appeared first on KDAB.

Qt Creator 4.6.0 released

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

C++ Support

C++ is changing a lot these days, and to catch up with these developments we upgraded the backend for the Clang based code model from Clang 3.9 to 5.0. This enables support for many C++17 features that were not available in Clang 3.9. Since the ClangCodeModel plugin is not enabled by default, you have to make sure to enable it in Help > About Plugins (Qt Creator > About Plugins on macOS), to benefit from this upgrade.

Diagnostics and fixits in Qt Creator by clang-tidy and clazy

In the animation above you see our new integration of Clang-Tidy and Clazy warnings into the diagnostic messages in the C++ editor. Since some checks can be time consuming, and other checks can produce false positives to varying degrees, they are not enabled by default. To enable them go to Options > C++ > Code Model > Clang Code Model Warnings, create a copy of one of the presets, and choose the checks that you want to be performed.

If you enable the Clang code model, that is now also used for the informational tooltips on symbols in the editor. They now resolve auto to the actual type and show template parameters for template types. They show the first or the \brief paragraph of a documentation comment, too.

We also added separate highlighting of function definitions and fixed some issues with saving header files on Windows while Clang has a grip on them.

Navigation

We added 3 more filters to Locator. Type “b<space>” to jump to a bookmark, filtering on file name and notes. The other two are not directly related to navigation but nevertheless useful.
The filter “t<space>” triggers an item from the main menu. You can either use the display name of the item to locate it, or parts of the menu path leading to it. For example “t sess expe” could be used to trigger the menu item File > Sessions > Experimental Something.
Use “=<space>” to evaluate simple ECMAScript (JavaScript) expressions. You have all functionality from the ECMA-262 specification at your disposal, and for convenience, we also added the functions from the Math object as global functions (so you can write “max(1, 2)” instead of “Math.max(1, 2)”).

We continued the work on the File System navigation pane that we started with 4.5. It now offers breadcrumbs for the file path at the top, and we added actions for adding, removing, and renaming files to its context menu.

Model Editor

Thanks to Jochen, the original contributor, the model editor received a big update in this release. First of all we removed the experimental state and made it available by default. We cleaned up the UI a bit, adding the zoom actions to the editor tool bar, and moving the export actions to the File menu. You can export only selected elements or the whole diagram to images. The editor now supports text alignment and multi-line object names. A wider range of panes now supports drag & drop of items.

There have been many more improvements all over Qt Creator. Please have a look at our changelog for a more detailed overview.

Get Qt Creator 4.6

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

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

Qt Installer Framework 3.0.4 Released

We are happy to announce the release of Qt IFW 3.0.4.

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

  • Add possibility to skip proxy with –no-proxy -option
  • Fix infinite wait if downloadable package is missing
  • Avoid admin query popup with –checkupdates -option
  • Fixed Mkdir operation in 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 download.qt.io (open source) or in your Qt Account.

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

New in Qt 5.10: Texture Based Animations in Qt 3D

Many new features were added to Qt 3D in the 5.10 release. One of them is the support for sprite sheets, contributed by KDAB, as provided by QSpriteGrid and QSpriteSheet and their respective QML items.

One way of animating things is to switch between many different versions of the same object at different points in time, like the flip books we all enjoyed as kids. If you flip fast enough, you get the illusion of animation.

In the context of OpenGL and Qt 3D, images are simply textures and are very commonly used to add details to 3d models. The naive approach to animating texture would be to use lots of them. However, switching textures has a very high cost so traditionally modellers will use texture atlases, where all the images are arranged into a single texture. This does complicate modelling slightly as the original texture coordinates need to be modified to point to the portion of the atlas that now contains the relevant image.

In effect, sprite sheets are simplified atlases that take care of this for you. They are commonly used in 2d or 2.5d applications to animate effects or characters.

Building Sprite Sheets

Simple sprite sheets are just regular grids of images.

However, as with general atlases, all individual images need not be the same size or be arranged in a grid. In that case, individual sprites need to be specified by their bounding rectangle within the texture.

There's a number of applications that can be used to create them. Blender can output steps in animations to a sprite sheet. TexturePacker can also be used to assemble pre-existing images.

Texture Transforms

In the simplest case, a sprite will be mapped on to planar surfaces, a simple rectangle. When applying textures to a surface, you of course need to provide texture coordinates, mapping points to pixels in the texture. In the case of the PlanarMesh, precomputed texture coordinates will map to textures such as it covers the entirety of the surface.

However, if the source texture is a sprite sheet, then the texture coordinates do not work any more as we want to cover the specific sprite, not the entire sheet.

One thing you do NOT want to do is replace the texture coordinates every time you want to change sprite.

In effect, texture coordinates need to be:

  • scaled to cover the range of a sprite cell
  • offset to specify the right origin

This transformation can easily be encoded in a 3x3 matrix which is applied to texture coordinates in the vertex shader. In order to support this, QTextureLoader has been extended with a textureTransform parameter which is passed to the shader as a uniform.

Putting it all together

A sprite sheet is conceptually very simple in Qt 3D. It has:

  • a list of "areas", one for each sprite
  • a current sprite index in that list
  • an input texture to pick sprites from
  • a 3x3 texture transform matrix which is updated every time the current index changes

So simple animations can be achieved by changing the current sprite index and binding the texture transform to the matching property in the QTextureLoader instance.

Sprite Grids

QSpriteGrid is used when sprites are arranged in regular grid.

Entity {

    PlaneMesh {
        id: mesh
    }

    TextureMaterial {
        id: material
        texture: TextureLoader {
            id: textureLoader
            source: "spritegrid.png"
            mirrored: false
        }
        textureTransform: spriteGrid.textureTransform
    }

    SpriteGrid {
        id: spriteGrid
        rows: 2; columns: 6
        texture: textureLoader
    }

    components: [ mesh, material ]
}

Images in the grid are assumed to be arranged in row major order. So currentIndex must remain between 0 and rows * columns.
The texture property points to the image containing the sprites. The current index, number of rows and columns and the actual size of the texture are all used to compute the texture transform.

Sprite Sheets

QSpriteSheet is used when the sprites are not all the same size and/or are not organised in a grid. You then need specify the extent of each sprite.

Entity {

    PlaneMesh {
        id: mesh
    }

    TextureMaterial {
        id: material
        texture: TextureLoader {
            id: textureLoader
            source: "spritegrid.png"
            mirrored: false
        }
        textureTransform: spriteGrid.textureTransform
    }

    SpriteSheet {
        id: spriteSheet
        texture: textureLoader

        SpriteItem { x:    0; y:   0; width: 250; height: 172 }
        SpriteItem { x:  276; y:   0; width: 250; height: 172 }
        SpriteItem { x:  550; y:   0; width: 250; height: 172 }
        //...
    }

    components: [ mesh, material ]
}

The currentIndex must remain between 0 and the number to QSpriteItem children.

Example

[video width="1014" height="758" mp4="https://www.kdab.com/wp-content/uploads/stories/qt3dexplosion.mp4"][/video]

 

In this example, we use a sprite grid which contains frames of an explosion. A timer is used to change the current index. While the animation runs, the object is faded out.

Looking straight on, you see a rather nice effect. The illusion becomes clear when you look at it sideways and see the plane on which the texture is mapped.

Notes:

  • In the general 3d case, it is common to combine sprite sheets with billboards in order to keep the plane aligned with the screen. This can normally easily be done in the shaders.
  • QSpriteSheet doesn't currently support rotated sprites.
  • QTextureMaterial does not currently support alpha blending, so transparent portions of the textures will appear black. This can worked around by building a custom material and will be fixed in 5.11.
  • One of the problems with putting all the images in one texture is that you get quickly limited by the maximum texture size. For bigger images, a more modern approach may be to use QTexture2DArray. However, in this case all images need to be the same size. But the only limit then would be the maximum texture size and the amount of texture memory available...

  continue reading

The post New in Qt 5.10: Texture Based Animations in Qt 3D appeared first on KDAB.

Certifiably Qt

Expanding your team’s software development capacity is something that most managers will encounter at some point in their careers. There are several ways to do this – three of the most common options are hiring new employees, using a service company, or incorporating onsite contractors. Regardless of which route you choose to go, software certifications are an effective tool to help you identify the right resources. Qt certifications are a case in point.

Originally created by Nokia, the Qt certification program has been running for many years and is available through a number of third-party providers worldwide. It is a well-respected program, known for its fair and impartial grading, and is considered to be an accurate measure of Qt skill level, making it a no-brainer as a hiring/outsourcing criterion for your next Qt project.

The biggest benefit to you as a manager is knowing that Qt certified engineers have solid knowledge of the framework as well as the ability to apply it to real-world situations. A secondary benefit is knowing you’ve got engineers who are dedicated professionals willing and able to learn new skills, and adapt to the dynamic demands of the workplace.

Here’s what the different certifications mean:

  • Certified Qt and QML Developer – demonstrates that the holder has a baseline knowledge of creating, building, and debugging Qt and QML applications
  • Certified Qt C++ Specialist – confirms that the applicant has a sound working knowledge of UI creation using widgets as well as Qt C++ modules, APIs, and patterns
  • Certified Qt Quick Specialist – verifies that the developer has a solid understanding of UI creation using Qt Quick and QML

KDAB certification
We at KDAB consider certifications to be vital. In fact, all KDAB engineers are Certified Qt and QML Developers at a minimum, and many have one or both of the extended certifications. Feel free to call us if ever you find yourself in need of Qt reinforcements! continue reading

The post Certifiably Qt appeared first on KDAB.

KDSoap 1.7.0 is released

kdsoap128KDSoap is a tool for creating client applications for web services without the need for any further component such as a dedicated web server.

KDSoap lets you interact with applications which have APIs that can be exported as SOAP objects. The web service then provides a machine-accessible interface to its functionality via HTTP.

Changes in 1.7.0

General

  • Qt 5.9.0 support (compilation fix due to qt_qhash_seed being removed, unittest fix due to QNetworkReply error code difference)

Client-side

  • Fix unwanted generation of SoapAction header when it should be empty (SOAP-135).
  • Abort the connection when destroying a job with a pending call (SOAP-138).

WSDL parser / code generator changes, applying to both client and server side

  • Add support for body namespace specification in RPC calls.
  • Fix namespace handling in typename comparison for optional element used inside itself (github issue #83).
  • Add missing include in generated header, when an operation's return value needs one (ex: QDate) (github issue #110).
  • Fix namespace handling in restriction and extension tags
  • Fix wrong indentation of "};" for classes inside namespaces

Links

  • You can see the changelog here.
  • The source code can be found on GitHub here.
  • Tarballs and zipballs are available here.
  • Prebuilt packages for some popular Linux distributions can be found here  (use the qt5-kdsoap packages unless you are still on Qt4).
  • We also provide Homebrew recipes (Qt4 and Qt5 based versions) for the Mac folks.
    See https://github.com/KDAB/homebrew-tap
  • If you use KDAB Commercial you'll need to wait a few days for the download area to be updated.

continue reading

The post KDSoap 1.7.0 is released appeared first on KDAB.

Qt Champions 2017

Qt Champions

It’s time to share who the Qt Champions for 2017 are!

As always, all the nominees were incredible people. It is hard to decide who is most worthy of the Qt Champion title. I asked for help from our lifetime Qt Champion Samuel Gaist, and together we faced the tough decision.

And without further ado, here are the new Qt Champions:

@mrjj and @kshegunov have been granted the Community Builder title. Beside answering questions on the forum @mrjj is always ready to try or build test applications in order to help fellow members to solved their problem. @kshegunov‘s deep C++ knowledge and insightful comments are always appreciated for moving the debate further.

@dheerendra is this year’s Ambassador for all the work he is doing in India that promotes the use of Qt through local meetups, training and also the forum.

@marco_piccolino gets the Content Creator reward. Outside of being the driving force behind the qtmob slack channel, Marco is also the author of the Qt 5 Projects book.

@aha_1980 is the 2017 QA Champion. While being present on the forum he’s also very active on the bug reporting front helping on triaging, improving the reports and fixing these nasty bugs especially on the QtSerialBus module.

The Developer title goes to @orgads. His work on Qt’s internal might not be visible to the outside but his gerrit record speaks loudly. Between his own patches and reviews, his helpfulness and friendly nature is praised by his peers.

Our Maverick Of The Year is @benlau ! Ben provides numerous helper libraries covering interesting aspects like promises handling for QML and C++, custom Android components and more.

Thank you everyone for your involvement in Qt, you make the community a better place for everyone!

And congratulations to all the Qt Champions!

The post Qt Champions 2017 appeared first on Qt Blog.

Cutelyst 2 released with HTTP/2 support

Cutelyst the Qt/C++ web framework just got a major release update, around one and half year ago Cutelyst v1 got the first release with a stable API/ABI, many improvements where made during this period but now it was time to clean up the mistakes and give room for new features.

Porting applications to v2 is mostly a breeze, since most API changes were done on the Engine class replacing 1 with 2 and recompiling should be enough on most cases, at least this was the case for CMlyst, Stickyst and my personal applications.

Due cleanup Cutelyst Core module got a size reduction, and WSGI module increased a bit due the new HTTP/2 parser. Windows MSVC was finally able to build and test all modules.

WSGI module now defaults to using our custom EPoll event loop (can be switched back to Qt's default one with an environment variable), this allows for a steady performance without degradation when an increased number of simultaneous connections is made.

Validators plugins by Matthias got their share of improvements and a new password quality validator was added, plus manual pages for the tools.

The HTTP/2 parser adds more value to our framework, it's binary nature makes it very easy to implement, in two days most of it was already working but HTTP/2 comes with a dependency, called HPACK which has it's own RFC. HPACK is the header compression mechanism created for HTTP/2 because gzip compression as used in SPDY had security issues when on HTTPS called CRIME .

The problem is that HPACK is not very trivial to implement and it took many hours and made KCalc my best friend when converting hex to binary to decimal and what not...

Cutelyst HTTP/2 parser passes all tests of a tool named h2spec, using h2load it even showed more requests per second than HTTP/1 but it's complicated to benchmark this two different protocols specially with different load tools.

Upgrading from HTTP/1.1 is supported with a switch, as well as enabling H2 on HTTPS using the ALPN negotiation (which is the only option browsers support), H2C or HTTP/2 in clear text is also supported but it's only useful if the client can connect with previous knowledge.

If you know HTTP/2 your question is: "Does it support server push?". No it doesn't at the moment, SERVER_PUSH is a feature that allows the server to send CSS, Javascript without the browser asking for it, so it can avoid the request the browser would do, however this feature isn't magical, it won't make slow websites super fast , it's also hard to do right, and each browser has it's own complicated issues with this feature.

I strongly recommend reading this https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ .

This does not mean SERVER_PUSH won't be implemented, quite the opposite, due the need to implement it properly I want more time to study the RFC and browsers behavior so that I can provide a good API.

I have also done some last minute performance improvements with the help of KDAB Hotspot/perf, and I must say that the days of profiling with weird/huge perf command line options are gone, awesome tool!

Get it! https://github.com/cutelyst/cutelyst/archive/v2.0.0.tar.gz

If you like it please give us a star on GitHub!

Have fun!

Qt Quick without a GPU: i.MX6 ULL

 

With the introduction of the Qt Quick software renderer it became possible to use Qt Quick on devices without a GPU. We investigated how viable this option is on a lower end device, particularly the NXP i.MX6 ULL. It turns out that with some (partially not yet integrated) patches developed by KDAB and The Qt Company, the performance is very competitive. Even smooth video playback (with at least half-size VGA resolution) can be done by using the PXP engine on the i.MX6 ULL.

continue reading

The post Qt Quick without a GPU: i.MX6 ULL appeared first on KDAB.

Swift 4.0 is Ready

We’re excited to announce that Swift 4.0 has reached full release status. The packages can be downloaded from the releases page and a full list of new features can be found in the 4.0 changelog.

We encourage everyone to get the new build and try it out, and give us feedback on our latest release.

Qt Creator 4.6 RC released

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

Since the beta release we have been busy with bug fixing. Please refer to the beta blog post and our change log for an overview of what is new in Qt Creator 4.6. As always this is a final call for feedback from you before we release 4.6.0, so we would be happy to hear from you on our bug tracker, the mailing list, or on IRC.

Get Qt Creator 4.6 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.6 RC is also available under Preview > Qt Creator 4.6.0-rc1 in the online installer, as an update to the beta release. Please post issues in our bug tracker. You can also find us on IRC on #qt-creator on chat.freenode.net, and on the Qt Creator mailing list.

The post Qt Creator 4.6 RC released appeared first on Qt Blog.

Qt used to demonstrate KNX IoT possibilities at ISE and L+B fairs

KNX Introduction

In its more than 25 years of history, KNX has an unrivaled track record of guaranteeing long-term support of automation solutions in any type of building.
Based on the KNX standard, building automation can be realized in a reliable, interoperable and extendable way: devices from over 400 manufacturers work together in a very stable distributed environment without a single point of failure. The current ecosystem is physically easy to install and logically configurable with one single tool, ETS™.

IoT is not an easy solution with cross-vendor support yet

Complexity has increased, reliability and interoperability are however still not guaranteed

  • Many solutions are available that cover just one single use case (voice control, internet connected doorbell, lights and room temperature regulator controllable by App, …).
  • To try to connect the different services provided by devices in a reliable way is not trivial.
  • In many cases, the correct functioning of devices depends on internet connection.
  • Customized software integrations can break upon every software update and is very complex to secure. Reliability and stability is not guaranteed over a longer period of time, a must for building automation.
  • Integration may depend on cloud services managed by 3rd party companies, out of control of the end user and with a specific business case in mind.

KNX and IoT

There are numerous good solutions from KNX manufactures to connect KNX to higher-level IoT systems already today. The internet side of these products is however not standardized or is created to match specific use cases.

As announced in 2016, as a first step towards standardizing the internet side of such KNX IoT gateways, KNX Association published the KNX web services specifications to allow aligning gateways to the existing web services protocols oBIX, OPC/UA, and BACnet web services.

Adding advantages from KNX to loT

As a second step in the KNX IoT project, KNX now wishes to make the key KNX advantages of interoperability, reliability, and extendibility also available on the IoT level. To demonstrate the goals, a demonstrator was created with Qt technology.

Qt KNX module

Qt KNX implements the client side of a connection between a client and a KNXnet/IP server. This connection enables sending messages to the KNX bus and controlling the functionalities of the KNX devices. The Qt KNX module is currently available as a Technology Preview as part of Qt for Automation add-ons. More details on the Qt KNX module can be found here: https://resources.qt.io/qt-knx/. Documentation: http://doc.qt.io/QtKNX/qtknx-overview.html/

Qt demonstrator

For the new KNX IoT solution, it is crucial that all device types can seamlessly tap into the communication. The demonstrator includes a representation of all possible involved device types. The goal is to explain the advantages of each type towards the overall solution.

 

picture1

picture2

 

The demonstrated devices include:

  • KNX devices on twisted pair and radio frequency.
  • NXP development boards with Thread group network stack, integrated with the KNX application layer
  • RaspberryPi devices representing capable devices and cloud server
  • A Linux desktop

The setup underlines the key points of the KNX IoT solution:

  • Semantic interoperability
  • A distributed solution containing both Classic and IoT device/services
  • Integration of KNX Classic devices
  • Integration of Fairhair group network devices based on Thread as example for constrained field bus level network
  • High availability and eventual consistency, demonstrating how the distributed solution copes with device and network failures

Demo cases

  1. Data is synchronized in real-time. Light color can be changed by any of the components, change is visible on all others
  2. The system still works when disabling components, demonstration of how parts recover
  3. The system works when the internet connection is down, requests for color changes can still be made from all sides (execution will not be immediate on all sides, but as soon as the broken link in the network is restored)
  4. Show data-driven messages
  5. Show semantic model
  6. Show integration with Google drive

 

The Qt framework was chosen to easily create this setup for several reasons:

  • Single codebase usable for RaspberryPi graphical solution + Android + Linux desktop
  • Low effort to create a visually appealing interface, including animations and high framerate for smooth animations and movements within the frontend.
  • Network libraries giving a better abstraction for networking
  • Qt is also used for the authentication against the Google API
  • Qt KNX is used to connect to KNXnet/IP to interact with the devices on Twisted pair and radio frequency

Summary

The KNX IoT solution will lower the barrier to access KNX as part of the Internet of Things. The aim is to reduce the knowledge required and open the current KNX ecosystem to non-KNX IT specialists through ‘out-of-the-box’ operation, while still allowing advanced configuration and adaption by specialists.

The KNX IoT solution is defined in partnership with key KNX manufacturers and standardization bodies (like Fairhair and the Thread group). KNX is also working on proofs of concept to validate the solutions. Qt makes it possible to concentrate on the key points and keep the code clear from system-specific implementations in these proofs of concepts.

Leveraging standards ensures that the value of KNX products is increased and long-term support can be guaranteed in a constantly changing IoT world. KNX has the advantage of a large KNX install base, which allows drawing on a wealth of experience that will help successfully extending the KNX integration into the Internet of Things.

More details on the KNX IoT project can be found here: https://www.knx.org/knx-en/Landing-Pages/KNX-IoT/

“The Qt Company is exhibiting at Light+Building 2018 at Hall 8.0 F98 as part of the KNX member booth and our experts will be on hand to discuss building cost and time efficient building automation applications. “

The post Qt used to demonstrate KNX IoT possibilities at ISE and L+B fairs appeared first on Qt Blog.

Qt Creator 4.5.2 released

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

This release includes a workaround for an issue in Qt which makes Qt Creator’s summary progress bar and some other controls disappear (QTCREATORBUG-19716).

Get Qt Creator 4.5.2

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

qutebrowser v1.2.0 released!

I'm happy to announce that I just released qutebrowser v1.2.0!

qutebrowser is a keyboard driven browser with a vim-like, minimalistic interface. It's written using PyQt and cross-platform.

This release comes with a long changelog, but the most interesting changes are probably initial support for per-domain settings (I've had …

Qt Contributors’ Summit 2018

QtCS

Contributors, Mark your calendars!

11th and 12th June 2018

And the location is Oslo, Norway.

Oslo in June is a beautiful place to be, but the best part is that you will meet all the Qt Contributors!

The Qt Contributors’ Summit is an annual event open to anyone who has contributed toward the Qt project in the past year. Contributions can include code, helping on the forum, maintaining the wiki, or any other form of moving the Qt project forward. We are also happy to have advanced Qt users at the event, as there can never be too much user feedback.

For the past two years the Qt Contributors’ Summit has been run as part of bigger events. In 2016 we co-located with QtCon and last year with Qt World Summit. This year we want to have Qt Contributors’ Summit as it’s own event which focuses again more on the core Qt community.

Qt Contributors’ Summit is traditionally run as an unconference, participants bring their topics to the event and they are presented and discussed. We are thinking of changing the format somewhat, so that the topics can be prepared a bit more in advance and we could also have some hands on work ongoing at the event itself.

As always the event will be free of charge, but we will have a registration page, so we can prepare better.

If you are interested in sponsoring the event, please get in touch with me, we are more than happy to have help in making Qt Contributors’ Summit a great event.

I’m looking forward to seeing many of you in June in Oslo!

The post Qt Contributors’ Summit 2018 appeared first on Qt Blog.

Slate: A Basic Pixel Art Editor Built with Qt Quick

I loved video games as a kid. Pokémon Blue and Wario Land on GameBoy. On the SNES I played SimCity, The Lost Vikings, Cannon Fodder, Super Mario World, Axelay… probably more that I can’t remember. Then there were the old Windows 95 games on PC, PlayStation, Xbox… ah, good times. Video games were the reason I started learning how to program: I wanted to make my own games. To this day (at least a decade later) I’m still working on games in my spare time, hoping to one day release a game that others will enjoy as much as I enjoy the games I play.

The current one I’m working on is a 2D isometric turn-based RPG. The artwork is all pixel art, as it’s easy to create, and, as a bonus, I don’t have to worry about scaling/high DPI! While working on the game, I decided that I should find a tool for creating tilesets. None of the tools I looked at had what I was after, so I thought: “how hard could it be to create my own?”

As it turns out, it wasn’t that hard, and it was also really fun and rewarding. It has also branched out beyond just creating tilesets, and is now a more general editor that has support for editing images directly and using layers. Here’s a GIF of it in action (apologies in advance for the compression in the colour picker):

slate-in-action

It’s still in alpha, but it’s at a stage where I’ve been happily using it to create the artwork for my game, so I consider it usable.

Taken from its GitHub page:

“Slate was built for pixel art, and its goal is to simplify the creation of sprites and tilesets by offering a user-friendly, customisable interface.”

Being a desktop application built with Qt Quick Controls 2, I figured that it might be an interesting example for others to read about. In this post, I’m going to briefly discuss how I implemented Slate’s user interface and auto tests.

Visual Structure

Slate is simple. My goal when creating it was to have something that was fun to work on and easy to maintain.

To that end, each instance of Slate can only have one image open at a time. The canvas for the image takes up the most of the screen:

slate

Panels

slate-panels

Currently, all of the panels are collapsible, but fixed to the right side of the window. I know some people like dockable windows, but in the spirit of keeping it simple, I went with this approach. Each panel is represented by Panel.qml:

import QtQuick 2.6
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0

import App 1.0

import "." as Ui

Page {
    id: root
    objectName: "panel"
    background: Rectangle {
        color: Ui.CanvasColours.panelColour
    }

    property bool expanded: true
    property Popup settingsPopup: null

    header: RowLayout {
        spacing: 0

        Label {
            text: root.title
            font.bold: true

            Layout.leftMargin: 16
        }

        Item {
            Layout.fillWidth: true
        }

        ToolButton {
            objectName: root.objectName + "SettingsToolButton"
            text: "\uf013"
            font.family: "FontAwesome"
            focusPolicy: Qt.NoFocus
            visible: settingsPopup

            Layout.preferredWidth: implicitHeight

            onClicked: settingsPopup.open()
        }

        ToolButton {
            objectName: root.objectName + "HideShowToolButton"
            text: expanded ? "\uf146" : "\uf0fe"
            font.family: "FontAwesome"
            focusPolicy: Qt.NoFocus

            Layout.leftMargin: -8
            Layout.preferredWidth: implicitHeight

            onClicked: expanded = !expanded
        }
    }
}

Panel itself is a Page. I chose this type because it allows me to conveniently specify a header that contains the title of the panel and its buttons. Each panel can be collapsed, and can also provide some panel-specific settings that are modified through a popup.

Menus

slate-menus

Common tools and operations are in the toolbar at the top of the window, with the complete set being available in the menu bar:

import Qt.labs.platform 1.0 as Platform

import App 1.0

Platform.MenuBar {
    property ImageCanvas canvas
    property ProjectManager projectManager
    property Project project: projectManager.project
    property int projectType: project ? project.type : 0
    readonly property bool isImageProjectType: projectType === Project.ImageType || projectType === Project.LayeredImageType

    property var canvasSizePopup
    property var imageSizePopup

    // ...

    Platform.Menu {
        id: editMenu
        objectName: "editMenu"
        title: qsTr("Edit")

        Platform.MenuItem {
            objectName: "undoMenuButton"
            text: qsTr("Undo")
            onTriggered: project.undoStack.undo()
            enabled: project && project.undoStack.canUndo
        }

        Platform.MenuItem {
            objectName: "redoMenuButton"
            text: qsTr("Redo")
            onTriggered: project.undoStack.redo()
            enabled: project && project.undoStack.canRedo
        }

        Platform.MenuSeparator {}

        Platform.MenuItem {
            objectName: "copyMenuButton"
            text: qsTr("Copy")
            onTriggered: canvas.copySelection()
            enabled: isImageProjectType && canvas && canvas.hasSelection
        }

        Platform.MenuItem {
            objectName: "pasteMenuButton"
            text: qsTr("Paste")
            onTriggered: canvas.paste()
            enabled: isImageProjectType && canvas
        }

        // ...
    }
    // ...
}

As Slate has been developed against the latest Qt Quick Controls 2 versions, it recently started using native menu bars on all platforms. However, it was previously using non-native menus on Windows until the support was added. I mention this because I feel like it could be a useful example; not only for how to have native controls on some platforms, and non-native controls on others, but also to demonstrate how to use file selectors for situations like this in general. To learn more, see the repo as of this commit; specifically, this version of MenuBar.qml is native, and this one is a non-native alternative for Windows.

ToolBars

slate-toolbar

The ToolBar is based on the ToolBar control:

import QtQuick 2.6
import QtQuick.Controls 2.1

import App 1.0

import "." as Ui

ToolBar {
    id: root
    objectName: "iconToolBar"

    // ...

    Row {
        id: toolbarRow
        enabled: canvas
        anchors.fill: parent
        // Make sure that we don't end up on a sub-pixel position.
        anchors.leftMargin: Math.round(toolSeparator.implicitWidth / 2)

        ToolButton {
            id: canvasSizeButton
            objectName: "canvasSizeButton"
            enabled: project && project.loaded
            hoverEnabled: true
            focusPolicy: Qt.NoFocus

            icon.source: "qrc:/images/change-canvas-size.png"

            ToolTip.text: qsTr("Change the size of the canvas")
            ToolTip.visible: hovered && !canvasSizePopup.visible

            onClicked: canvasSizePopup.open()
        }

        ToolButton {
            id: imageSizeButton
            objectName: "imageSizeButton"
            enabled: project && project.loaded && !isTilesetProject
            hoverEnabled: true
            focusPolicy: Qt.NoFocus

            icon.source: "qrc:/images/change-image-size.png"

            ToolTip.text: qsTr("Change the size of the image")
            ToolTip.visible: hovered && !imageSizePopup.visible

            onClicked: imageSizePopup.open()
        }

        ToolSeparator {}

        Row {
            spacing: 5

            Ui.IconToolButton {
                objectName: "undoButton"
                text: "\uf0e2"
                enabled: project && project.undoStack.canUndo
                hoverEnabled: true

                ToolTip.text: qsTr("Undo the last canvas operation")
                ToolTip.visible: hovered

                onClicked: project.undoStack.undo()
            }

            Ui.IconToolButton {
                objectName: "redoButton"
                text: "\uf01e"
                enabled: project && project.undoStack.canRedo
                hoverEnabled: true

                ToolTip.text: qsTr("Redo the last undone canvas operation")
                ToolTip.visible: hovered

                onClicked: project.undoStack.redo()
            }

            ToolSeparator {}
        }
        // ...
    }
}

It is a mix of ToolButtons using images for icons and a custom IconToolButton that is simply a ToolButton that sets FontAwesome as its font family for convenience.

Shortcuts

All of the shortcuts are defined in Shortcuts.qml:

import QtQuick 2.6

import App 1.0

Item {
    objectName: "shortcuts"

    // ...

    Shortcut {
        objectName: "redoShortcut"
        sequence: settings.redoShortcut
        onActivated: project.undoStack.redo()
        enabled: canvasHasActiveFocus && project && project.undoStack.canRedo
    }

    Shortcut {
        objectName: "copyShortcut"
        sequence: StandardKey.Copy
        onActivated: canvas.copySelection()
        enabled: isImageProjectType && canvasHasActiveFocus && canvas.hasSelection
    }

    Shortcut {
        objectName: "pasteShortcut"
        sequence: StandardKey.Paste
        onActivated: canvas.paste()
        enabled: isImageProjectType && canvasHasActiveFocus
    }

    // ...
}

I started writing Slate before Action was introduced, and haven’t bothered to clean this up yet. Ideally, each of these shortcuts would be an action in MenuBar.qml, instead of being defined in both Shortcuts.qml and MenuBar.qml.

Each shortcut’s key sequence is stored in ApplicationSettings, as they are configurable. Below is a screenshot of the shortcuts tab of OptionsDialog:

slate-options

Each shortcut there is represented by a ShortcutRow item. KeySequenceEditor takes care of the actual key editing.

Style

To match its name, Slate uses the Material style‘s dark theme. I find dark themes more gentle on the eyes, and, in my opinion, the Material style is the best looking style in Qt Quick Controls 2.

In some places I’ve experimented with supporting other styles, such as the Universal style. I did so using file selectors.

When adding custom UI elements, such as the current layer indicator in the Layer panel, I’ve made sure to use the accent colour from the active style:

slate-layers

To do this, I use a CanvasColours singleton. The default implementation is for the default style (again, just experimenting), with other styles having their own implementation of the singleton in their specific file selector directories. The Material style implementation is here. Notice that it uses Material.accent.

Testing

I take comfort in auto tests. They’re a great reassurance that I haven’t screwed everything up. I try to add tests for every new feature. Sometimes I get lazy, but in general I think the coverage is pretty good.

Gritty Details

My goal with the auto tests is to try as much as possible to emulate the workflow that a user would employ. This means clicking buttons instead of just calling the C++ function that the button would have called.

The test case itself inherits from TestHelper, which provides helper functions for common tasks. Here’s an example of a test:

void tst_App::disableToolsWhenLayerHidden()
{
    QVERIFY2(createNewLayeredImageProject(), failureMessage);

    // The cursor should be normal.
    setCursorPosInScenePixels(0, 0);
    QTest::mouseMove(window, cursorWindowPos);
    QCOMPARE(window->cursor().shape(), Qt::BlankCursor);

    QQuickItem *layer1Delegate = nullptr;
    QVERIFY2(verifyLayerName("Layer 1", &layer1Delegate), failureMessage);
    QQuickItem *layer1VisibilityCheckBox = layer1Delegate->findChild<QQuickItem*>("layerVisibilityCheckBox");
    QVERIFY(layer1VisibilityCheckBox);

    const QVector<ImageCanvas::Tool> tools {
        ImageCanvas::PenTool,
        ImageCanvas::EyeDropperTool,
        ImageCanvas::EraserTool,
        ImageCanvas::FillTool,
        ImageCanvas::SelectionTool/*,
        ImageCanvas::CropTool TODO: not implemented yet*/
    };

    foreach (ImageCanvas::Tool tool, tools) {
        // Hide the layer.
        mouseEventOnCentre(layer1VisibilityCheckBox, MouseClick);
        QCOMPARE(layeredImageProject->currentLayer()->isVisible(), false);

        // Switch tool.
        QVERIFY2(switchTool(tool), failureMessage);

        // The cursor should be disabled for each tool.
        setCursorPosInScenePixels(0, 0);
        QTest::mouseMove(window, cursorWindowPos);
        if (window->cursor().shape() != Qt::ForbiddenCursor) {
            QString message;
            QDebug debug(&message);
            debug.nospace() << "Expected Qt::ForbiddenCursor for tool " << tool << ", but got " << window->cursor().shape();
            QFAIL(qPrintable(message));
        }

        // Make the layer visible again.
        mouseEventOnCentre(layer1VisibilityCheckBox, MouseClick);
        QCOMPARE(layeredImageProject->currentLayer()->isVisible(), true);

        // The cursor should not be ForbiddenCursor now.
        QVERIFY(window->cursor().shape() != Qt::ForbiddenCursor);
    }

    // Hide the layer.
    mouseEventOnCentre(layer1VisibilityCheckBox, MouseClick);
    QCOMPARE(layeredImageProject->currentLayer()->isVisible(), false);

    // Ensure that we can't actually do anything when the cursor is disabled.
    QVERIFY2(switchTool(ImageCanvas::PenTool), failureMessage);
    setCursorPosInScenePixels(10, 10);
    QTest::mouseMove(window, cursorWindowPos);
    QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, cursorWindowPos);
    QCOMPARE(layeredImageProject->currentLayer()->image()->pixelColor(10, 10), QColor(Qt::white));
}

One important thing that I think is worth mentioning is the approach to verifying the success of helper functions. QVERIFY and friends do not work outside of test functions. What you’ll see if you try to cause a failure outside of a test function invoked by the test framework is that the failure is printed in the test’s output, but does not prevent further execution of the test (it can’t, because the macros just return early, which would bring control back to the test function itself). This is a subtle issue that I think deserves some attention.

To get around this, I’ve copied the macros and removed their “Q” prefixes. As an example, here’s VERIFY:

#define VERIFY(statement) \
do { \
    if (!static_cast<bool>(statement)) { \
        failureMessage = #statement; \
        return false; \
    } \
} while (false)

All helper functions must use these macros. It’s not as good as having the code within the test functions themselves, because I don’t get useful line numbers (the failure points to the invocation of the function, not the position of the failure in the helper function). However, I can make up for this by providing better failure messages in the helper functions, and I’d rather this than having to duplicate the code. Using the first line of the test above as an example:

QVERIFY2(createNewLayeredImageProject(), failureMessage);

If a failure were to occur on this line in the createNewLayeredImageProject() helper:

VERIFY(nameTextField->property("text").toString() == QLatin1String("Layer 1"));

I would receive this failure message:

FAIL! : tst_App::disableToolsWhenLayerHidden() 'createNewLayeredImageProject()' returned FALSE. (nameTextField->property("text").toString() == QLatin1String("Layer 1"))
..\..\slate\tests\tst_app.cpp(3203) : failure location

As mentioned in the bug report, QCOMPARE can’t be easily duplicated, so I also can’t see what the actual value is, just the expected value.

If the QVERIFY2 above fails, execution eventually returns to cleanup(), where the failure message is cleared in preparation for the next test.

Project Structure

I took the lazy man’s approach to the project structure for the auto tests. Everything needed to build the application is in app.pri. That way, app.pro and tests.pro just need to include it.

… which means that all of the C++ files and resources (QML, images, etc.) are built twice! I would not recommend this, especially for larger projects (Slate is not that big, so it hasn’t bothered me yet). The standard, proper, non-lazy way of structuring a project like this is to move the application’s C++ and resources into a library, and then use that in the application and tests. One day I’ll do it the proper way, but so far I’ve been much more interested in adding cool features to my application than build systems. 🙂

Summary

Writing this application has been fun. It was also nice to dogfood Qt Quick Controls 2 in the process, as it’s helpful to be able to think like a user of the API.

In terms of things I have learned in the process, the first one that comes to mind is the undo framework.

I hope that this article was interesting. Feel free to explore the code in Slate and use it in your applications. 🙂

The post Slate: A Basic Pixel Art Editor Built with Qt Quick appeared first on Qt Blog.