Contributing to Qt? Come to Oslo in June 2015!


QtCS_2015It’s half a year since the 2014 Qt Contributors’ Summit, and now is a good time to give an early warning about next years QtCS.

We’ll be inviting you to Oslo in early June to come and discuss the current state and future of Qt.

The Qt Contributors’ Summit is an annual event where the people contributing to Qt gather to have fun, discuss where Qt is going and even code a little.

The plans include a pre-party / hack event before the actual summit at The Qt Company offices, two days of unconference style workshops and an evening out in Oslo.

Oslo is a beautiful city in June well worth a visit, especially when combined with the possibility to meet other Qt contributors.

If you aren’t an active contributor yet, don’t worry, you still have plenty of time to start contributing to Qt. Code, documentation, tests, forum activity, helping new users… everything you do to help out Qt is considered contributing.

QtCS 2014 in Berlin was a great event, let’s make QtCS 2015 even better.
The trolls welcome you to the home of Qt!

Qt 4.8.x Support to be Extended for Another Year


Standard Qt support for Enterprise licensees is for 2 years after the next minor or major Qt release is available. For Qt 4.8 it would mean support ending in December 2014, but we will extend it for a whole year to allow seamless migration to Qt 5.

Originally the support for Qt 4.8.x would have ended on 19th December 2014, 2 years after Qt 5.0.0 was released. We are now extending the standard support for 1 more year, meaning that it will not reach end of life until 19th December 2015. By 19th December 2015, Qt 4.8 will have been supported for four years.  Subsequently we now plan to have a Qt 4.8.7 release in Q1 2015. This is planned to be the last release of Qt 4.8.x series, unless there is a need to provide  an update due to a critical security issue.

So what does this mean for you? Well, if you are entitled to support then it means you can still use Qt 4.8.x safe in the knowledge that you will get the same level of support as before until the 19th December 2015. For older versions,we do have an extended lifetime option which you can find more information about by contacting The Qt Company.

We recommend that applications are ported to Qt 5.x as there are new versions of operating systems and compilers coming out which we can’t guarantee will be supported 100% by Qt 4.8. Qt 5 is a solid platform to migrate to with already version Qt 5.4 coming out soon. Therefore, now is the time to start seriously considering to port any existing applications if you haven’t already started doing so. Porting to Qt 5 is pretty straightforward and the documentation at http://qt-project.org/doc/qt-5/portingguide.html will help with that. If you need help, we and our service partners have services available for porting too – more information can be found at http://www.qt.io/services/.

Qt 5.4 Release Candidate Available


I am happy to announce that Qt 5.4 Release Candidate is now available.

After the Qt5.4 Beta release we have done some build & packaging related updates in addition to large number of error fixes based on feedback from Beta release

  • Mac OS X 10.10 is now used in packaging side
  • Android SDK is updated to 21.02
  • MinGW 4.9.1 is taken in the use
  • ICU is updated to 53-1
  • QtWebEngine is separated as its own installable binary package in the installers component tree

Starting from Qt 5.4 RC, Qt for iOS will be build as a fat binary supporting both 32- and 64-bit builds, fulfilling Apple’s requirement for new apps (see https://developer.apple.com/news/?id=10202014a). It also contains improved support for iPhone6/6+.

Qt 5.4 RC packages also contains Qt Creator 3.3 RC and in commercial packages candidates for new commercial value-add items as well.

Please take a tour & try Qt 5.4 Release candidate! It is quite close to final release so please give your feedback:

Please familiarize yourself to Qt 5.4 known issues wiki. For those who have not yet checked what Qt 5.4 brings, please refer to the Qt 5.4 Beta blog post, the wiki article listing new Qt 5.4 features, or the documentation snapshot for more details.

Qt 5.4 Release Candidate is available via online and offline installers. Installers are available from the Qt Account for commercial users of Qt. Open source users can download installers from qt.io downloads page. Qt 5.4 RC can be updated to existing online installation using the Maintenance Tool and selecting package manager.

Qt Creator 3.3 RC released


We are happy to announce the release of Qt Creator 3.3 RC1. Please have a look at the beta release blog post or the change log, for an overview of the new features and key improvements that are waiting for you in this new minor version.

This is the point where we think that we are almost ready to release 3.3.0, so it is a great time for you to download and try the RC, and give us last minute feedback through our bug tracker, the mailing list, or on IRC (#qt-creator on irc.freenode.net).

You find the opensource version on the Qt Project download page, and Enterprise packages on the Qt Account Portal.

Qt Weekly #21: Dynamic OpenGL implementation loading in Qt 5.4


In Qt 5.4 there is a new configure option on Windows: -opengl dynamic. This, in addition to -opengl desktop and -opengl es2, changes the OpenGL implementation (and implicitly the window system interface API) that Qt is built against. However, unlike the previously existing flags, dynamic is something different. Enabling it ensures that neither the Qt libraries nor the applications link directly to an OpenGL implementation, meaning that neither opengl32.lib nor libEGL.lib + libGLESv2.lib are passed to the linker. Instead, Qt will, upon application startup, choose the implementation to load.

Starting with the Qt 5.4 release candidate the previously ANGLE-only pre-built packages are changed to be dynamic builds. It is therefore time to take a closer look at this feature.

Up until Qt 5.4 the binary packages of Qt have been offered in two variants: desktop OpenGL (meaning opengl32.dll) and ANGLE. ANGLE provides an EGL and OpenGL ES 2.0 (soon 3.0) implementation by translating calls and shaders to Direct3D9 or 11. This is very handy for systems that have a lacking OpenGL implementation, for example due to not having the necessary graphics drivers or installed or due to using remote desktop. In addition, Direct3D 11 supports WARP, a software rasterizer.

The ability to work on a wider range of systems made ANGLE a promising prospect for providing OpenGL support for Qt and Qt Quick 2 on Windows, and so it became the default configuration setting. This is true in 5.4 too: configure defaults to ANGLE when no -opengl setting is specified.

However, the results were not always pretty. Offering multiple versions of the binaries causes confusion when getting started (which package to download?) and when deploying (which Qt libraries to ship with my application?). Relying exclusively on ANGLE is not an option in practice. Many desktop applications want OpenGL 3.x and 4.x features. On systems where a proper graphics driver is known to be available, the translation to Direct3D is unnecessary. Advanced modes of operation, like rendering from multiple threads have issues with ANGLE. Therefore the “desktop” OpenGL packages, meaning binaries linked against opengl32, had to be made available.

To eliminate the confusion, Qt 5.4 introduces the concept of dynamic OpenGL implementation selection. The binaries built in this mode are capable of operating with opengl32 (using WGL as the windowing system interface and regular OpenGL), ANGLE (using EGL and Open GL ES) or with a custom opengl32 variant (for example Mesa llvmpipe). As expected, Qt will perform some additional steps during application startup to decide which library to load. After that, all OpenGL calls (for example from Qt Quick) will be routed to this library, via QOpenGLFunctions.

The selection algorithm in Qt 5.4 is simple:

  1. Try opengl32 and check if OpenGL 2.0 functions are available.
  2. If this fails, try ANGLE.
  3. If initialization fails either due to missing ANGLE libraries or some other reason, try opengl32sw.dll. In practice this will be a software rasterizer based implementation. To make it easy to get started, a pre-built version of Mesa llvmpipe is bundled with the binary packages of Qt 5.4.

Pro tip: The debug output printed from the platform plugin can be very helpful to check which implementation gets loaded. To enable these prints, set the environment variable QT_LOGGING_RULES to qt.qpa.gl=true.

Why is this logic useful? Consider the following use cases:

  • When running on a modern system with the necessary graphics drivers installed, the first step will succeed so OpenGL is used normally.
  • When running the same application over remote desktop, the first step will fail and the fallback to ANGLE will be used instead. This functions better with remoting, so the application runs, just like locally.
  • Similarly, on a locked-down Windows 7 PC with no vendor-provided drivers installed, opengl32 will often turn out to be useless, providing only OpenGL 1.x. Direct3D and thus ANGLE may still be functional however.
  • In a virtual machine with limited or no accelerated graphics capabilities both step 1 & 2 may fail. In this case a build of Mesa llvmpipe can be utilized automatically, transparently to the application.

Applications that require desktop OpenGL and are not functional with OpenGL ES can use the QT_OPENGL environment variable or the Qt::AA_UseDesktopOpenGL application attribute before instantiating Q(Gui)Application. ANGLE can also be forced, if needed. For example, when playing video with Qt Multimedia, the best, accelerated path relies on Direct3D – ANGLE interop. Using a non-ANGLE implementation will still work, but possibly with reduced performance. Finally, in some scenarios (e.g. when targetting Windows XP) the robust solution is to deploy a software rasterizer (i.e. opengl32sw.dll) and force that with Qt::AA_UseSoftwareOpenGL in order to ensure a uniform experience across all the target systems. For the relevant settings, see the Windows-specific pages in the Qt documentation.

So how do you take this into use? It is easy: with Qt 5.4 the binary packages that previously were using ANGLE are now built with -opengl dynamic instead. This means that the “suffixless” packages that do not have opengl in the name (for instance, qt-enterprise-windows-x86-msvc2013_64-5.4.0.exe) are now capable of operating both with regular, desktop OpenGL, ANGLE and the software fallbacks, if needed. For the time being the “opengl” packages (built with -opengl desktop) are still being offered. However, these may disappear in Qt 5.5.

There is an important consequence of not linking directly to the OpenGL implementation: no OpenGL functions like glClear() are callable directly anymore. Applications that want to be dynamically switchable must always use QOpenGLFunctions and be prepared to function both on OpenGL and OpenGL ES 2.0. For Qt itself, this is not a problem. All the standard Qt modules, including Qt Quick 2 (qtdeclarative), have been updated to make sure they function as expected in all configurations. For examples, see the documentation and our earlier post about QOpenGLWidget.

Note that this dynamic mode of operation and in particular the software rasterizer fallback are targeted towards general GUI applications based on Qt Quick 2. Applications with heavy OpenGL graphics, for example visualization or games, are obviously not in scope here. Such applications are expected to continue to rely exclusively on modern OpenGL and dedicated graphics hardware. They should enforce a given implementation via QT_OPENGL or the application attributes, so they can continue to use direct OpenGL function calls and other features, like the versioned OpenGL function wrappers. Just add LIBS += -lopengl32 to the application’s .pro file. The migration of an application that today uses and requires the desktop OpenGL builds of Qt is as simple as adding a line to its main() function and a line to the .pro project file. This is naturally not always an option, and this is the reason why Qt 5.4 continues to offer some of the desktop OpenGL packages. The future however lies in the dynamic builds, so applications are expected to gradually migrate to it.

Reminder: Desktops DevRoom @ FOSDEM 2015

We are less than 10 days away from the deadline for the Desktops DevRoom at FOSDEM 2015, the largest Free and Open Source event in Europe.

Do you think you can fill a room with 200+ people out of 6,000+ geeks? Prove it!

Check the Call for Talks for details on how to submit your talk proposal about anything related to the desktop:

  • Development
  • Deployment
  • Community
  • SCM
  • Software distribution / package managers
  • Why a particular default desktop on a prominent Linux distribution ;-)
  • etc

http://www.elpauer.org/2014/10/fosdem-2015-desktops-devroom-call-for-talks/

Qt Downloads moving to qt.io


QtProject_02-Download_Page_768x400As you have noticed from the banner on the qt-project.org download page, downloads are moving to qt.io. This is part of unifying Qt and defragmenting the community. The intention is to gradually move to using one Qt website for all services.

Downloads have been available on the unified Qt site for some time now, and everything has been working well there, so today we will start forwarding all traffic that is coming to qt-project.org/downloads to the qt.io/download page.

On the unified Qt download page you’ll find all the downloads as before plus the commercial options on one page.

Next steps

Next in the site unification is the moving of the Qt blog and documentation to the new site and making a unified login service for all the Qt online services.

The Qt blog will be moving to the qt.io domain with a new layout in the coming weeks. This change will be straightforward and isn’t expected to cause any issues.

We received good feedback from you on the new look and feel of the documentation. Thank you. We made changes based on the feedback, and now the Qt 5.4.0 release documentation will be available on doc.qt.io. You can already see the release candidate documentation at doc.qt.io. The rest of the documentation will also be moving to the new address later on.

The new unified login, Qt Account, will enable you to use the same credentials for forums, wiki, bugs and all the other services. We will start moving services that need a login to qt.io as soon as the new login system is properly tested and available for use. The current plan is that in early 2015 we should have most of the developer services in the unified Qt site.

If you have feedback or questions, please leave a comment!

Qt on Android Episode 5

After we’ve seen how to set up the development environment, how to use Qt on Android and what deployment systems are available and how to sign the final package, it’s time to move forward. In this article we are going to learn about JNI.

Why do we need JNI?

Because it is impossible for Qt to implement all Android features. To use any of them we’ll need to use JNI to access them. JNI the only way to do calls to/from Java world from/to native (C/C++) world.

JNI intro

In this article we’ll learn the basics of the JNI, in the next article(s) we’re going to learn how to use this knowledge to correctly extend Qt on Android apps.

There is tons and tons of information on this matter on the net, in this article I’m focusing only on how to do JNI on Android using Qt. Starting with 5.2, Qt ships Qt Android Extras module. This module makes our life much more pleasant when we’ll have to do JNI.

There are two use cases:

  • Call a Java function from C/C++
  • Callback a C/C++ function from Java

Call a Java function from C/C++

Calling a Java function from C/C++ using Qt Android Extras module is quite easy.

First let’s create a Java static method:

// java file android/src/com/kdab/training/MyJavaClass.java
package com.kdab.training;

public class MyJavaClass
{
    // this method will be called from C/C++
    public static int fibonacci(int n)
    {
        if (n < 2)
            return n;
        return fibonacci(n-1) + fibonacci(n-2);
    }
}

So, we defined fibonacci static method into MyJavaClass class into com.kdab.training package. This method returns the computed fibonacci number.

Now let’s see how to call it from Qt. The first step is to make sure we are using the android extras, so we need to add it to our .pro file.

# Changes to your .pro file
# ....
QT += androidextras
# ....

Then do the actual call:

// C++ code
#include <QAndroidJniObject>
int fibonacci(int n)
{
    return QAndroidJniObject::callStaticMethod<jint>
                        ("com/kdab/training/MyJavaClass" // class name
                        , "fibonacci" // method name
                        , "(I)I" // signature
                        , n);
}

Yes, that’s all folks!

Let’s take a closer look to this code and see what we have here:

  • we are using QAndroidJniObject::callStaticMethod to call a Java static method.
  • first argument is the fully-qualified class name. The fully-qualified name for a class (or interface) is the package name (com/kdab/training) followed by the class/interface name(MyJavaClass), separated by a slash (/) (NOT by a period, the period is used only in Java world not in C/C++ world!)
  • the next argument is the method name
  • the next is the method signature
  • the next arguments are the arguments that will be passed to the java function

Please check QAndroidJniObject documentation for more information about method signature and the arguments types.

Callback a C/C++ function from Java

In order to callback a C/C++ function from Java you need to do the follow steps:

  • declare the native method(s) in Java, using native keyword
  • register native method(s) in C/C++
  • do the actual call

Declare the native method(s) in Java, using native keyword.

Let’s change the previous java code a little bit:

// java file android/src/com/kdab/training/MyJavaClass.java
package com.kdab.training;

class MyJavaNatives
{
    // declare the native method
    public static native void sendFibonaciResult(int n);
}

public class MyJavaClass
{
    // this method will be called from C/C++
    public static int fibonacci(int n)
    {
        if (n < 2)
            return n;
        return fibonacci(n-1) + fibonacci(n-2);
    }

    // the second method that will be called from C/C++
    public static void compute_fibonacci(int n)
    {
        // callback the native method with the computed result.
        MyJavaNatives.sendFibonaciResult(fibonacci(n));
    }
}

Let’s take a closer look to this code and see what we have here:

  • personally, I prefer to keep all my native method(s) in a separate class, so, I declared sendFibonaciResult native method into MyJavaNatives class into com.kdab.taining package. This native method will be used by compute_fibonacci static method to callback the C/C++ world to send the computed result instead to return it as fibonacci method does.
  • compute_fibonacci, this method will be called from C/C++, but instead to return the result as fibonacci method does, it uses sendFibonaciResult native method to callback the C/C++ world to end the result.

If you try only this code it will fail, because sendFibonaciResult is not registered, and Java VM doesn’t know it yet.

C/C++ register native methods

Now let’s see how to register the function in C/C++.

First thing you need to know is that you can register only function(s). You can NOT register C++ class (non-static) members!

There are two ways to register native methods, we are going to check both ot them:

Registering functions using Java_Fully_Qualified_ClassName_MethodName

#include <jni.h>
#include <QDebug>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT void JNICALL
  Java_com_kdab_training_MyJavaNatives_sendFibonaciResult(JNIEnv *env,
                                                    jobject obj,
                                                    jint n)
{
    qDebug() << "Computed fibonacci is:" << n;
}

#ifdef __cplusplus
}
#endif

Let’s take a closer look to this code and see what we have here:

  • First thing we’ve seen, is that all the functions must be exported as C functions and NOT as C++ functions!
  • The function name MUST follow the next template: Java word, followed by the package name, then followed by the class name, then followed by the method name,separated by an underscore (_)
  • When JavaVM loads the .so file, it will search for this template and it will automatically register all your functions for you
  • the first argument (env) of the function is a pointer to JNIEnv object.
  • the second argument (obj) is a reference to the Java object inside which this native method has been declared.
  • the first and second arguments are mandatory for every function that you’ll register.
  • the next arguments must match the java native method arguments. So, our third argument is actually our first (and only) java native method argument. This is the argument that compute_fibonacci will pass to sendFibonaciResult native method when it calls it.

Using this method to register is quite easy to declare and register, but it has a few disadvantages:

  • the function names are huge:

    Java_com_kdab_training_MyJavaNatives_sendFibonaciResult

  • the library must to export all functions
  • unsafer, there is no way for the JavaVM to check the function signature, because the functions are exported as C functions and NOT as C++ functions!

Use JNIEnv::RegisterNatives to register native functions

In order to use JNIEnv::RegisterNatives to register native functions, we need to do the following 4 steps to use it:

  • step 1: we need get access to an JNIEnv pointer. The easiest way is to define and and export JNI_OnLoad function, (once per .so file) in any .cpp file we like.
  • step 2: create a vector with all C/C++ methods that we want to register.
  • step 3: find the ID of java class that declares these methods using JniEnv::FindClass
  • step 4: call JNIEnv::RegisterNatives(java_class_ID, methods_vector, n_methods)
// C++ code
#include <jni.h>
#include <QDebug>

// define our native method
static void fibonaciResult(JNIEnv */*env*/, jobject /*obj*/, jint n)
{
    qDebug() << "Computed fibonacci is:" << n;
}

// step 2
// create a vector with all our JNINativeMethod(s)
static JNINativeMethod methods[] = {
    { "sendFibonaciResult", // const char* function name;
        "(I)V", // const char* function signature
        (void *)fibonaciResult // function pointer 
    }
};

// step 1
// this method is called automatically by Java VM
// after the .so file is loaded
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
{
    JNIEnv* env;
    // get the JNIEnv pointer.
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)
           != JNI_OK) {
        return JNI_ERR;
    }

    // step 3
    // search for Java class which declares the native methods
    jclass javaClass = env->FindClass("com/kdab/training/MyJavaNatives");
    if (!javaClass)
        return JNI_ERR;

    // step 4
    // register our native methods
    if (env->RegisterNatives(javaClass, methods,
                            sizeof(methods) / sizeof(methods[0])) < 0) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

Let’s check the code for a better understanding:

  • static void fibonaciResult(JNIEnv */*env*/, jobject /*obj*/, jint n) it is the method that we’re registering and which Java VM will call.
  • the first argument (env) of the function is a pointer to JNIEnv object.
  • the second argument (obj) is a reference to the Java object inside which this native method has been declared.
  • the first and second arguments are mandatory for every function that you’ll register.
  • the next arguments must match the java native method arguments. So, our third argument is actually our first (and only) java native method argument. This is the argument that compute_fibonacci will pass to sendFibonaciResult native method when it calls it.
  • we add the method to a vector (methods) of JNINativeMethod structures.
  • JNINativeMethod structure has the following fields:
    • const char* name – it is the function name, it has to be exactly as the native function name that we’ve declared in Java
    • const char* signature – it is the function signature, it has to match the native function arguments that we’ve declared in Java
    • void* fnPtr – it is the C/C++ function pointer. In our case it’s a pointer to static void fibonaciResult(JNIEnv */*env*/, jobject /*obj*/, jint n) function. As you can see the C/C++ function name doesn’t matter, the Java VM needs only a pointer to it.
  • the rest of the code is clear and easy and I don’t think it needs any explanations than the comments.

Even if it looks a little bit complicated to use it, this method has the following advantages:

  • the C/C++ function can have any name you want
  • the library needs to export only one function (JNI_OnLoad)
  • safer, because the Java VM checks the declared signature

It’s just a matter of taste which method you decide to use to register your native functions. I do recommend you to use JNIEnv::RegisterNatives as it offers you extra protection because the Java VM checks the functions signature and it throws an exception if it doesn’t match.

Conclusion

In this article we’ve learned the basics of the JNI, in the next article(s) we’re going to learn how to use this knowledge to correctly extend Qt on Android apps. We’ll talk more about Qt on Android apps architecture, how to extend the Java part of your application and we’ll take a real life example to show how to correctly do safe calls from Qt thread to Android UI thread and vice-versa.

Thank you for your time!

The post Qt on Android Episode 5 appeared first on KDAB.

User Experience Design Principles of a Natural User Interface (NUI)

In a previous blog post (Defining a Natural User Interface) I explained how finding a clear and concise definition of a Natural User Interface (NUI) was not easy. Finding a clear and concise list of user experience design principles for a NUI is even more challenging. An obvious reason for this is that NUIs encompass a broad range of possibilities, and it’s difficult to be general enough to cover the range and at the same time specific enough to be useful.

QML wrappers for native Android components

TL;DR It might be simpler than you think to wrap native UIs with the QtQml module, but it does require a good understanding of the underlying platform

In my previous post, I showed how you can work with platform-native classes and use the QtAndroidExtras module to create UIs from code. One of the downsides was the extra code complexity you had to manage. The "Qt way" of doing UIs is, however, by using QML, for the reasons of brevity, development speed and flexibility. I cobbled together a custom Android component module to demonstrate this (sources available on GitHub) - the 40+ thick line C++ UI example suddenly becomes a lot more readable and fun to work with.



Qt does have a solution for native-looking UIs on Android in the form of QtQuick.Controls, so my reasoning here is more to show

  • what are the advantages of custom components
  • how custom components are done
  • what are the pitfalls of custom component sets
What are the advantages? If there is no native-looking component set, it's quite clear - you simply have no alternative. If QtQuick.Controls does exist for your platform (see the case of Android), there is still a number of reasons why you might consider going custom. First, you get the full functionality and availability of the platform-native set. QtQuick.Controls gives you something that is closer to a lowest common denominator, with a lot of platform-specific components/functionality missing and occasionally some input method quirks. By skipping this, you create UIs which are not just "close-to-platform-native", but effectively *are* platform native. Second, you get the full performance. By having a wrapper, there will still be a slight penalty for loading Qt, and parsing/constructing the QML objects, but there is no compromise once the UI is instantiated. I personally also like that you can use the platform-native documentation and examples, since you're just using QML syntax, but class names, properties and general usage pattern remain the same as on the platform.

How does one go about creating a new component set? As you've seen from the first QML snippet, all we really need is the QtQml module. If you start creating with a completely custom *native* component set (ie not deriving from an existing QtQuick or QtQuick.Controls base) you get a really basic set of components to work with, namely Component, QtObject, Binding, Connections, Timer. All you native components will be actually QObject derived C++ objects, registered with the QML system, as described here. The classes themselves are still plain Qt classes, here's how my activity.h looks like:



After that, you need to register every such object with the QML engine (usually in your main.cpp) :

qmlRegisterType("OutQross.Android", 0, 1, "Activity");

With this we can start instantiating our custom objects from QML. The QtObject class/element unfortunately does not have a lot of the functionality normally coming from Item (including having a default children property), so I created an OutQrossItem helper class for this purpose, which is the base class for all my Qml elements.



Finally, let's see the gritty innards of a custom component class, an Android Button in this case



As you can see, I still use the same UI inflate paradigm as Android to actually instantiate the button (this way we also avoid the question of the order of object initialization or property settings), and you can also see how a property can we wrapped. This means that the full power of QML - bindings, signals/slots and JS are available to us as the properties are mapped to the native components. This is crucial if you are building your own component sets, as otherwise you're just making a syntax converter - and this is also the answer to how this is different to just converting QML to Android .XML UIs or vice versa.

For completeness' sake, let's mention that the .APK was 6.9MB and the memory usage of the HelloWorld app was 61510kb (about halfway between the version in my previous blog post and the "full" QtQuick experience)

There are some pitfalls as well. First, while not rocket science, it's actual work. If you have an extensive GUI widget set or library (like Android), you probably want to use or write some sort of wrapper code generator as manually creating and maintaining a full wrapper set can be daunting. Second, there might be specific UI caveats - for example, in the case of my Android example, to keep it simple, I'm not actually running on the UI thread. This means that in my particular implementation while native component and property updates happen via the bindings, they might not immediately appear on the screen. This can be resolved, but it does require a very good understanding of how the native platform works. My advice is that you shouldn't consider writing wrappers because you don't know how the platform-native UIs work - it should primarily be done to accelerate future development and prototyping.

Injeqt 0.9.0 released

First official (beta!) version of Injeqt dependency injection library for Qt was released today. I can be downloaded from GitHub releases page.

For last 3 weeks I was working on Kadu and switching some parts of it to use Injeqt for its objects and services wiring. As it turns out, it all works very well already. There is no need to postpone Injeqt release until it gains additional features (and I have big plans for it).

0.9.x series will continue until Kadu 2.0 release with only bugfixes. I don't expect a lot of them (Injeqt has very nice unit tests coverage), but better safe than sorry. Exported API is very minimal and should not be changed (only extended) in a long time.

If you wish to try it - please do it now. I would be happy to see more use cases and real world applications before committing 100% to 1.0 release.

Enjoy!

Qt Weekly #20: Completing the offering: QOpenGLWindow and QRasterWindow


Together with the introduction of QOpenGLWidget, Qt 5.4 adds two more classes: QOpenGLWindow and QRasterWindow. Let us now look at the list of native window classes and OpenGL container widgets. The list may look long and confusing at first glance, but it is all quite logical so everything will fall into place quickly:

  • QWindow: Represents a native window in the windowing system. The fundamental window class in Qt 5. Every top-level window, be it widget or Quick based, will have a QWindow under the hood. Can also be used directly, without widgets or Quick, both for OpenGL and software rendered graphics. Has no dependencies to the traditional QWidget stack.
  • QRasterWindow: Convenience wrapper over QWindow for software rendered graphics.
  • QOpenGLWindow: Convenience wrapper over QWindow for OpenGL graphics. Optionally backed by a framebuffer object, but the default behavior (and thus performance) is equivalent to QWindow.
  • QOpenGLWidget: The modern replacement for Qt 4’s QGLWidget. A widget for showing OpenGL rendered content. Can be used like any other QWidget. Backed by a framebuffer object.
  • QQuickWindow: A QWindow subclass for displaying a Qt Quick 2 (QML) scene.
  • QQuickView: Convenience wrapper for QQuickWindow for easy setup of scenes loaded from QML files.
  • QQuickWidget: The equivalent of QQuickView in the QWidget world. Like QOpenGLWidget, it allows embedding a Qt Quick 2 scene into a traditional widget-based user interface. Backed by a framebuffer object.

For completeness sake, it is worth noting two additional APIs:

  • QQuickRenderControl: Allows rendering Qt Quick 2 scenes into framebuffer objects, instead of targeting an on-screen QQuickWindow.
  • QWidget::createWindowContainer(): In Qt 5.1 & 5.2 the only way to embed Qt Quick 2 content (or in fact any QWindow) into a widget-based UI was via this function. With the introduction of QQuickWidget and QOpenGLWidget this approach should be avoided as much as possible. Its usage should be restricted to cases where it is absolutely neccessary to have a real native window embedded into the widget-based interface and the framebuffer object-based, more robust alternatives are not acceptable, or where it is known in advance that the user interface layout is such that the embedded window will not cause issues (for example because the embedded window does not care about input, is not part of complex layouts that often get resized, etc.).

We will now take a look at no. 2 & 3, the QWindow convenience wrappers.

Ever since the introduction of the QPA architecture and QWindow, that is, since Qt 5.0, it has been possible to create windows based on QWindow that perform custom OpenGL drawing. Such windows do not use any QWidget-derived widgets, instead they render everything on their own. A game or a graphics intensive application with its own custom user interface is a good example.

This is the most lightweight and efficient way to perform native OpenGL rendering with Qt 5. It is free from the underlying complexities of the traditional widget stack and can operate with nothing but the QtCore and QtGui modules present. On space-constrained embedded devices this can be a big benefit (no need to deploy QtWidgets or any additional modules).

Power and efficiency comes at a cost: A raw QWindow does not hide contexts, surfaces and related settings, and it does not provide any standard mechanism for triggering updates or opening a QPainter (backed by the OpenGL 2.0 paint engine) targeting the window’s associated native window surface.

For example, a simple QWindow subclass that performs continous drawing (synchronized to the display’s vertical refresh by the blocking swapBuffers call) both via QPainter and directly via OpenGL could look like the following:

class MyWindow : public QWindow
{
public:
    MyWindow() : m_paintDevice(0) {
        setSurfaceType(QSurface::OpenGLSurface);

        QSurfaceFormat format;
        format.setDepthBufferSize(24);
        format.setStencilBufferSize(8);
        setFormat(format);

        m_context.setFormat(format);
        m_context.create();
    }

    ~MyWindow() { delete m_paintDevice; }

    void exposeEvent(QExposeEvent *) {
        if (isExposed())
            render();
    }

    void resizeEvent(QResizeEvent *) {
        ...
    }

    void render() {
        m_context.makeCurrent(this);

        if (!m_paintDevice)
            m_paintDevice = new QOpenGLPaintDevice;
        if (m_paintDevice->size() != size())
            m_paintDevice->setSize(size());

        QOpenGLFunctions *f = m_context.functions();
        f->glClear(GL_COLOR_BIT | GL_DEPTH_BUFFER_BIT);
        // issue some native OpenGL commands

        QPainter p(m_paintDevice);
        // draw using QPainter
        p.end();

        m_context.swapBuffers(this);

        // animate continuously: schedule an update
        QCoreApplication::postEvent(new QEvent(QEvent::UpdateRequest), this);
    }

    bool event(QEvent *e) {
        if (e->type() == QEvent::UpdateRequest) {
            render();
            return true;
        }
        return QWindow::event(e);
    }

private:
    QOpenGLContext m_context;
    QOpenGLPaintDevice *m_paintDevice;
};

Now compare the above code with the QOpenGLWindow-based equivalent:

class MyWindow : public QOpenGLWindow
{
public:
    MyWindow() {
        QSurfaceFormat format;
        format.setDepthBufferSize(24);
        format.setStencilBufferSize(8);
        setFormat(format);
    }

    void resizeGL(int w, int h) {
        ...
    }

    void paintGL() {
        QOpenGLFunctions *f = context()->functions();
        f->glClear(GL_COLOR_BIT | GL_DEPTH_BUFFER_BIT);
        // issue some native OpenGL commands

        QPainter p(this);
        // draw using QPainter

        // animate continuously: schedule an update
        update();
    }
};

That is a bit shorter, isn’t it. The API familiar from QOpenGLWidget (initializeGL/resizeGL/paintGL) is there, together with the update() function and the ability to easily open a painter on the window. While QOpenGLWindow, when used this way, does not remove or add anything compared to raw QWindow-based code, it makes it easier to get started, while leading to shorter, cleaner application code.

QRasterWindow follows the same concept. While everything it does can be achieved with QWindow and QBackingStore, like in the raster window example, it is definitely more convenient. With QRasterWindow, the example in question can be reduced to something like the following:

class RasterWindow : public QRasterWindow
{
    void paintEvent(QPaintEvent *) {
        QPainter painter(this);
        painter.fillRect(0, 0, width(), height(), Qt::white);
        painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QRasterWindow"));
    }
};

Painters opened on a QOpenGLWindow are always backed by the OpenGL paint engine, whereas painters opened on a QRasterWindow are always using the raster paint engine, regardless of having OpenGL support enabled or available at all. This means that QRasterWindow, just like the traditional widgets, is available also in -no-opengl builds or in environments where OpenGL support is missing.

Now, what about incremental rendering? In the QRasterWindow example above there is strictly speaking no need to clear the entire drawing area on each paint. Had the application wished so, it could have continued drawing over the existing, preserved backing store content in each invocation of paintEvent(), as long as the window did not get resized. With QGLWidget, QWindow or the QOpenGLWindow example shown above this is not possible, unless preserved swap is enabled via the underlying windowing system interface, since on each paintGL() call the color buffer contents is effectively undefined. QOpenGLWidget does not have this problem since it is backed by a framebuffer object instead of targeting the window surface directly. The same approach can be applied to QOpenGLWindow too. Hence the introduction of the different update behaviors that can be set on a QOpenGLWindow.

Take the following QWindow-based code:

class MyWindow : public QWindow
{
public:
    MyWindow() : m_paintDevice(0), m_fbo(0), m_iter(0) {
        ... // like in the first snippet above
    }

    ...

    void render() {
        m_context.makeCurrent(this);

        if (!m_fbo || m_fbo->size() != size()) {
            delete m_fbo;
            m_fbo = new QOpenGLFramebufferObject(size(), QOpenGLFramebufferObject::CombinedDepthStencilAttachment);
            m_iter = 0;
        }

        if (!m_paintDevice)
            m_paintDevice = new QOpenGLPaintDevice;
        if (m_paintDevice->size() != size())
            m_paintDevice->setSize(size());

        m_fbo->bind();
        QPainter p(m_paintDevice);

        // Draw incrementally using QPainter.
        if (!m_iter)
            p.fillRect(0, 0, width(), height(), Qt::white);

        p.drawText(QPointF(10, m_iter * 40), QString(QStringLiteral("Hello from repaint no. %1")).arg(m_iter));

        ++m_iter;

        p.end();
        m_fbo->release();

        // Now either blit the framebuffer onto the default one or draw a textured quad.
        ...

        m_context.swapBuffers(this);

        // animate continously: schedule an update
        QCoreApplication::postEvent(new QEvent(QEvent::UpdateRequest), this);
    }

private:
    QOpenGLContext m_context;
    QOpenGLPaintDevice *m_paintDevice;
    QOpenGLFramebufferObject *m_fbo;
    int m_iter;
};

For brevity the code for getting the framebuffer’s content onto the window surface is omitted. With QOpenGLWindow’s PartialUpdateBlit or PartialUpdateBlend the same can be achieved in a much more concise way. Note the parameter passed to the base class constructor.

class MyWindow : public QOpenGLWindow
{
public:
    Window() : QOpenGLWindow(PartialUpdateBlit), m_iter(0) {
        QSurfaceFormat format;
        format.setDepthBufferSize(24);
        format.setStencilBufferSize(8);
        setFormat(format);
    }

    void resizeGL(int, int) {
        m_iter = 0;
    }

    void paintGL() {
        QPainter p(this);

        // Draw incrementally using QPainter.
        if (!m_iter)
            p.fillRect(0, 0, width(), height(), Qt::white);

        p.drawText(QPointF(10, m_iter * 40), QString(QStringLiteral("Hello from repaint no. %1")).arg(m_iter));

        ++m_iter;

        update();
    }

private:
    int m_iter;
};

That’s it, and there is no code omitted in this case. Internally the two are approximately equivalent. With the QOpenGLWindow-based approach managing the framebuffer object is no longer the application’s responsibility, it is taken care by Qt. Simple and easy.

Native UI in Qt on Android (without QtQuick.Controls)

TL;DR - Yes, you can do a fast, no-compromise native UI without QtQuick on Android, and you'll use a lot less resources than a full QtQuick app, at the cost of somewhat messy code.

Nowadays Qt for Android comes with a nice QtQuick-compatible set of native-looking Android controls in the form of QtQuick.Controls. This blog post is not about them :) Let's go a bit off the beaten path - can we create a Qt application with a graphical, performant, native UI without using QtQuick (or QWidgets)? What are the advantages and disadvantages to such an approach?

In a blog post Artem Marchenko lists a couple of approaches how a Qt based native-looking UI would be possible, but these all include QML in one form another, which is not quite what we're after in this particular case. Another interesting project is Ben Lau's QAndroidRunner which combines native UIs and QML. Here, however, we'll focus how far can you get without ever touching QML or QtQuick.

The key to using Android classes and resources is the QAndroidExtras module (it's an add-on module that has been around since Qt 5.2). The class I'm heavily relying on is QAndroidJNIObject which allows Java class/object instantiation and manipulation. Thus, the two includes we'll use to enable creating native objects are

#include <QtAndroidExtras/QAndroidJniObject>
#include <QtAndroidExtras/QtAndroid>

When it comes to Android UIs, the first stop is the Activity - on Android activities are how we interact with the user. This is effectively a window on which we put all our widgets and UI elements. Luckily, starting with Qt 5.3, we have a simple way of retrieving an activity with the QtAndroid::androidActivity function.

QAndroidJniObject activity = QtAndroid::androidActivity();

Let's get to the meat of the matter - we'll need to create native layout and widget objects and set their parameters from Qt. Here's how that looks like

QAndroidJniObject layout("android/widget/RelativeLayout", 
"(Landroid/content/Context;)V",
activity.object());

The first parameter is the Java class name, the second the Java method signature (see here for a few more examples, "javap -s" is your friend), and the third parameter is the actual object used as the parameter (as activity is a QAndroidJniObject, we need to use the object() method). With the call above we create a Layout and assign it to the activity.

We can also call methods of our objects:

button.callMethod<void>("setTextColor", "(I)V", -1); // Color.WHITE

Putting all these together, we can create a basic, but full-fledged Android application:



...resulting in...


This "Hello world" code is clearly quite a bit more complicated than it's QML counterpart:



The complexity downside is quite obvious - it's hard to beat QML's brevity and clarity. Another, perhaps not immediately visible downside is that this particular style of C++ code is more error-prone - there is no type safety as the objects are generated dynamically, so on errors, it's easy to end up with NULL objects and segfaults.

Why would anyone use it, then? Let's take a look at resource consumption:

The APK size for the non-QML Android version of Hello World is 5,663,420 bytes, while the APK with the Controls included is 10,406,706. The difference could be even bigger, though, as the default android mkspec includes a few extra Qt modules. It should be possible to get the minimum APK size down to around 3MB. If you are using Ministro, this might not be as big of an issue, but for self-contained applications, or embedded, this can shave a few precious megabytes off of the application.

It's not just flash storage and network bandwidth we can save though - there is a memory-usage difference as well. While adb dumpsys meminfo is not a perfect way to measure memory usage, it is indicative:

40761 kB: org.qtproject.example.QtJavaHelloWorld
77531 kB: org.qtproject.example.QmlHelloWorld

While a ~35MB of minimum framework tax might not sound like much in the era of devices with several gigabytes of RAM, using a complex QML structure can inflate the difference further. On embedded and legacy devices every megabyte counts, so even this 35MB difference can help (plenty of low-end Android devices with 256-512MB of RAM).

There are other benefits to not using QtQuick controls - controls are a "lowest common denominator" approach designed to easy cross-platform development. It does not contain all UI widgets and elements, nor functionality offered by Android APIs. By using the approach as demonstrated, there is no compromise - the full UI arsenal is at our disposal, at the exact same performance as for regular Java apps.

Finally, the QtQuick controls version depends on the Qt version shipped with the application. In the non-Controls version we always get the native controls, with native styling and behavior, even if the platform release is newer than what our QtQuick.Controls version supports.

To summarize, the advantages to a Controls-less approach are:
  • Native UI performance
  • Smaller APK size (currently at least ~5MB less, potentially ~7MB)
  • Smaller memory footprint (35MB for Hello world, more as app complexity increases)
  • Full UI functionality available, regardless of Qt version
  • Styling always latest platform-native
Disadvantages

  • Not cross-platform
  • Significantly increased code complexity, especially with more complex UIs
  • Harder to debug due to dynamic nature and lack of tooling support

It's actually possible to mitigate some of the disadvantages, so stay tuned for further posts on this topic!

C++14 for Qt programmers

C++14 is the name of the version of the standard to be released this year. While C++11 has brought many more feature that took time to be implemented by the compilers, C++14 is a much lighter change that is already implemented by compilers such as clang or gcc.

Qt 5 already was adapted in many ways so you can make use of the new features of C++11. You can read about that in my previous article. C++11 in Qt5 . This article mention some of the changes in C++14 and the impact on Qt users.

Generic lambda

C++11 introduced lambda function, and Qt5 allow you to connect signals to them with the new connect syntax. C++14 simplify the use of lambda function as the arguments can be automatically deduced. You can use auto as parameter type instead of explicitly writing the type.

 connect(sender, &Sender::valueChanged, [=](const auto &newValue) {
        receiver->updateValue("senderValue", newValue);
    });

Internally, lambda function is just a functor object with an operator(). With generic lamdba, that operator is now a templated function. I had to make a change which was included in Qt 5.1 already to support such functors.

C++14 also adds the possibility to have expressions in the capture.

 connect(sender, &Sender::valueChanged, [reciever=getReciever()](const auto &newValue) {
        receiver->updateValue("senderValue", newValue);
    });

Relaxed Constant expressions

C++11 came with the new constexpr keyword. Qt 4.8 has added a new macro Q_DECL_CONSTEXPR that expands to constexpr when supported, and we have been using it for many function when possible in Qt 5.

C++14 is relaxing the rules of what is allowed in a constexpr. C++11 rules were only allowing a single return statement, and could only be applied on const functions. C++14 allow pretty much any code that can be evaluated at compile time.

/* This function was not valid in C++11 because it is composed of several statements,
 * it has a loop, and a local variable. It is now allowed in C++14 */
constexpr int myFunction(int v) {
  int x = 1;
  while (x < v*v)
    x*=2;
  return x;
}

Member functions declared as constexpr in C++11 were automatically considered as const. It is no longer the case as non-const function can also be constexpr.
The result of this change is that constexpr member functions that were not explicitly marked as const will change const-ness in C++14, and this is a binary incompatible change. Fortunately in Qt, all Q_DECL_CONSTEXPR member functions were also explicitly declared as const to keep binary compatibility with non C++11 code.

So now we can start annotating non-const functions such as operator= of many classes. For this reason, Qt 5.5 will come with a new macro Q_DECL_RELAXED_CONSTEXPR which expands to constexpr when the compiler is in a C++14 mode. We will then be able to start annotating relevant functions with Q_DECL_RELAXED_CONSTEXPR

Small features

C++14 also comes with a lot of small convenience feature. That do not have direct impact on Qt, but can be used in your program if you enable C++14. We just made sure that tools like moc can handle them.

Group Separators in Numbers

If you are writing huge constant in your code, you can now now use ' as a group separator:

    int i = 123'456'789;

Binary literal

In C++ you can write your number in decimal, octal (starting your number with 0), hexadecimal (starting with 0x). You can now also write in binary by using the 0b prefix.

    int i = 0b0001'0000'0001;

Automatic return type detection

If you have an inline function, you can use auto as a return type, and you do no longer need to specify it. The compiler will deduce it for you

// return type auto detected to be 'int'
auto sum(int a, int b) { return a+b; }

This is, however, not supported for slot or invokable method as moc would not be able to detect the return type

Variable template

You could have functions template or class template. Now you can also have variable template.

template<typename T> const T pi = 3.141592653589793;
/*...*/
    float f = pi<float>;
    double d = pi<double>;

Uniform initialization of structures with non static data member initializers

In C++11, you can use the uniform initialization to initialize a struct that has no constructor by initializing all the members. C++11 also added the possibility to have inline non static data member initiazers directly in the class declaration. But you could not use the two at the same time. In C++14, you can. This code works and do what you would expect:

struct MyStruct {
    int x;
    QString str;
    bool flag = false;
    QByteArray str2 = "something";
};

    // ...
    // did not compile in C++11 because MyStruct was not an "aggregate" 
    MyStruct s = { 12, "1234", true };
    Q_ASSERT(s.str2 == "something");

Reference Qualifiers

This is not a C++14 feature, but a C++11 change. But we only started to make use of this late in the Qt5 cycle and I did not mention it in a previous blog post so I'll mention it here.

Consider this code:

    QString lower = QString::fromUtf8(data).toLower();

fromUtf8 returns a temporary. It would be nice if the toLower could re-use the memory allocated by the string and do the transformation in place. Well that's what the reference qualifiers for member functions are for.

(code simplified from qstring.h:)

class QString {
public:
    /* ... */

    QString toLower() const &
    { /* ... returns a copy with lower case character ... */ }
    QString toLower() &&
    { /* ... do the conversion in-place ... */ }
    
    /* ... */
};

Notice the '&' and '&&' at the end of toLower. Those are references qualifier and let overload a function depending on the reference type of the 'this' pointer, just like the const qualifier let overload on the constness of this. When toLower is called on a temporary (a rvalue reference) the second overload (the one with &&) will be chosen and the transformation will be done in place.

The functions that benefit from the optimisation in Qt 5.4 are: QString::toUpper, QString::toLower, QString::toCaseFolded, QString::toLatin1, QString::toLocal8Bit, QString::toUtf8, QByteArray::toUpper, QByteArray::toLower, QImage::convertToFormat, QImage::mirorred, QImage::rgbSwapped, QVersionNumber::normalized, QVersionNumber::segment

Changes in the standard library.

C++11 and C++14 have added a lot of feature to the standard library, competing with many of the features of QtCore. However, Qt makes little use of the standard library. In particular, we do not want to have the standard library as part of the ABI. This would allow to stay binary compatible even when the standard library is changed (example libstdc++ vs. libcpp). Also, Qt still supports older platforms that do not have the C++11 standard library. This really limits our uses.

Yet, Qt5 deprecated its own algorithms library and is now recommending to use the algorithms from the STL (example, std::sort instead of qSort).

Conclusion

It may still take some time before you can use those features in your project. But I hope that, by now, you started using C++11 features like many others projects did (Qt Creator, KDE, LLVM).

MSVC will enables C++14 by default with their new compilers, but clang and gcc require a special compilation flag (currently -std=c++1y). With qmake, you can enable your project to build with C++14 since Qt 5.4 by using this option:

CONFIG += c++14

What's New in Qt 5.4: The QStorageInfo Class

In this blog post, I will cover a new class introduced in Qt 5.4.0: QStorageInfo. This post is based on a Lightning Talk I gave at Qt Developer Days 2014 in San Francisco.

Overview

The QStorageInfo class provides information about mounted filesystems, also known as volumes. It allows retrieving information about a volume's storage space, mount point, label and filesystem name. New in the Qt 5.4.0 release, QStorageInfo is part of the Qt Core module.

Endocode is hiring an Assistant to the Board

If you are a recent or about to graduate in a Bachelor’s or Fachhochschule degree in business studies, Endocode might be looking for you! We are hiring an assistant to the board. Admittedly, the job is quite a challenge. It gives a sneak peek into all aspects and functions of managing a company. It does not require much experience, but it requires good training and a passion for learning and problem solving. The responsibilities include supporting management processes like board meetings and negotiations, and also some administrative work for relaxation.

Endocode

One interesting detail about the job is that it is ideal for gaining management and leadership skills before beginning a Master’s degree. I was told not many companies are offering interesting jobs for Bachelor graduates – well, we do! If you are interested, the details are on Endocode’s job page. Feel free to pass it on to your student and graduate friends. The deadline for applications is December 7.


Filed under: Coding, CreativeDestruction, English, FLOSS, KDE, OSS, Qt

HsQML 0.3.2.0 released: Enters the Third Dimension

Last night I released HsQML 0.3.2.0, the latest edition of my Haskell binding to the Qt Quick GUI library. As usual, it's available for download from Hackage.

HsQML allows you to bind declarative user interfaces written in QML against a Haskell back-end, but sometimes you can't just let QML hog all the graphical fun to itself. This latest release allows you incorporate 3D (OpenGL) graphics rendered from Haskell into your QML scenes using the new Canvas module.

The screenshot below shows off the OpenGL demo in the samples package. The colourful triangle is rendered using the regular Haskell Platform's OpenGL bindings, but HsQML sets up the environment so that it renders into a special HaskellCanvas element inside the QML scene. If you run the actual program you can see it being animated too, moving around and changing colour.


This release also adds the Objects.Weak module which allows you to hold weak references to QML objects and keep track of their life cycles using finalisers. The new FactoryPool abstraction uses these primitives to help you efficiently keep track of instances you've created, especially for when you need to fire change signals on them for data-binding.

London Haskell User Group

I've been fortunate enough to get a speaking slot at the London Haskell User Group and will be giving a talk on Building Pragmatic User Interfaces in Haskell with HsQML on the 26th of November. Please feel free to come along and watch. You can RSPV on the group's meet-up page.

The talk should be videoed and materials will be available online afterwards.

release-0.3.2.0 - 2014.11.13

* Added OpenGL canvas support.
* Added weak references and object finalisers.
* Added FactoryPool abstraction.
* Added To-only custom marshallers.
* Added Ignored type.
* Relaxed Cabal dependency constraint on 'text'.

Applying Scrolling and Eliding Text in a Natural User Interface

We recently made a presentation at the Qt Developer Days conference in San Francisco, entitled Make Your Content Shine: Design Choices for a Qt Touch Kiosk. In the presentation we talked about numerous issues related to content display in our touchscreen kiosk product, ViewPoint and explained the best practices that we used to solve those issues. In this post, we are going to focus on a couple of issues with scrolling and eliding text. 

Tasuku Suzuki is the second Qt Champion


QtChampion_logo_72dpi_RGB_color

Last week in the Americas Qt Developer Days, our second Qt Champion was announced.

Tasuku Suzuki, who has been working hard with the Japanese Qt community has earned the Qt Champion title.

Suzuki-san got his first introduction to Qt when as a student back in 2002 he needed to make a UI for a scientific simulator he had written as part of his studies. He tried out several different toolkits and found Qt best suited for his needs.

After that Suzuki-san got more involved in Qt, when  he joined Trolltech in 2006, as a local technical sales support person for Japan. Suzuki-san and his colleagues did a lot of work to get Qt more known locally in Japan. They at some point translated the whole Qt website to Japanese, to make it more accessible. He was also heavily involved in making the Japanese Qt Developer Conferences happen in 2009 – 2011.

Qt_Dev_Tokyo_2011

More recently Suzuki-san has been heavily involved in the Qt Meetups in Japan. The meetups originate from 2010, when @vivisuke started having Qt meetups in his home city. The meetup activity spread inside Japan and soon there were quite a lot of separate meetups in different cities. In 2012 these meetups joined to form the Japan Qt Users’ Group. Around this time Suzuki-san was already active in the Tokyo meetup and the community agreed that he could take over organising the Tokyo meetups.

The format of the meetups in Japan varies, but Suzuki-san has changed the format from a presentation style event to a more active coding event. Everyone can come to the meetup and code, study and ask questions on Qt. These meetups have been happening continuously every month since January 2013, and have attracted new developers to Qt too.

One of the fun details in the meetups is the Qt Sweets Division with @hermit4, whose mission is to provide snacks for the meetups. The results are pretty impressive (cake, choclate and cake 2).

As part of the meetups, Japanese developers have contributed code and bug reports to the Qt project. Suzuki-san has also helped in this, as the language barrier is a problem for many Japanese developers.

Suzuki-san codes himself too, he has worked on different things, including Japanese text input for Qt based platforms.

Another interesting project Suzuki-san is working on, is silk- Simple and flexible web framework. Silk is a Qt project that makes it possible to write server-side code with QML and JavaScript. It comes with everything needed to get running fast with Qt on the server.

Suzuki-san has also contributed code to Qt for several years, and has several contributions to his name.

A package of goodies is on it’s way to Japan, and a one year Qt Professional license has been given to Suzuki-san. I would like to congratulate Suzuki-san on his new title as Qt Champion!

New service: Fix My Qt Bug!

FixMyQtBug2

Need a fix for a Qt bug? Look no further…

At KDAB, we know that fixing bugs in Qt requires resources, deep knowledge of Qt in various use cases and the right tools. Sounds simple enough but can you afford to take the time to do it yourself? Taking part in hundreds of our clients’ Qt projects around the world, embedded as well as desktop, we have come in contact with all types of Qt bugs. To help you save time and money – we are now making that experience available to you, for a fixed price and with a fast turnaround time.

  • Just send your application or a standalone test case to us
  • You will receive a fix in return
  • We’ll even take care of the demanding process of having it included in Qt

A fix for only 7.500 Euro

  • We offer this service at fixed price, so there will be no surprises *
  • After the initial evaluation we can let you know when the fix will be ready
  • We will work on having the fix included in Qt at no extra cost
  • And if for any reason your Qt fix cannot be included in Qt, we’ll even maintain it for you **

Contact us now at:

Curious about our latest fixes?
Go to: https://codereview.qt-project.org/#/q/ownerin:%22CLA+KDAB%22+status:merged+message:Task-number,n,z

* Disclaimer: We reserve the right to reject a bug fix request if the issue is deemed technically insurmountable or would cause disproportionate effort. Customers will be informed of such cases as soon as the evaluation part of the process is over.

** Maintenance of your fix is only included until the next major Qt version is released. Due to the nature of the open-governance process of a Qt contribution, we cannot guarantee when upstream inclusion will happen Additional maintenance purchase is possible. Contact us to request a tailored quote.

The post New service: Fix My Qt Bug! appeared first on KDAB.

Documentation now up for testing in doc.qt.io


Hello,

We have been working on transferring Qt documentation under qt.io and would like to have your feedback on the work so far. All improvement suggestions are welcome. We have a meta-bug opened on the Qt bugtracker where you can add your findings.

The new documentation can be found at http://doc.qt.io/

So what has changed?

–          New layout and style to match qt.io style
–          New documentation publishing process (this is mostly for the benefit of the documentation team)
–          All documentation will be (eventually) transferred under the same location

The upcoming Qt 5.4.0 release will see the Qt 5.4.0 documentation only on the qt.io site, along with downloads.

The other parts of the documentation will also move to the new site in due time. However with that we need to make sure that we have working redirects in place. The web is full of links to the documentation and we want to make sure people don’t end up on a 404 page. So we are not hurrying the move, the redirects need to go right on the first try.

But now we are looking forward to your comments on the new look and feel of the documentation!

Help Qt Continue To Reign Supreme | Vision Mobile 8th Developer Economics Survey


Our friends at Vision Mobile have launched their Developer Economics 2015 Q1 survey to track developer trends across platforms and dev tools – as well as investigate the emerging IoT market. Of course we want Qt to reign supreme, so make sure you let your voice be heard!

DE8-illustration

Take the 10-minute survey and talk mobile trends  – Do you see more opportunity in Wearables, Smart Homes or Connected Cars? Who’s making money from apps – and how? Which are the must-have tool categories for developers? Is the web vs. native debate still relevant?

The key findings will become available in the form of a free research report in February. Aside from contributing to the research, you will also get a chance to win some great prizes, including an iPhone 6, a Google Nexus 5,  a Lumia 930, an Oculus Rift DevKit, and a Samsung Gear Smartwatch!

Get involved and don’t forget to help us spread the word via the Qt community.

Let’s join forces and support Qt!

QMetaType in plugins

I've learned that for some uses QMetaType just does not work.

Imagine that you want to read types of parameters of some signal or slot of QObject. You also know that all parameters to this method are pointers to QObject-based types. The best way to do that is to:

  1. register your type with qRegisterMetaType<QObjectDerivedType>
  2. read parameter meta type id with QMetaMethod::parameterType(int)
  3. get QMetaObject of this parameter with QMetaType::metaObjectForType(int)
In most cases it works. But not when QObjectDerivedType lives inside a plugin that is dynamically loaded and unloaded several times during program execution (and this whole sequence is run on each plugin load).

On first load everything works perfectly. On second (or third or next, it is rather random and probably depends on allocation patterns in application) your QMetaObject from point 3 is invalid and using it causes access violation. Why? QMetaType remembers address of QMetaObject for each QObject based class pointer per program execution. On load a new QMetaObject is constructed for each type that lives in plugin. And on unload its memory is freed. In result the stored pointer just must to be invalid.

Maybe I missed something, but I was not able to get it to work properly. My solution is to use custom paramter-QMetaObject mapping instead of relying on QMetaType. It is based on QMetaMethod::parametrTypes() method that returns type name and a map of type-name to QMetaObject pointer that is created on each plugin load and passed around. I'm not very happy with this solution, because it is prone to namespace issues and it does not allow usage of types that are no preregistered in plugin (on the other side, QMetaType has the same problem). Hopefully C++ reflection will become real some day.

But there is one more thing that makes me happy - replacing first solution with second in my dependency framework Injeqt took some time and required non-trivial changes in library. But API and ABI remained the same - there was no need to recompile Kadu 2 to work with new version. It means that my usage of private and public interfaces, pimpls and anonymous namespaces is at least proper. This also closed last bug that blocked 1.0 release. This means I can now prepare beta 0.9 and focus on developing Kadu (also to test if Injeqt is really ready to be released).

Qt Creator 3.3 beta released


We are happy to announce that we released Qt Creator 3.3 beta1 today.

editordraganddrop

It comes with enhanced support for splitting editors and additional editor windows. You can now drag & drop editors between splits by dragging the new file type icon, next to the document drop down (see screenshot). Hold the Ctrl key (or Option key on OS X) to open another editor on the same document, instead of moving it. The navigation views (such as Projects and Open Documents) also support dragging files onto splits. Dropping files from the system onto a Qt Creator window now will also open the file in the appropriate split.

It is now possible to specify environment variables to be used with specific kits. Display names of kits and Qt versions can contain variables like %{Qt:Version}, which are automatically filled with the corresponding values. We also added a check box to select and deselect all kits when setting up projects.

Opening QMake projects is now also done asynchronously, like the reparsing that is done when .pro or .pri files change. You can now add files to Qbs projects via the context menu on the Projects view.

The QML Profiler got support for reordering, showing, and hiding categories in the timeline. Also, you can attach notes to events, that are then exported together with the profiling data and can be shared with others.

When pressing the Enter key while the text cursor is within a C++ string literal, the string is now (optionally) split and continued on the next line, adding the necessary quotes for you automatically. We also added a little refactoring action for converting connect() calls to use the new connect style in Qt 5.

For Android development we added support for the Gradle build system.

For users of the Professional or Enterprise edition, we added experimental support for running the Clang Static Analyzer on your projects, as a new tool in Analyze mode. The scene graph events category in the QML Profiler has been significantly improved and will now visualize the time ranges of all scene graph related events instead of showing them as a list of numbers. You can also see input events in the QML profiler now, in a separate category.

We fixed many more bugs and made improvements, such as enhancing the appearance of Qt Creator on high DPI displays, adding a list of open windows to the Window menu, and adding an optional sidebar with Contents, Index, Bookmarks and Search views to the external help window. See our change log for a more complete list of changes.

You find the opensource version on the Qt Project download page, and Enterprise packages on the Qt Account Portal. Please post issues in our bug tracker. You also can find us on IRC on #qt-creator on irc.freenode.net, and on the Qt Creator mailing list.

Note: With Qt Creator 3.3 we drop support for compiling Qt Creator with Qt 4. The minimal required Qt version to compile Qt Creator itself is currently Qt 5.3.1. This does not affect your own projects, of course, we still fully support development of Qt 4-based applications with Qt Creator.

An update on OS X Code Signing

by Morten Johan Sørvig (Qt Blog)


There has recently been updates to the OS X code signing process. These updates also affect Qt applications signed for distribution, both on and outside the App Store.

OS X 10.9 Mavericks introduced version 2 signatures. As of OS X 10.9.5 and 10.10 Yosemite, v2 signatures are now required. We’ve recently spent some time updating Qt to be v2 compliant and Qt 5.4 will be the first compliant release. This includes patches to qmake and the macdeployqt deployment utility. Manually correcting the signing errors is possible if you are using an older version of Qt.

The Apple documentation is quite comprehensive on this topic, in particular see Code Signing Guide and TN2206 OS X Code Signing In Depth. The Qt tracking bug for this issue is QTBUG-32896.

Required changes to Qt

The required changes falls in three categories: updating the framework and application bundle structure, updating Info.plist contents, and special Qt Quick imports handling.

Updating the framework and application bundle structure

  • The Info.plist file must be placed in Versions/5/Resources/Info.plist.
  • Updated symlink structure: “Current” symlink points to the actual version (“4” or “5”).
  • The framework must be “clean” at code signing time, with for example no QtCore.prl at the root. This is currently enforced by macdeployqt.

As an example, the QtCore.framework structure should look like this:

QtCore.framework/
    QtCore -> Versions/Current/QtCore
    Resources -> Versions/Current/Resources
    Versions/
        Current -> 5
        5/
            QtCore
            Resources/
                Info.plist

And a typical app bundle:

foo.app/
    Contents/
         Frameworks/
             QtCore.framework/
         Info.plist
         MacOS/
             foo
         PkgInfo/
         PlugIns/
         Resources/

Update Info.plist contents
The Info.plist files as generated by current qmake versions are missing some required keys:

  • CFBundleIdentifier (“org.qt-project.QtCore”)
  • CFBundleVersion (“5.4.0″)

Split Qt Quick imports into code and data in the application bundle

This is a v2 code signing requirement which affects applications with Qt Quick imports that contain both binary code (.dylib) and data (.qml) files.

Previous versions macdeployqt would deploy all files to Resources/, but as of v2 binary code in Resources/ is now prohibited. This is solved deploying .dylib files to PlugIns/ and then placing a symlink in Resources/ pointing to the .dylib.

Code signing flow and checkpoints

The following outlines a typical code signing process, with notes on where a current 4.8/5.3 Qt install may fail. The focus is on using the command line tools. Code signing using Xcode is possible but not covered here. The process is incremental: Some steps can be verified by any developer locally, while others require developer account admin access.

1) Signing and verifying the app bundle.

    sign: codesign --deep foo.app -s MyCertificate
      or: macdeployqt foo.app -codesign=MyCertificate
    verify: codesign —verify foo.app

The -deep option signs the app bundle recursively, including contained frameworks. While convenient to use, –deep is documented for “emergency repairs and temporary adjustments only“. As of Qt 5.4 macdeployqt has a -codesign option that recursively signs the app bundle without using –deep.

Common errors at this stage include “bundle format unrecognized, invalid, or unsuitable”, and/or “bar.dylib: code object is not signed at all”, which indicates that the framework structure is not correct or that some contained binary was not signed.

At this point which certificate you use does not matter. You can use a self-signed one created in Keychain Access for development and testing purposes.

2a) Distribution outside the App Store
Verify that GateKeeper will allow the app:

    spctl --assess --type execute foo.app

spctl outputs nothing on success. Common errors include “Rejected”. The bundle must be signed with the correct “Developer ID Application” production certificate for this check to work. The certificate is available for download to the Team Agent in the Mac Dev Center.

2b) App Store distribution
May trigger additional errors:

    ERROR ITMS-9000 The application bundle contains a tool or framework
    foo.app/Contents/Frameworks/QtCore.framework that is missing the
    bundle identifier.

This is currently a pending task for Qt 5.4. You can edit the plist files manually and add a bundle identifiers.

Availability

The updates are/will be available for three Qt versions:

  • 5.3 source code (not packaged)
  • 5.4 release. The updates will be be a part of the 5.4 source and binary release.
  • 4.8 patches: https://codereview.qt-project.org/#/c/95572, with the intention that this will be a part of a future 4.8.x release.

TODO list

The fixes for some issues are currently in progress:

  • Adding CFBundleIdentifier for the Qt frameworks
  • Changing the location of .prl files

Do you have corrections or additional info? Hit the comments section!

Notes from a UX Pro Over a Cup of Joe: Mental Models

Welcome back to the coffee corner!  

I hope that you’re doing well and enjoying your user experience (UX) rock star status on any project you may be working on, no matter your role. Today, we’re going to be chatting about Mental Models - what they are, why we should care about them and how we can leverage them to inform design thinking.

FOSDEM 2015 Desktops DevRoom Call for Talks

FOSDEM is one of the largest gatherings of Free Software contributors in the world and happens each February in Brussels (Belgium). One of the tracks will be the Desktops DevRoom (formerly known as “CrossDesktop DevRoom”), which will host Desktop-related talks.

We are now inviting proposals for talks about Free/Libre/Open-source Software on the topics of Desktop development, Desktop applications and interoperability amongst Desktop Environments. This is a unique opportunity to show novel ideas and developments to a wide technical audience.

Topics accepted include, but are not limited to: Enlightenment, Gnome, KDE, Unity, XFCE, LXQt, Windows, Mac OS X, software development for the desktop, general desktop matters, applications that enhance desktops and web (when related to desktop).

Talks can be very specific, such as the advantages/disadvantages of development with Qt on Wayland over X11/Mir; or as general as predictions for the fusion of Desktop and web in 5 years time. Topics that are of interest to the users and developers of all desktop environments are especially welcome. The FOSDEM 2014 schedule might give you some inspiration.

Please include the following information when submitting a proposal:

  • Your name
  • The title of your talk (please be descriptive, as titles will be listed with around 250 from other projects)
  • Short abstract of one or two paragraphs
  • Short bio (with photo)
  • Requested time: from 15 to 45 minutes. Normal duration is 30 minutes. Longer duration requests must be properly justified. You may be assigned LESS time than you request.

The deadline for submissions is December 7th 2014. FOSDEM will be held on the weekend of January 31st-February 1st 2015 and the Desktops DevRoom will take place on Sunday, February 1st 2015. Please use the following website to submit your proposals: https://penta.fosdem.org/submission/FOSDEM15 (you do not need to create a new Pentabarf account if you already have one from past years).

You can also join the devroom’s mailing list, which is the official communication channel for the DevRoom: desktops-devroom@lists.fosdem.org (subscription page for the mailing list)

– The Desktops DevRoom 2015 Organization Team

Qt + CMake + code coverage

Yesterday I was working on getting reports on code coverage for Injeqt library. I've found several tutorials on the internet, but every one of them was missing a detail or two.

So here is what I've come with:

1. Update compiler and linker flags in CMakeLists.txt file of your tests:

set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -g
-fprofile-arcs -ftest-coverage -O0")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -W -g
-fprofile-arcs -ftest-coverage -O0")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}
-fprofile-arcs -ftest-coverage -O0")
2. Link each test with gcov library:
target_link_libraries (test-target-name gcov)
3. Add new target for extracting coverage data:
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
4. Insert coverage.sh script into directory of CMakeLists.txt:
#!/bin/bash

lcov --capture --directory . --output-file coverage.info
lcov --directory . --output-file coverage.info \
--remove coverage.info "/usr/*" "*.moc" "test/*"
genhtml coverage.info
First lcov invocation will capture all data from previously executed tests. Second will remove useless data like coverage of generated moc files or of standard library headers and tests themselves.

5. Run tests and coverage:
make test
make coverage
6. Enjoy nice HTML coverage report.

Injeqt got 90,4% of lines coverage on first try! I hope to make it even better today.