Qt in World’s Fastest Electric Car


Digia has supported Metropolia University of Applied Sciences in their electric car project called Electric Raceabout (E-RA). This cool research project has produced a street legal electric sports car, which not only has the World record on ice, but also runs Qt.

Metropolia University, located in Helsinki, Finland, does extensive research on electric vehicles, one example being E-RA – an electric sports car built primarily by automotive engineering students.

With 4-wheel drive and well designed handling E-RA is a really capable sports car with impressive specs:

  • Top speed of over 260 km/h
  • Motor power of 282 kW
  • Peak torque of 800 Nm – in each wheel

And all this provided by an electric vehicle that is fully street legal (and rest assured, the Finnish road inspection is surely one of the toughest in the world to pass).

E-RA has achieved lap time of 8 minutes 42,72 seconds at Nürburgring Nordschleife, which was electric vehicle track record for quite a while, as well as World record as the fastest electric vehicle on ice with average speed of 252,09 km/h. Nicely driven E-RA has operating range of over 200 kilometers.

The students have built both the IVI system and the instrument cluster with Qt 4.8 running on top of Linux. I think the whole E-RA project is a really great proof of the skills the soon-to-graduate engineers have, and certainly the Qt parts are no less impressive.

Have a look on the enclosed video produced by the students at Metropolia University to hear the full story:

Data initialization in C++

In this blog post, I am going to review the different kind of data and how they are initialized in a program.

What I am going to explain here is valid for Linux and GCC.

Code Example

I'll just start by showing a small piece of code. What is going to interest us is where the data will end up in memory and how it is initialized.

const char string_data[] = "hello world"; // .rodata
const int even_numbers[] = { 0*2 , 1*2,  2*2,  3*2, 4*2}; //.rodata

int all_numbers[] = { 0, 1, 2, 3, 4 };  //.data

static inline int odd(int n) { return n*2 + 1; }
const int odd_numbers[] = { odd(0), odd(1), odd(2), odd(3), odd(4) }; //initialized

QString qstring_data("hello QString"); //object with constructor and destructor

I'll analyze the assembly. It has been generated with the following command, then re-formatted for better presentation in this blog post.

g++ -O2 -S data.cpp

(I also had to add a function that uses the data in order to avoid that the compiler removes some arrays that were not used.)

The sections

On Linux, the binaries (program or libraries) are stored as file in the ELF format. Those files are composed of many sections. I'll just go over a few of them:

The code: .text

This section is the actual code of your library or program it contains all the instructions for each function. That part of the code is mapped into memory, and shared between the instances of the processes that uses it (provided the library is compiled as position independent, which is usually the case).

I am not interested in the code in this blog post, let us move to the data sections.

The read-only data: .rodata

This section will be loaded the same way as the .text section is loaded. It will also be shared between processes.

It contains the arrays that are marked as const such as string_data and even_numbers.

.section    .rodata
_ZL11string_data:
    .string "hello world"
_ZL12even_numbers:
    .long   0
    .long   2
    .long   4
    .long   6
    .long   8

You can see that even if the even_numbers array was initialized with multiplications, the compiler was able to optimize and generate the array at compile time.

The _ZL11 that is part of the name is the mangling because it is const.

Writable data: .data

The data section will contain the pre-initialized data that are not read-only.
This section is not shared between processes but copied for each instance of processes that uses it. (Actually, with the copy-on-write optimization in the kernel, it might need to be copied only if the data changes.)

There goes our all_number array that has not been declared as const.

.data
all_numbers:
    .long   0
    .long   1
    .long   2
    .long   3
    .long   4

Initialized at run-time: .bss + .ctors

The compiler was not able to optimize the calls to odd(), it has to be computed at run-time. Where will our odd_numbers array be stored?

What will happen is that it will not be stored in the binary, but some space will be reserved in the .bss section. That section is just some memory which is allocated to each process, it is initialized to 0.

The binary also contains a section with code that is going to be executed before main() is being called.

.section    .text.startup
_GLOBAL__sub_I_odd_numbers:
    movl    $1, _ZL11odd_numbers(%rip)
    movl    $3, _ZL11odd_numbers+4(%rip)
    movl    $5, _ZL11odd_numbers+8(%rip)
    movl    $7, _ZL11odd_numbers+12(%rip)
    movl    $9, _ZL11odd_numbers+16(%rip)
    ret

.section    .ctors,"aw",@progbits
    .quad   _GLOBAL__sub_I_odd_numbers

.local  _ZL11odd_numbers  ; reserve 20 bytes in the .bss section
    .comm   _ZL11odd_numbers,20,16

The .ctor section contains a table of pointers to functions that are going to be called by the loader before it calls main(). In our case, there is only one, the code that initializes the odd_numbers array.

Global Object

How about our QString? It is a global C++ object with a constructor and destructor. It is simply initialized by running the constructor at start-up.

.section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "hello QString"

.section    .text.startup,"ax",@progbits
_GLOBAL__sub_I_qstring_data:
       ; QString constructor (inlined)
    movl    $-1, %esi
    movl    $.LC0, %edi
    call    _ZN7QString16fromAscii_helperEPKci
    movq    %rax, _ZL12qstring_data(%rip)
       ; register the destructor
    movl    $__dso_handle, %edx
    movl    $_ZL12qstring_data, %esi
    movl    $_ZN7QStringD1Ev, %edi
    jmp __cxa_atexit   ; (tail call)

Here is the code of the constructor, which have been inlined.

We can also see that the code calls the function __cxa_atexit with the parameters $_ZL12qstring_data and $_ZN7QStringD1Ev Which are respectively the address of the QString object, and a function pointer of the QString destructor. In other words, this code registers the destructor of QString to be run on exit.
The third parameter $__dso_handle is a handle to this dynamic shared object (used to run the destructor when a plugin is unloaded for example).

What is the problem with global objects with constructor?

  • The order in which the constructors are called are not specified by the C++ standard. If you have dependencies between your global objects, you will run into trouble.
  • All the constructors of all the global in all the libraries need to be run before main() and slow down the startup of the application. (Even for objects that will never be used).

This is why it is not recommended to have global objects in libraries. Instead, one can use function static objects, which are initialized on the first use. (Qt provides a macro for that: Q_GLOBAL_STATIC which is made public in Qt 5.1.)

Here comes C++11

C++11 comes with a new feature: constexpr

That keyword can be used in two ways: If you specify that a function is a constexpr it means that the function can be run at compile-time.
If you specify that a variable is a constexpr, then it means it can be computed at compile time.

Let us slightly modify the example above and see what it does:

static inline constexpr int odd(int n) { return n*2 + 1; }
constexpr int odd_numbers[] = { odd(0), odd(1), odd(2), odd(3), odd(4) };

Two constexpr were added.

.section    .rodata
_ZL11odd_numbers:
    .long   1
    .long   3
    .long   5
    .long   7
    .long   9

Now they are generated at compile time.

If a class has a constructor that is declared as constexpr and has no destructor, you can have this as global object and it will be initialized at compile time.

Since Qt 4.8, there is a macro Q_DECL_CONSTEXPR which expands to constexpr if the compiler supports it, or to nothing otherwise.

Introducing Qt Quick Layouts


If you want to create a QML application where the UI responds well to window resizing, the toolbox that Qt Quick offers has been somewhat limited. Qt 5.1 will offer the new Qt Quick types RowLayout, ColumnLayout and GridLayout for this purpose.

Background

Up until Qt 5.1, positioners and anchors have been the only Qt Quick tools available for arranging items in the UI.

Positioners are convenient for adding many items, but not always helpful for creating a resizable UI since they (as the name implies – surprise, surprise) only positions the items – the widths and heights are kept the same.

Anchors allows a bit more flexibility, at the price of verbosity. With anchors you can make an item stretch by binding one edge to the corresponding edge of the parent, and you set up a similar binding on the items’ opposite edge. However, you cannot make several items distribute themselves evenly if the window is resized.

The last option is to do the manual layouting yourself. This offers great flexibility, but it can be verbose, cumbersome and error-prone. During the development of Qt Quick Controls, we wanted to improve this and decided to provide a better and more convenient layout system.

import QtQuick.Layouts 1.0

By including the above import you will have RowLayout, ColumnLayout and GridLayout available in your toolbox. These layouts behave very much like their sisters found in the QtWidgets module: QHBoxLayout, QVBoxLayout and QGridLayout. It also tries to match the API of the Row, Grid and Column QML elements where it makes sense. So, if you are familiar with any of these APIs, you will find Qt Quick Layouts easy to grasp.

Alignment of items inside a cell can be specified with the Layout.alignment property.

Spans across rows or columns can be specified with the Layout.rowSpan and Layout.columnSpan properties.

Grid coordinates can be specified with the Layout.row and Layout.column properties.

Resizable items can be specified with the Layout.fillWidth and Layout.fillHeight properties. This was the main goal of the Qt Quick Layouts.

Minimum, Preferred and Maximum sizes can be specified with Layout.minimumWidth, Layout.preferredWidth and Layout.maximumWidth  properties (“Width” can be replaced with “Height” for specifying similar constraints to the height).

The feature set it adds might not look like a lot, but the fact that you can have both non-stretching items and stretching items in the same layout makes things easier and more intuitive in many cases.

Example

Suppose we need to create a ToolBar with two buttons and a slider that occupies the remaining space. When resizing, the extra space will be allocated to the slider.
Without Qt Quick Layouts, the solution with least code would probably be a mix between using a Row and using anchors:
ToolBar {
    Row {
        id: row
        spacing: 2
        anchors.verticalCenter: parent.verticalCenter
        ToolButton { iconSource: "images/go-previous.png" }
        ToolButton { iconSource: "images/go-next.png" }
    }
    Slider {
        anchors.left: row.right
        anchors.leftMargin: 2
        anchors.verticalCenter: parent.verticalCenter
        anchors.right: parent.right
    }
}
With Qt Quick Layouts, all items can be added to the same layout:
ToolBar {
    RowLayout {
        anchors.fill: parent
        spacing: 2
        ToolButton { iconSource: "images/go-previous.png" }
        ToolButton { iconSource: "images/go-next.png" }
        Slider { Layout.fillWidth: true }
    }
}
Notice how much shorter the declaration for the Slider element is. Also note that when using Qt Quick Layouts, the spacing only needs to be specified once. Code is reduced from 288 to 172 characters (whitespace excluded), which is a 40% reduction.

Summary

In this example, by using Qt Quick Layouts we got 40% less code, improved readability (not only because the code got shorter, but also because the structure of the code became closer to the structure of the UI).
If you want a resizable UI, you will probably find that Qt Quick Layouts are easier to use than anchors, positioners and manual layouting.

Qtified JavaScript


When writing JavaScript code, it doesn’t take long until I’m missing some function which is available in Qt’s C++ API. One very simple example is QList::contains. Checking whether an array contains a certain element works like this in JavaScript:

var names = ["Egon", "Peter", "Raymond", "Waldo"];
if (names.indexOf("Waldo") !== -1)
    print("We've found him!");

It would be nice if we could express the condition using a contains method but Array doesn’t provide one.
Luckily, JavaScript enables us to add methods to inbuilt types by modifiying the corresponding prototype object.

Array.prototype.contains = function(e) {
    return this.indexOf(e) !== -1;
}
if (names.contains("Waldo"))
    print("We've found him!");

Yay! Now we can use the contains method for all arrays!
But wait – there’s a surprise lurking right around the corner once you’re trying to iterate over the keys of the array.

for (var i in names)
    print(i);

This will print:

0
1
2
3
contains

I know, iterating over arrays should be done with an index variable…but still…this additional key is unexpected and asking for trouble.

The solution for this problem is to mark the property contains as non-enumerable. We can use the Object.defineProperty function for that which is available since JavaScript 1.8.5.

Object.defineProperty(Array.prototype, "contains", {
    value: function(e) { return this.indexOf(e) !== -1; },
    enumerable: false    // This is the default and can be omitted.
})

We’re passing to Object.defineProperty the object we want to enhance, the name of the property we want to add and a descriptor object that contains the attributes of our new property.
The value of  contains will be the function that we formerly passed directly to the prototype. Setting the enumerable property to false in the descriptor object will hide contains when using a for (... in ...) loop.

This way we can create a nice Qtish API for the inbuilt JavaScript types Array and String. This can be put into a .js file and used it in QML/JS or in qbs project files.

What do you think? Would such an API be helpful for your QML code? Which QList or QString method are you missing most?

Qt 5.1 Beta Released


I am happy to announce that we have today released Qt 5.1 Beta. We are now a major step closer to release Qt 5.1.0, which is expected before the summer. With the Beta release, binary installers for Qt 5.1 are available making it easier for you to get started with Qt. Let’s take a quick look at what is in the package.

Key functionality

The main driver for Qt 5.1 has been to increase the maturity of the new features introduced with Qt 5.0. We have improved the functionality and performance based on the feedback received from real-world use cases of Qt 5.0 and porting applications from Qt 4.x. We are able to meet your needs with Qt 5 because of the feedback and contributions from our growing ecosystem of about 500,000 developers in over 70 industries using Qt on numerous platforms and configurations.

The key new features of Qt 5.1 Beta include:

  • Qt Quick Controls module providing a set of reusable UI components especially for desktop applications created with Qt Quick
  • Qt Quick Layouts module bringing an easier, more intuitive, way to manage scalable UIs by ensuring that items are consistently arranged, and that the UI as a whole remains usable across different screen sizes.
  • Qt Serial Port module providing a cross-platform interface for using hardware and virtual serial ports in Qt applications
  • Possibility to use Qt Quick and Widgets together in the same application window
  • Qt Creator 2.7.1 bundled into the package, providing, for example, Qt Quick Designer for rapid prototyping, as well as improved C++11 code editing
  • Support for static Qt builds making it possible to address those use cases that cannot use dynamic linking
  • Introducing Qt Sensors as an officially supported module

For a more detailed look, please take a look to the Wiki article listing the new features of Qt 5.1 Beta, refer to the Qt 5.1 Documentation Snapshot as well as the Known Issues page in the wiki.

Binary installers

For most users the big thing with Qt 5.1 Beta compared to Qt 5.1 Alpha is binary installers that provide a convenient way of installing all you need to start developing with Qt without needing to build Qt yourself. With Qt 5.1 we are introducing some new configurations such as 64bit VS2012 with OpenGL, which is already available with the Beta. Soon after the Beta we are upgrading MinGW to version 4.8 and aim to bring also 32bit VS2012 with ANGLE configuration by the time we are releasing Qt 5.1.0.

Qt 5.1 Beta comes as an offline installer, but we will also be providing online installers before the release of Qt 5.1.0 final. The offline installer contains all you need to get started with Qt – tools, documentation, examples and pre-built Qt libraries. Source packages are available for those who wish to build Qt (or need to use a configuration that is not available as a pre-built binary). In addition to the desktop binaries, Qt 5.1 Beta comes with pre-built binaries for Android that can be bundled in with your application.

New platforms

Qt 5.1 Beta provides technology-preview level implementation of the new Android and iOS ports. In addition, Qt 5.1.0 final is planned to re-introduce Windows Embedded Compact 7 support that has earlier been available with Qt 4.8. We have added all these new platforms into the CI system so that each change that goes into Qt is verified to work on these as well as the other platforms and configurations already in the CI. At the moment, the CI for Android and iOS only tests for building, but we are gradually also adding the automated tests to be run on these new platforms, to decrease the possibility of regressions.

There is quite a lot of buzz around the new mobile ports and many are interested in knowing what is possible already with the Qt 5.1 Beta. In general, it can be stated that you can create stunning applications that run smoothly on both of the new platforms, but with limitations in supported functionality and the developer experience of getting your masterpiece into these devices.

With Android the following functionality works quite well in the Qt 5.1 Beta:

  • Widgets, Graphics View, Qt Quick 1 and Qt Quick 2 applications
  • OpenGL, networking and other core functionalities of Qt
  • Some parts of Qt Multimedia, for example QML media player
  • A set of commonly used sensors with Qt Sensors
  • Deploying your application to a device from Qt Creator
  • Debugging your application from Qt Creator
  • Qt 5.1 Beta comes with pre-built binaries for Android that can be bundled in with your application

With iOS the main issue is Qt Quick 2 not being available, as it needs a new QML engine, but the following functionality works quite well in the Qt 5.1 Beta:

  • Widgets, Graphics View and Qt Quick 1 applications
  • OpenGL, networking and other core functionalities of Qt
  • A set of commonly used sensors with Qt Sensors
  • Deploying your application to a device from Xcode / iTunes

Next steps

With the release of Qt 5.1 Beta we are one step closer to the Qt 5.1.0 final release, which we aim to have out before summer. Based on the feedback we receive from the Beta, there will be a Release Candidate created in a few weeks time, or alternatively a second Beta.

Please test out Qt 5.1 Beta and send us feedback:

  • File a bug report to bugreports.qt-project.org in case you find a new bug
  • Send e-mail to Qt Project mailing lists or contact us via IRC
  • If you have a commercial license, please contact Digia Qt Support via the Customer Portal

Qt 5.1 Beta release can be downloaded from the Digia Qt Customer Portal or from download.qt-project.org for open-source users.

 

Qt Contributors Summit 2013 – Please register


Guggenheim mirror balls
Guggenheim mirror balls

Registration for the Qt Contributors Summit 2013 is now open.

Before going into details, I’ve added a photo of the The Guggenheim mirror balls right outside the famous Guggenheim Museum in Bilbao. It can symbolise how every Qt contributor is linked together, working on the same project, using the summit to reflect on how Qt can be developed even better. Ok, Knut, snap out of it. Over to the practicalities.

Qt Contributors Summit 2013 registration is easy. Just use the Qt CS registration form.

Since the Qt Contributors Summit is an invitation-only event, please make sure you fit into one or more of the following before registering:

  • You are a Qt Project maintainer
  • You are a Qt Project approver
  • You took part in the previous Summit (Attendees at Qt CS 2012)
  • You took a sponsorship package including event invitations (coming soon)
  • You are in the organization team.
  • You are invited by a maintainer or the organization team and we still have seats left.
  • KDE Akademy contributor

Please add sessions unconference style

Since the main idea for the Qt CS is to let developers meet and make solutions, now is the time to pre-schedule sessions on the Qt CS program wiki. Please press “Join group” at the top of the wiki-page. We will  give you wiki-access as soon as possible and add you to the group.

Qt Creator 2.7.1 released


We take today’s Qt 5.1 beta release as an opportunity to push out some fixes to Qt Creator 2.7.

Around 40 bugs reported on our bugtracker have been fixed, so if you wonder if your favorite issue is one of them you might want to check out the list of “Qt Creator bugs that have been closed as ‘done’ for 2.7.1″ on our bug tracker. And of course there were other bugs fixed that do not appear on that list, so you should definitely check Qt Creator 2.7.1 out.

Download Qt Creator 2.7.1

Qt5 Battery Component

After the QUItIndicator trilogy which introduced idea, design and performance of a specific Qt5 QML component there's room for more, right?! Something like this:


This time we have a dynamic QML component for showing the remaining power of your mobile device battery. As a recap, with "Dynamic QML component" I mean someting which utilizes not only basic QML animation properties (position, opacity, scale etc.) but also new Qt5 features (shaders, particles, scenegraph powa!) to appear "more dynamic". Maybe it's just me, but I would love to see UIs really utilizing modern GPUs... and accelerating this progress is one of the reasons why I code these examples and blog about them. Another reason being to rule-the-world, obviously ;-P

Instead of explaining design & features of QUItBattery component I'll let this video to do that:





If you want to use this liquid battery component in your UI: Download the sources from here, copy QUItBatteryComponent directory, import it in your QML and off you go. Happy hacking!

Welcome Endocode, the future of Agile Workers Software

Recently, we announced the incorporation of Endocode AG. With its team of five founders, Endocode offers software engineering services around Open Source technologies, as well as consultations with businesses in collaboration with Open Source communities. This sounds very similar to what Agile Workers Software offered. In fact, Endocode is the second incarnation of the vision we strove for with Agile Workers – to create a partnership of experts, of knowledge workers, offering advice and services as a coherent team. In this post, I am going to explain the advantages of starting over, and how it will benefit both our clients and the partners who are working on the company.

Our clients will benefit from the extension of our leadership team. Endocode is lead by four directors with a combined experience of multiple decades of working on Open Source software engineering and connections into various Open Source communities. With this move, we will become more approachable and extend the expertise represented by the board to new fields. We see one of our biggest strengths as our ability to understand and solve software engineering problems that span a multitude of technical domains. We believe in the synergies that stem from combining the diverse experience of our partners. To further grow this potential, Endocode will continue to invite outstanding new partners solely based on their motivation and general engineering prowess. Because “if all you have is a hammer, everything looks like a nail”, there will be no specific technological focus on certain programming languages, tool kits or platforms. The only common denominator is a passion for and a focus on Open Source technologies.

Endocode’s partners and employees will benefit from the new corporate setup (a shareholders company, as opposed to a limited liability company) because it makes it easier to implement a partnership scheme. For anybody who joins Endocode, there will be the opportunity to become a shareholder, and eventually a partner. This in turn will make the company more attractive to self-determined and self-motivated individuals, who are often exactly the experts we are looking for. In this regard, Endocode is more similar to a law or architecture firm than to the typical software services shop. There will be more information about Endocode’s partnership model in a future post over on the Endocode site.

Agile Workers will conclude and finish ongoing projects, and Endocode will gradually take over from there. For our clients, the transition should be seamless and smooth. If there are any worries or concerns, please contact us immediately. If you are a client looking to contract our professional services, please contact either Agile Workers or Endocode, and you will talk to the same team. If you are a software engineer and you feel like Endocode would be a great place to work, we are hiring.

Introducing Endocode, you are invited!

tl:dr version: New venture Endocode, we are hiring!

Skill and the will to remain in control of one’s own future seem to come in pairs. I consider myself an expert coder with sugar on top, and a darn good manager, too. Working for the man is nothing more than an acceptable means to the end of making ends meet. If you are a knowledge worker and you left average behind a while ago, chances are you feel exactly the same. However, we all need to eat, and that usually means accepting to do paid work. So what is there to do? Well, for one thing, put that gray matter to use and design a company to your liking, that’s it. Challenge accepted, and we are almost done with it. Meet Endocode.

endocode-logo

For work to be motivating beyond getting paid, it has to be meaningful to us. Almost everything that determines how meaningful a job is has to do with participation. Real participation is not about installing an office hour where employees can complain after filing their TPS reports. For each individual, it is about being a part of decisions that are made, being an integral, equal part of the team doing the work, and about receiving a part of the benefits from it. On one hand, there is the good old self-employment bug, where those who have been infected often say that even though being self-employed may be stressful, they would never go back to not being their own master. But there is also the Open Source bug, where contributors to communities have tasted the collaborative ways, and say they would not go back to a place with a traditional, rigid, do-as-I-say model of working. And we think this is a good thing.

Participation and meaning are built right into the corporate setup of Endocode. There are five founders, and even the company name is the result of a lengthy collaboration (believe me, it took a looooong time). Besides that we maintain a close relationship to Open Source communities and products, there is no technological focus. Instead we invite those to join us who have passion in their hearts for something awesome. Well, something awesome related to software engineering, because we are a software company. However, there will be no discrimination. If you are from Pluto and you can code, please apply. And Pluto is not even a planet. Every person that joins Endocode will have the chance to become a partner in the company.

But… when building a collaborative business, when trying to build ideals into the setup of the company, there is always the danger of striving towards some egalitarian utopia which in the end undermines the stability and profitability of the company. We designed Endocode with this experience in mind, and added instruments to maintain long-term operating efficiency. There will be well-documented, collaborative, transparent decision making processes, but we still will get to a decision. Profit sharing mechanism are in place, but we will keep an eye on profitability. This balance is tricky to strike. But the fact that these fundamental problems are understood and actively tackled in Endocode will be reassuring, will help to convince talented future partners to join us.

We are trying to build a company in which knowledge workers can feel right at home and that implements a coherent, profitable business strategy. There will be more details on how the people engaged in Endocode will work together later. The company has been incorporated, and we are now finishing the remaining formalities (hence the “almost done”). If you are wondering what kind of work we do, here is that our partner Chris Kühl has to say about it. And this is our first job opening (still on the old site, it will move soon).


Filed under: Coding, CreativeDestruction, English, FLOSS, KDE, OSS, Qt Tagged: business, Creative Destruction, FLOSS, KDE

Spring cleaning of the qt-jenkins.moiji-mobile.com

About a week ago I asked for help/support on the Continuous Integration of Qt for the combination of Linux/MIPS/UCLIBC/DirectFB and due the lack of feedback I have removed the DNS entry and cleaned up my system.

This means that currently there is no (public) build testing for any of DirectFB, MIPS, UCLIBC and the bitrot will increase over time. I have asked on the mailinglist about the removal of the Broadcom 97425 device support as it likely to be unused now.


FrOSCon 2013: Call for Projects, Papers

frosconThe Free and Open Source Software Conference (FrOSCon) will take place on the 24th and 25th of August this year, kindly hosted by the Bonn-Rhein-Sieg University of Applied Sciences, Sankt Augustin.

We are looking for projects that would like to present in the exhibition area, as well as interesting talks or workshops. Additionally, you can request a project room if you want to sit together to do some hacking, or have your own, topic specific course of lectures. Sign up now!

But even more so, we are looking for speakers. The focus this year is on Seamless Computing, How Free Software should deal with closed ecosystems and How to let the computer do your chores. Even if your topic is not in one of those domains: Submit your proposal.

QUItIndicators: Performance considerations

(This is part III, please check also parts I and II)

Even with a small component like this, there are plenty of possibilities to improve (or sink) the performance. To make sure that our indicators perform as expected, we'll test them on Nokia N9 and and on Raspberry Pi.

These both devices are relatively low-end by current standards. N9 contains 1GHz Cortex-A8 CPU which is still quite beefy, but GPU (SGX530) on the other hand is getting old and unable to handle more complicated fragment shaders. For RPi these are just the opposite: CPU is slowish 700MHz ARM11 while the GPU (VideoCore IV) is more performant than N9 SGX530. Because of these qualities (and because both support Qt5, naturally) this duo is excellent for our performance ensurement.

So here's a short video showing how our indicators perform on Nokia N9 and on RaspberryPi:




Performs pretty OK on both, right? ProgressIndicator stress test isn't smooth on RPi, which indicates that its CPU can't handle 100 indicators animated like that. So stress test does what it's supposed to, normal use cases perform well.

Even with declarative QML language, good performance doesn't just happen, you need to work towards it. By looking at the sources of these indicators, at least these tips/notes can be made:

  • BusyIndicator and ProgressIndicator are separate components instead of just one component with e.g. "indeterminate" property. This allows using a more light-weight (only one texture, animating only vertex shader, less properties etc.) BusyIndicator component with indeterminate use-cases. Lesson to learn is to avoid making too general/bloat QML components.
  • There are four different sizes for indicators, from small (64x64px) to huge (512x512px). These sizes were selected because power-of-two texture sizes are more optimal for GPU. SourceSize property is used to scale and cache exactly the correct sized textures.
  • BusyIndicator animation is achieved purely on vertex shader. As vertex shader is run once for every vertex instead of once for every fragment (pixel), it can be much more GPU-friendly. In case of an 256x256px indicator, our vertex shader is executed over 650(!) times less than fragment shader.
  • To keep the amount of vertices as small as possible while making sure animation looks still smooth, the mesh size is allocated based on indicator size. GridMesh resolution for 256x256 indicator is 10x10 while 64x64 indicator manages with a 4x4 mesh.
  • When using items&images as sources for ShaderEffect and not needing the original one, remember to set its visibility to false to prevent it from rendering.
  • ProgressIndicator can show percentages in the center and applies vertex animation also for it, which requires that the whole Item is used as a source for ShaderEffect. Initialize of Item as a ShaderEffect source is slightly slower than initialize of Image. This is because Items (with their child Items) need to be rendered into FBO first while Image textures are instantly available. When percentages are disabled (showPercentages: false), Image is used directly and stress test of 162 ProgressIndicators starts pretty instantly. So if you need instantly appearing ProgressIndicators, don't show percentages on them.
  • Minimize the amount of property changes. Property bindings in QML are so easy to make that without paying attention you may forget to disable those when not needed. As an example, ProgressIndicator percentages Text element visibility was set to false when disabled and it wasn't even used as part of the shader source. But because of an oversight, its text property was still updated whenever ProgressIndicator value changed. That's bad, fixed now to update text only when showPercentages is true. Qt Creator QML Profiler is the tool to use to analyze your code.

So with all this, does it mean that these indicator components are fully optimized? Well of course not! There are still some generalization left and room for improvements. Additinally, although we have tried to offload most of the work from CPU to GPU, indicator animations like these should be run in a separate thread instead of the GUI thread. Only this would allow smooth 60fps even when processing under heavy CPU load. For details, please read this blog post by Gunnar: http://blog.qt.digia.com/blog/2012/08/20/render-thread-animations-in-qt-quick-2-0/

Summing up briefly: When implementing QML components for applications, developers and designers should co-operate closely to bend the design to be as CPU&GPU friendly as possible while still making designers happy. Designers dig perfect pixels, but they also appreciate smooth 60fps. By making wise compromises and utilizing Qt5 correctly, we can deliver both.

Sources of QUItIndicator components & examples are available from: http://quitcoding.com/?page=work#indicators

Using QAbstractItemModel with Cascades on BB10

With QML as abstraction layer, we nowadays have a great way to separate the business logic (C++) of our application from the graphical user interface (QtQuick/QtWidgets/Cascades) on top of it. The interface between the two layers is well defined by the meta-object API, which essentially boils down to signals and slots for notifications and invocations, and properties for data access.

To reuse the business logic objects with different UIs, the data types of the signal/slot parameters and the property types must be known by both sides, the business logic and the UI library. While the parameters for signals and slots are normally simple types like ‘int’, ‘bool’, ‘QString’ or ‘QDateTime’, the property types tend to be more complex. There are scalar values with simple types of course and for non-scalar values a ‘QVariantList’ or ‘QVariantMap’ can be used, however to visualize lists of data in a list view, the UI libraries normally expect some specific model interface.

QtWidgets and QtQuick both use the QAbstractItemModel interface to make data of arbitrary formats accessible to the views. QAbstractItemModel is aimed to work with list, table and tree structures, and to work fast on big data sets. All these requirements reflect in an extensive and not so easy to use API, starting from hierarchic model indexes, over persistent model indexes, down to item data roles. Cascades on the other side defines its own model interface (bb::cascades::DataModel), which is aimed to work with lists and tree structures only and can’t be optimized for large data sets as good as QAbstractItemModel. However its API is much smaller and easier to use.

The problem occurs when you want to implement a business logic class that provides a list of objects to be displayed in a list view. Depending on the UI to use, you’d either have to make your property of type QAbstractItemModel or of type bb::cascades::DataModel.
Needless to say, this breaks our nice separation and the business logic would now
depend on the UI… that’s bad :( But we have to provide the data to the list view in some way, so how?

QAbstractItemModel is declared in QtCore, that means every Qt-based application will know about it. Furthermore, QAbstractItemModel is more generic than bb::cascades::DataModel API-wise, so all the functionality of bb::cascades::DataModel can be modeled with QAbstractItemModel as well.

For this reason I suggest to only use QAbstractItemModel as type for model properties in C++ business logic objects, which you want to use accross multiple platforms!

All right, but how can bb::cascades::ListView access the data from the QAbstractItemModel then, if it only supports bb::cascades::DataModel as input?
Say hello to AbstractItemModel

AbstractItemModel

AbstractItemModel is a class that implements the Adapter design pattern.
It inherits the bb::cascades::DataModel interface, so it can be plugged into a b::cascades::ListView as data model, and as adaptee it uses an arbitrary QAbstractItemModel object. All the mapping between the different index systems (QVariantList indexPath vs. QModelIndex) and the forwarding of change notification signals (items added/removed/updated) is handled by AbstractItemModel, so it can be used out-of-the-box like this:

import bb.cascades 1.0
import com.kdab.components 1.0

Page {
    attachedObjects: [
        AbstractItemModel {
            id: abstractItemModel
            sourceModel: _fileSystemModel
        }
    ]

    ListView {
        dataModel: abstractItemModel

        listItemComponents: [
            ListItemComponent {
                type: ""
                StandardListItem {
                    title: ListItemData.display
                }
            }
        ]
    }
}

At first you have to import the module where the AbstractItemModel is defined in, here we used ‘com.kdab.components’. Then you declare a new instance of AbstractItemModel as attached object of some component and give it an ‘id’. As ‘sourceModel’ you set the QAbstractItemModel based model, here we use a QFileSystemModel, which has been set as context property under the name ‘_fileSystemModel’. Inside the ListView we can use the AbstractItemModel as input for the ‘dataModel’ property now.

The usage of a custom ListItemComponent in this example brings us to a specific in AbstractItemModel: While bb::cascades::DataModel::data(indexPath) returns all data of the item at this indexPath in one go, QAbstractItemModel::data(index, role) returns only the data at this index for the specific role. AbstractItemModel adapts this behavior by calling QAbstractItemModel::data() for every available role and returns all the data as QVariantMap, where the keys are the role names. For this reason we use ‘ListItemData.display’ as title of the custom StandardListItem in the example above, to display the QAbstractItemModel’s data for the Qt::DisplayRole.

bb::cascades::DataModel associates a so called item type with each item in the model. The item type is an arbitrary string value, which should be known by the model and the ListItemComponent. While the standard models use ‘item’ and ‘header’, your custom model could use additional item types like ‘mysubheader’. Unfortunately QAbstractItemModel does not provide such an association by default, however if you know that your QAbstractItemModel will be used together with an AbstractItemModel in a Cascades application, you can simply define an additional role in your QAbstractItemModel (e.g. ItemTypeRole with the role name ‘itemType’) that returns a string value and then specify it as content of the AbstractItemModel’s ‘itemTypeRole’ property:

AbstractItemModel {
    id: abstractItemModel
        sourceModel: _myCustomModel
        itemTypeRole: "itemType"
    }

With this change the AbstractItemModel returns the value of the model’s ItemTypeRole as item type.

Another specific in QAbstractItemModel is its view-driven lazy loading mechanism. Because real-world models can contain thousands or even millions of items, loading all items into memory on start-up is a bad idea. Instead the model loads only an initial subset and the view asks the model to load more in case the view needs to display further items (e.g. after the user expanded the branch of a tree). To query more data, the view uses QAbstractItemModel::fetchMore(index) to trigger the loading of all data underneath index. Since some models expect the call of fetchMore() to actually populate any data, AbstractItemModel provides the slot fetchMore(indexPath), which calls the fetchMore() method of the associated QAbstractItemModel with the mapped index. You would use the fetchMore() slot inside your UI code whenever the user enters a new level in the hierarchy. In our file browser example with the QFileSystemModel, the code would look like that:

    ListView {
        id: listView

        dataModel: abstractItemModel
        onTriggered: {
            listView.rootIndexPath = indexPath
            abstractItemModel.fetchMore(indexPath)
        }

        ...
    }

Whenever the user clicks on a directory entry, we change the ‘rootIndexPath’ property of the ListView to the clicked indexPath, so that the ListView now shows the content of the selected directory. Additionally we tell the AbstractItemModel that it needs to populate the items for this indexPath now (if not done already).

The Code

The code of the AbstractItemModel (and the complete filebrowser example) can be found at
https://github.com/tokoe/cascades/tree/master/abstractitemmodel
It is available under a BSD-like license, so you can freely use it in your own project,
and modify or redistribute it as long as you keep the original copyright notice.

Interested in MIPS/UCLIBC/DirectFB becoming a Tier1 platform?

Are you running Qt on a MIPS based system? Is your toolchain using UCLIBC? Do plan to use Qt with DirectFB? If not you can probably stop reading.

During the Qt5 development the above was my primary development platform and I spent hours improving the platform and the Qt support. I descended down to the kernel and implemented (and later moved) userspace callchain support for MIPS [1][2] in perf. This allows to get stacktraces/callchains for userspace binaries even when there is no framepointer. I stress-tested the DirectFB platform plugin and found various issues in DirectFB, e.g. this memleak. I modified the V8 MIPS JIT to provide the necessary routines for QML. While doing this I noticed that the ARM implementation is broken and helped to fix it.

At the time Nokia was still using Puls. This meant that getting an external build to integrate with their infrastructure was not possible. So I started to setup a Jenkins for DirectFB and Qt myself. The Qt Jenkins is compiling QtBase, QtJsBackend, QtXmlPatterns, QtDeclarative and QtWebKit for MIPS/Linux/UCLIBC. On top of these there a daily builds for the various QtBase configurations (dist, large, full, medium, small, minimal) and running the V8 unit tests using the built-in simulator for ARM and MIPS. The goal was to extend this to run the all the Qt tests on real hardware. The unit that supported my work was shut-down before I could implement it and the platform work has mostly been in maintenance mode since then.

This has all worked nicely for the release up to Qt 5.0 but when Qt5.1 got merged into the stable branch and received some updates the build started to break and I don't have enough spare time to fix that.

If anyone is interested in either taking over the CI or helping to make this part of my work again I would be very happy.


How to tile widgets in a multiple document interface application


In Qt you can create multiple document interface (MDI) applications using a QMdiArea as the central widget. The QMdiArea widget serves as a window manager for the MDI windows. There are already functions available for tiling all the child windows into a tile pattern and for cascading them into a cascade pattern.

With MDI application it would sometimes be useful to tile the child windows also horizontally and vertically. The QMdiArea does not currently have an API to achieve this functionality but it’s quite simple to arrange the child windows in your application. We will next cover the steps needed to tile the child windows horizontally and vertically. The approach presented here is implemented on top of the MDI Example (http://qt-project.org/doc/qt-5.0/qtwidgets/mainwindows-mdi.html).

Let’s start by adding the actions in place so that the functionality can be triggered. To the MainWindow we will add one action for each function as private member variable:

QAction *tileVerticalAct;
QAction *tileHorizontalAct;

We will also add a private slot for each function:

void tileSubWindowsVertically();
void tileSubWindowsHorizontally();

Then we will initialize the actions and connect them to the right slots. We are going to add the following code to the createActions() method that already initializes actions for the application:

tileVerticalAct = new QAction(tr("Tile Vertically"), this);
tileVerticalAct->setStatusTip(tr("Tile the windows vertically"));
connect(tileVerticalAct, SIGNAL(triggered()), this, SLOT(tileSubWindowsVertically()));
tileHorizontalAct = new QAction(tr("Tile Horizontally"), this);
tileHorizontalAct->setStatusTip(tr("Tile the windows horizontally"));
connect(tileHorizontalAct, SIGNAL(triggered()), this, SLOT(tileSubWindowsHorizontally()));

And naturally we need to add the actions to the menu in order to launch the tiling. We can do this in the updateWindowMenu() where other actions are added to the menu too:

windowMenu->addAction(tileVerticalAct);
windowMenu->addAction(tileHorizontalAct);

Now we are ready to start tiling the child windows. We are going to take a closer look at the tileSubWindowsVertically() slot here. To begin with, we will start by checking that there are child windows in the MDI area to prevent us from trying to do modifications to non-existing windows.

if (mdiArea->subWindowList().isEmpty())
    return;

We are going to initialize a rectangle that defines the size of one child window. The width for a child window will naturally be the width of the MDI area. The height of a child window will be based on the height of the MDI area and the amount of child windows. Basically, we will just divide the MDI area height with the amount of child windows. The rectangle can then be used to set the geometry for each child widget in the MDI area.

QPoint position(0, 0);
foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
    QRect rect(0, 0, mdiArea->width(), 
               mdiArea->height() / mdiArea->subWindowList().count());
    window->setGeometry(rect);
    window->move(position);
    position.setY(position.y() + window->height());
}

While we are setting the geometry for the child widgets we also define the new position for them to have the windows tiled vertically. The child windows are ordered here based on the order of the child windows in the MDI area. By default, this order is the order in which the windows were inserted into the workspace. We will move the first window in the MDI area to the top left corner. While processing the child windows we will adjust the position so that each child window is position below the previously processed one. This is all we need to tile the child windows vertically.

Tiling the child windows horizontally will be almost the same; you only need to adjust the width and x-position of the window. The height of a child window will be the same as the height of the MDI area. The position of a child window will be on the right of the previous child.

void MainWindow::tileSubWindowsHorizontally()
{
    if (mdiArea->subWindowList().isEmpty())
        return;
    QPoint position(0, 0);
    foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
        QRect rect(0, 0, mdiArea->width() / mdiArea->subWindowList().count(), 
                   mdiArea->height());
        window->setGeometry(rect);
        window->move(position);
        position.setX(position.x() + window->width());
    }
}

Not that hard or what do you think? If you want to give it a try you can get the source code for the example here: Source code for example application . Shall you have any questions related to this you can always contact us in the Qt Support team via the Customer Portal.

Enginio: Qt Backend as a Service Launches Tech Preview


You may have already heard of Enginio at Qt Developer Days 2012  or you may have stumbled across our site, http://engin.io. We are now ready to officially open up the doors to our Enginio Tech Preview and welcome you to test it out. We have already had some early adopters who have given us valuable feedback which we have used to develop the product.

Why Enginio?

When we had a look at the existing cloud solutions, we saw that there was room for improvement. They were sometimes difficult to get started using and required specific knowledge of certain infrastructures or platforms and in most cases did not have Qt/C++ APIs. Using the experience we have from building backend solutions for various kinds of applications, we decided to create a solution that linked applications with a backend cloud storage based on Qt’s intuitive APIs. With Enginio developers can concentrate on creating their application making it visually pleasing and performing and let Enginio manage the backend functionality, scalability, security and performance.

Our goal was to build upon Qt’s motto of making “developer’s lives easier” and so what we wanted to do was provide developers with an uncomplicated and stress-free development experience in the backend. So, we started to create a solution that was easy to use and value-adding for Qt application development and at the same time transmit that Qt effortless development trait to other platforms. We want to make sure that the value-adding benefits of having a Qt backends are available to all. Enginio will be commercially available for both open-source and enterprise Qt users. For enterprise Qt users developing with a commercial license, a few additional value-adding features and functions will be made available to them later on.

The Enginio Technology Previews supports:

  • Web dashboard (UI for configuring & managing your backend)
  • Schema-less data storage (Place to store your application data)
  • Security model (Mechanism to control which end-users can access what data)
  • File support (Save small or large files in the cloud)
  • Full text search (Search stored data by its content)
  • Qt/QML client library (Convenient way to create applications)

How to get started?

1. Sign up for an Enginio account

2. Setup your new backend

3. Develop your App

The latest release version of the Qt library is available from the Enginio dashboard.

Shared library and QML extension plugin are built and installed as usual with `qmake && make && make install`

Qt example:

I. In Qt Creator choose File > New File or Project… and create new “Qt Gui Application”.
II. In the new project’s pro file add:

QT += network
win32:CONFIG(debug, debug|release): LIBS += -lenginioclientd
else: LIBS += -lenginioclient

III. In MainWindow.cpp:

// Include Enginio headers
#include <Enginio/Enginio>

// Instantiate Enginio Client
// Copy your backend ID and secret from Enginio dashboard
const QString backendId("YOUR_OWN_BACKEND_ID");
const QString backendSecret("YOUR_OWN_BACKEND_SECRET");
EnginioClient *client = new EnginioClient(backendId, backendSecret);

// Create new object to backend
EnginioJsonObject banana("objects.fruits");
banana.insert("name", QStringLiteral("Banana"));
banana.insert("price", 1.59);
EnginioObjectOperation *createOp = new EnginioObjectOperation(client);
createOp->create(banana);
createOp->execute(); // Initiates asynchronous operation

// Fetch objects from backend to list model
EnginioObjectModel *objectModel = new EnginioObjectModel();
EnginioQueryOperation *queryOp = new EnginioQueryOperation(client);
queryOp->setObjectType("objects.fruits");
queryOp->setModel(objectModel);
queryOp->execute();

 

QML example:

I. In Qt Creator choose File > New File or Project… and create new “Qt Quick 2 Application (Built-in Elements)”
II. In main.qml:

import io.engin 1.0 as Enginio

// Instantiate Enginio Client
// Copy your backend ID and secret from Enginio dashboard
Enginio.Client {
        id: client
        backendId: "YOUR_OWN_BACKEND_ID"
        backendSecret: "YOUR_OWN_BACKEND_SECRET"
}

Enginio.ObjectModel {
        id: objectModel
}

Enginio.QueryOperation {
        id: queryOp
        client: client
        model: objectModel // Query results are added to model
        objectTypes: ["objects.fruits"] // Get all fruit objects
}

Component.onCompleted: {
        // Create new object to backend
        var banana = {
                objectType: "objects.fruits",
                name: "Banana",
                price: 1.59
        };
        var createOp = client.createObjectOperation();
        createOp.create(banana);
        createOp.execute();
        createOp.finished.connect(function() {
                // Fetch objects from backend to list model
                queryOp.execute();
        });
}

Build and your connected application is ready.

We would like to invite more people to test and provide feedback. However, please bear in mind that the service is still under development and you may experience some bugs, changes and breaks. Go and check it out at http://engin.io. Let us know what you think!

You can reach the Enginio development team at mailus@engin.io.

Retina display support for Mac OS, iOS and X11

by Morten Johan Sørvig (Qt Blog)


Qt 5.0 added basic support for retina reasonable resolution displays. The upcoming Qt 5.1 will improve the support with new API and bug fixes. Qt 4.8 has good support, and backports of some of the Qt 5 patches are available.

While this implementation effort is mostly relevant to Mac and iOS developers, it is interesting to look at how other platforms handle high-dpi displays. There are two main approaches:

  • DPI-based scalingWin32 GDI and KDE. In approach the application works in the full physical device resolution and is provided with a DPI setting or scaling factor, which should be used to scale layouts. Fonts are automatically scaled by the OS (as long as you specify the font sizes in points and not pixels)
  • Pixels By Other Names. In this approach the physical resolution is (to various degrees) hidden to the application. Physical pixels are replaced with logical pixels:
    Platform/API Logical Physical
    HTML CSS pixel Device pixel
    Apple Point Pixel
    Android Density-independent pixel (dp) (Screen) Pixel
    Direct2D Device Independent Pixel (DIP) Physical Pixel
    Qt (past) Pixel Pixel
    Qt (now) Device-Independent Pixel Device Pixel

Qt has historically worked in device pixels with DPI scaling. Back in 2009 support for high DPI values on Windows was improved. The Qt layouts do however not account for increased DPI. Qt 5 now adds support of the “new pixels” type of scaling.

(Are there other high-dpi implementations out there? Use the comments section for corrections etc.)

Mac OS X High-dpi Support

The key to the OS X high-dpi mode is that most geometry that was previously specified in device pixels are now in device-independent points. This includes desktop geometry (which on the 15 inch retina MacBook Pro is 1440×900 and not the full 2880×1800), window geometry and event coordinates. The CoreGraphics paint engine is aware of the full resolution and will produce output at that resolution. For example, a 100×100 window occupies the same area on screen on a normal and high-dpi screen (everything else being equal). On the high-dpi screen the window’s backing store contains 200×200 pixels.

The main benefits of this mode is backwards compatibility and free high-dpi vector graphics. Unaware applications simply continue to work with the same geometry as before and can keep hardcoded pixel values. At the same time they get crisp vector graphics such as text for free. Raster graphics does not get an automatic improvement but is manageable. The downside is the inevitable coordinate system confusion when working with code that mixes points and pixels.

The scale factor between points and pixels is always 2x. This is also true when changing the screen resolution – points and pixels are scaled by the same amount. When scaling for “More Space” applications will render to a large backing store which is then scaled down to the physical screen resolution.

Scaling the user interface resolution on Mac OS

If you don’t have access to retina hardware there is also an emulation mode which can be useful when used on an extra monitor. Open Display Properties and select one of the HiDPI modes. (See this question on stack overflow if there are none.)

Enabling high-dpi for OS X Applications

High DPI mode is controlled by the following keys in the Info.Plist file:

<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<string>True</string>

Qmake will add these for you. (Strictly speaking it will only add NSPrincipalClass, NSHighResolutionCapable is optional and true by default).

If NSHighResolutionCapable is set to false, or the keys are missing, then the application will be rendered at the “normal” resolution and scaled up. This looks horrible and should be avoided, especially since the high-dpi mode is very backwards compatible and the application gets a lot of high-dpi support for free.

Scaled Qt Creator

High DPI Qt Creator

 

 

 

 

 

 

 

 

 
(Appart from a patch to update the “mode” icons, this an unmodified version of Qt Creator.)

Qt implementation details

Mac OS 10.8 (unofficially 10.7?) added support for high-dpi retina displays. Qt 4 gets this support for free, since it uses the CoreGraphics paint engine.

Qt 5 uses the raster paint engine and Qt implements high-dpi vector graphics by scaling the painter transform. HITheme provides high-dpi Mac style for both Qt 4 and 5. In Qt 5 the fusion style has been tweaked to run well in high-dpi mode.

OpenGL is a device pixel based API and remains so in high-dpi mode. There is a flag on NSView to enable/disable the 2x scaling – Qt sets it in all cases. Shaders run in device pixels.

Qt Quick 1 is built on QGraphicsView which is a QWidget and gets high-dpi support through QPainter.

Qt Quick 2 is built on Scene Graph (and OpenGL) which has been updated with high-dpi support. The Qt Quick Controls (née Desktop Components) has also been updated to render in high-dpi mode, including using distance field text rendering.

The take-away point here is that for app developers this doesn’t matter, you can do most of your work in the comfort of the device-independent pixel space while Qt and/or the OS does the heavy lifting. There is one exception which is raster content – high-dpi raster content needs to be provided and correctly handled by application code.

Widgets and QPainter

QPainter code can mostly be kept as is. As an example lets look at drawing a gradient:

QRect destinationRect = ...
QGradient gradient = ...
painter.fillRect(rect, QBrush(gradient));

On high-dpi displays the gradient will have the same size on screen but will be filled with more (device) pixels.

Drawing a pixmap is similar:

QRect destinationRect = ...
QPixmap pixmap = ...
painter.drawPixmap(destinationRect, pixmap);

To avoid scaling artifacts on high-dpi displays the pixmap must contain enough pixels: 2x the width and height of destinationRect. The application can either provide one directly or use QIcon to manage the different resolutions:

QRect destinationRect = ...
QIcon icon = ...
painter.drawPixmap(destinationRect, icon.pixmap(destinationRect.size()));

QIcon::pixmap() has been modified to return a larger pixmap on high-dpi systems. This is a behavior change and can break existing code, so it’s controlled by the AA_UseHighDpiPixmaps application attribute:

qApp->setAttribute(Qt::AA_UseHighDpiPixmaps);

The attribute is off by default in Qt 5.1 but will most likely be on by default in a future release of Qt.

Edge cases and devicePixelRatio

Qt Widgets has some edge cases. Ideally it would pass QIcons around and the correct pixmap would be select at draw time, but in reality Qt API often produces and consumes pixmaps instead. This can cause errors when the pixmap size is used for calculating layout geometry – the pixmap should not use more space on screen if it’s high-resolution.

To indicate that a 200×200 pixmap should occupy 100×100 device-independent pixels use QPixmap::devicePixelRatio(). Pixmaps returned from QIcon::pixmap() will have a suitable devicePixelRatio set.

QLabel is one “pixmap consumer” example:

QPixmap pixmap2x = ...
pixmap2x.setDevicePixelRatio(2.0);
QLabel *label = ...
label->setPixmap(pixmap2x);

QLabel then divides by devicePixelRatio to get the layout size:

QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio();

Several issues like this has been fixed in Qt, and application code can have similar code that needs to be corrected before enabling AA_UseHighDpixmaps.

The devicePixelRatio() accessor is available on several Qt classes:

Class Note
QWindow::devicePixelRatio() Preferred accessor
QScreen::devicePixelRatio()
QGuiApplication::devicePixelRatio() Fallback if there is no QWindow pointer
QImage::[set]devicePixelRatio()
QPixmap::[set]devicePixelRatio()

Text

Font sizes can be kept as-is, and produce similarly-sized (but crisp) text on high-dpi displays. Font pixel sizes are device-independent pixel sizes. You never get tiny text on high-dpi displays.

QGlWidget

OpenGL operates in device pixel space. For example, the width and height passed to glViewport should be in device pixels. QGLWidget::resizeGL() gives the width and height in device pixels.

However, QGLWidget::width() is really QWidget::width() which returns a value in device-independent pixels. Resolve it by multiplying with widget->windowHandle()->devicePixelRatio() if needed.

Qt Quick 2 and controls

Qt Quick 2 and the Qt Quick Controls work well out-of-the box. As with widgets coordinates are in device-independent pixels. Qt Quick has fewer raster-related edge cases, since the QML Image element specifies the image source as a url which avoids passing around pixmaps.

Qt Quick Controls

One exception is OpenGL shaders that run in device pixel space and see the full resolution. This is usually not a problem, the main thing to be aware of is that mouse coordinates are in device-independent pixels and may need to be converted to device pixels.

shadereffects example in action

Managing high-resolution raster content

As we have seen, raster content won’t look nice when scaled and high-resolution content should be provided. As an app developer you have two options: (ignoring the “do-nothing” option)

  • Replace existing raster content with a high-resolution version
  • Provide separate high-resolution content

The first option is convenient since there is only one version of each resource. However, you may find (or your designer will tell you) that resources like icons look best when created for a specific resolution. To facilitate this, Qt as adopted the “@2x” convention for image filenames:

foo.png
foo@2x.png

High-resolution content can be provided side-by-side with the originals. The “@2x” version will be loaded automatically when needed by the QML Image element and QIcon:

Image { source = “foo.png” }
QIcon icon(“foo.png”)

(remember to set AA_UseHighDpiPixmaps for QIcon)

Experimental cross-platform high-dpi support:

QPA allows us to relatively easily make a cross-platform implementation. The Qt stack can be divided into three layers:

  1. The Application layer (App code and Qt code that uses the QPA classes)
  2. The QPA layer (QWindow, QScreen, QBackingStore)
  3. The platform plugin layer (QPlatform* subclasses)

Simplified, the application layer operates in the device-independent pixel space and does not know about device pixels. The platform plugins operates in device pixel space and does not know about device-independent pixels. The QPA layer sits in between and translates, based on a scale factor set by the QT_HIGHDPI_SCALE_FACTOR environment variable.

In reality the picture is a little bit more complicated, with some leakage between the layers and the special Mac and iOS exception that there is additional scaling on the platform.

Code is on github. Finally, screenshots of Qt Creator on XCB:

DPI scaled Qt Creator

QT_HIGDPI_SCALE_FACTOR=2 Scaled Qt Creator

 

 

Keeping Qt in the Lead – And Adding Value


Six months ago we laid out Digia’s Qt strategy at Qt Developer Days 2012 and since then we have been working together with the community to achieve our goals of increasing the use of Qt and expanding business opportunities for all members of the Qt ecosystem and Digia.

I wanted to explain a bit more in detail via this blog post how Digia plans to keep Qt in the lead position, thriving and continuously evolving as well as give a state of the union as we mark our 6-month milestone.

2017 Goals

First, let’s quickly re-cap what we have set as our goals for the next few years.

  • #1 in multi-platform support
  • #1 in developer experience
  • #1 in creating great user experiences
  • Strong value-generating ecosystem
  • Dual licensing model
  • Open business architecture

We have made great progress in many of these already in the past few months, so I think we are definitely in the right track to reach these together.

#1 in Multi-Platform Support

Qt is by nature a cross-platform development framework, which has supported a large number of desktop, embedded and mobile platforms. In the past few months, we have been actively working on introducing support for Android and iOS as well as improving the experience on the desktop and embedded platforms. With the soon–to-be released Qt 5.1 we will already be able to provide solid technology previews for both Android and iOS, which we expect to be complete for Qt 5.2 coming out before the end of this year. We are also working with the WinRT port of Qt to be available soon after Android and iOS. With the introduction of support in Qt 5.1 for the leading mobile platforms, Qt jumps to the next phase of being a platform agnostic world-class and all-around cross-platform software development framework.

#1 in Developer Experience

We have started a few projects to make developers’ encounters with Qt easy and effortless. In Qt 5.0 we tightly coupled Qt Creator and other tools into the same Qt package together with the libraries making it possible to get everything they need to start developing with Qt all in one place. It is still possible to develop for Qt with other IDEs than Qt Creator – for example with Visual Studio or XCode. We have also been working with the online installers for Qt 5, which will be available soon and further improve the experience of developing with Qt. We are also investing heavily into tooling. Focusing on, for example, the new Qt Quick Designer, which was first released with Qt Creator 2.7, and the new Qt Quick Controls of which the first set will come in Qt 5.1.

#1 in Creating a Great User Experience

Qt is known for its ability to create amazing user experiences.  We are working hard to continue Qt’s position as the leading software development framework that enables the creation of stunning UIs with an unbeatable graphics performance. The new graphics pipeline of Qt 5 is one of the cornerstones to reach this goal.  Qt Quick 2 offers a GL-based scene graph, a particle system and a collection of shader effects for fun and cool animations, amongst other things, as well as Qt Multimedia and Qt Graphical Effects that lets the developer bring motion and sound to life within their application.  We will continue to improve these capabilities and make it even easier to build stunning applications with Qt.

Strong Value Generating Ecosystem

In addition to actively working with the developer community through the Qt Project, we are making good progress with our Digia Qt Partner Program with the first partners already signed on and many more to be enrolled soon. We are actively working with members of the Qt community to make sure that valuable Qt events and activities are possible.

This year, the Qt Contributors Summit and KDE Akademy will be held jointly where two strong communities can leverage from each other’s expertise. Digia is a platinum sponsor at this year’s combined Qt Contributor Summit and KDE Akademy. Following last year’s successful Qt Developer Days in Berlin and California, Digia will again join forces with KDAB and ICS to put Qt Developer Days 2013. Lastly, this June, Digia together with top sponsors and active Qt community participants BlackBerry and Jolla, will host the Qt Developer Day China in Beijing (June 6) to cater to our growing Qt ecosystem in China.  We believe that by working together in the ecosystem we can jointly take Qt forward at an unbeatable speed and benefit from the growing user base of developers making Qt-based solutions in over 70 different industries including free software.

Dual Licensing Model

We believe that the dual licensing model is crucially important for the whole Qt ecosystem to thrive, and that it is the best way to further develop Qt. The full development of Qt and making it the leading cross-platform application development framework is at the cornerstone of Digia’s strategy. This means that we want all developers, organizations, companies around the world regardless of industry, business model, device types etc., to use Qt to further their own development goals and business strategies.

In order to keep Qt in the lead allowing innovation into our development, it is important that Qt is available for commercial users and the open source community and provide the functionality that meet the varying needs of both. We believe in the power of open-source development in fostering innovation and value very much all the things we do together with the Qt community via the Qt Project. The dual licensing model serves two purposes in driving Qt forward:

 

  • Commercial licensing secures future investments into Qt R&D with the financial stability needed to keep the Digia Qt engineering teams producing invaluable code development and contributions. Revenue generated from the commercial license sales also enables the Qt Project to charge forward securing, for example, the infrastructure, repositories and qt-project.org servers and development to be a community arena for Qt development where all can participate and contribute.
  • Qt open-source development provides an incomparable vehicle to make Qt available everywhere for everybody increasing the Qt user base and promoting adoption of the technology.

Both of the above models work hand-in-hand; without one our goals of bringing Qt to all and making it the world’s leading cross-platform development framework are not fully possible. Our new mobile ports of Qt for Android, and iOS as well as the upcoming WinRT port are fully developed in the open, a very strong proof point that we really do believe in dual licensing also in the future.

Open Business Architecture

Tightly related with the strong value generating ecosystem is open business architecture – a new element in the Qt ecosystem. We believe that enabling more business opportunities for everybody via Qt will be beneficial for the entire ecosystem.  Open business architecture is a principle that defines the rules for an equal playing ground where everybody is invited to participate. At this point, we see this as a principle, but later on we hopefully are able to develop the whole business architecture forward in such way – and enable more business for everybody.

With an open and thriving Qt ecosystem, we believe that Digia and other players in the community can provide value-adding products for functionality, tools and services. We believe that having such additional components available not only provides more business opportunities for all interested companies, but also makes Qt stronger. The more there are ready-made solutions available to meet the needs and challenges in various industries and use cases, the more value Qt offers our users.

Adding Value

Digia is seeking to create added value in mainly the following areas:

•    Value-adding functionality especially for enterprise users and in the embedded space
•    Improved tools providing a shortened time-to-market and cost savings for companies using Qt
•    Cloud-based services than can be used in conjunction with solutions built with Qt
•    Support and services for development with Qt

Some examples of these are already available; for example, the Charts library and the improved Visual Studio Add-In, as well as our support and services offering. We are working on a new cloud-based backend for Qt applications called Enginio, which was first presented at the Qt Developer Days last year. We are very close to launching the public technology preview, so stay tuned for it.

Especially for our enterprise and embedded customers, we have been working with additional tools that can be plugged into the Qt Creator IDE to make developing with Qt even more efficient, as well as to meet the growing demands of our customers and companies who have chosen Qt as their strategic development choice and who require a full commitment from Digia to succeed in their industry.   We believe that it is possible to provide these refinements of Qt for many different industries, and are aiming to develop Qt and our tooling offering further to allow also other members of the Qt community to offer these as part of the open business architecture.

All in all, I am very happy with the progress we have made towards the goals we set for Qt last year. I am extremely pleased that we have been able to work towards these with so many great partners, customers and community members that form the Qt ecosystem. I believe that by continuing this together we will be able to take Qt forth at record pace and truly make it the number #1 choice for cross-platform application and UI development.

We would love to hear from you, so please drop us a note in the comments below. Happy Qt development!

The power of qobject_cast

One feature we wanted to implement in Tepee3D was a Services Manager that would allow various classes to interact with Services provided through shared libraries. Those services are axed toward database management, web services access and platform specific interactions such as posting notifications on Android and so on. That mechanism allows us to add new […]

QUItIndicators: Design considerations

(This is part II, for the introduction see part I)

The main points of this indicators exercise are to promote Qt5 QML+GLSL approach for building dynamic UI components (part I) and to give performance tips (part III, coming!). But here in the middle, we talk also a bit about design considerations behind these indicators. After all, who cares if your component performs well if it doesn't also look good and fulfil its functionality.

Here's set of design-related notes about QUItIndicators which we wanted to achieve:

  • The design language should be relatively neutral. Indicators like these may be used in many places, in applications and games, so they should not be too characteristic. And circles are pretty universal, so circles it is. The amount of circles in BusyIndicator is 11, by design. Reason behind this is that ProgressIndicator has one missing from top to mark start/end position, meaning 10 circles. This is optimal for percentages math e.g. when user sees 4 circles highlighted she can count that progress is at 40%. For smaller indicators, less & bigger circles might look better but decision was not to differentiate on these.

  • Different use-cases call for different kind of indicators. When indicator is only visible briefly and progress can't be tracked, BusyIndicator is the one to use. Some events may take more time and then ProgressIndicator can be used to keep users better informed of how long they still need to wait. With longer taking tasks you could show percentages and make indicator even more dynamic to make it less boring for user to watch. Watching interesting animation makes 5 seconds to feel like 2... So from brief (left) to longer (right) waiting times, indicator to choose from our set would be:

  • Indicators should fit and be clearly visible on top of any background. Users may wish to place them on white, black or colorful areas and expects indicator to fit there. To achieve this, our indicators use neutral black&white as their base colors and contain inverted version which works better on light backgrounds. It's also possible to define alternative highlight color when the default yellowish isn't suitable. Here are few examples of ProgressIndicators on top of different backgrounds:

  • Show/hide animations are also important. Too often animated items like these appear and disappear suddenly, breaking the illusion of a fluid component. In our component showing/hiding animations are combination of opacity, scale and vertex position skewing. Strips below show what the animation looks like. This could be made smoother but for performance reasons we use only vertex shader with a minimal mesh size. Fastly animated it anyway looks better than these still images.

  • Sometimes indicators like these should attract user attention. When the application is blocked until loading is ready, it's good that user eyes focus on the indicator. Darkening (and blurring, Qt5 graphical effects make that easy) the rest of the UI is a good way to achieve this. But sometimes just the opposite is desired, directing user focus to real content and keeping indicators relatively obscure. Example of this is our Picture Wall demo, users attention is on loaded images instead of the ones still loading. With our indicators this can be achieved by decreasing opacity. (Developer note: When making your own ShaderEffect which rewrites the default fragmentShader, remember to multiply gl_FragColor with qt_Opacity to keep QML opacity property behaving correctly!). Here's how Picture Wall demo fades indicators into background:

  • Circular zooming animation doesn't progress linearly, but instead follows a custom bezier curve. This change in speed makes animation feel more lively and natural as it would be affected by slight gravity, gaining speed when moving down and slowing down while reaching the top. Designs are often filled with small details like this, final touches.

These indicators are not highly original and will not win design awards. Graphics, effects and small details could be greatly refined. But we anyway tried to consider use-cases and apply them into the design. If you are eager to experiment yourself, grab the sources.

Next part will explain how to reach optimal performance to support these design considerations.


Qt’s WinRT port and its C++/CX usage


Background

After Friedemann has given an initial introduction about Qt’s Windows Runtime port, I would like to give some further insight about technical aspects and our ways of working on the port.

When reading about Windows Runtime development (Windows 8 store applications and Windows runtime components) in connection with C++ you will find C++/CX again and again. Windows C++/CX are C++ language extensions which were developed by Microsoft to make software development for Windows Runtime easier by bringing it “as close as possible to modern C++” (Visual C++ Language Reference (C++/CX)). In some cases, these extensions look similar to C++/CLI constructs, but they might have other meanings or slightly different grammar.

The first thing that catches someone’s eye when one has a look at C++/CX documentation or an example/application are lines like
Foo ^foo = ref new Foo();
The ^ is basically a pointer, but gives the additional information that it is used on a ref-counted COM object so that memory management happens “automagically”. The “ref new” keyword means that the user wants to create a new “Ref class” (see Ref classes and structs in Type System (C++/CX)), which means that it is copied by reference and memory management happens by reference count.  So there isn’t much magic involved in that line; it only tells the compiler that the object’s memory can be managed by reference count and the user does not have to delete it himself.

Basically C++/CX is just what its name tells us it is – extensions to the C++ language. Everything ends up as native unmanaged code quite similar to the way Qt works. Some people might argue whether it is necessary to reinvent the wheel for the n-th time where a lot of the “problems” are actually solved in C++11 (by the way, auto foo also works in the example above), but that is what was decided for Windows Runtime development.

Use of C++/CX inside Qt’s WinRT port

Microsoft has said on different occasions (among others during the Build conference 2012) that everything that can be done using C++/CX can also be done without the extensions, as everything ends up as native code in either case. So we had to decide whether we want to use the new fancy stuff or take the cumbersome road of manual memory management etc. Theoretically there is nothing that keeps us from using C++/CX in Qt’s WinRT port, but there are some reasons why we try to avoid them.

For one, these extensions might prevent developers who are willing to help with the Windows Runtime port from having a deeper look at the code. If you do not have any previous experience with this development environment, having new constructs and keywords (in addition to new code) might be enough for you to close the editor right away. While WinRT code which doesn’t use CX might not be especially beautiful, there are no non-default things which might obscure it even more.

Another issue is that Qt Creator’s code model cannot handle these extensions (yet). You don’t get any auto completion for ^-pointers, for example. This can of course be fixed in Qt Creator and time will tell whether it will be, but at the moment the port and basic Qt Creator integration (building, debugging & deployment) are our first priorities.
Due to these facts, we decided that we do not want to use the extensions. Though, if someone wants to help out with the port and is eager to use CX he/she might be able to persuade us to get the code in (after proper review of course ;) ).

Problems and challenges of not using C++/CX

The main problem when it comes to development of Windows Runtime code without using C++/CX is the severe lack of documentation. While the MSDN documentation generally can be improved in certain areas, it almost completely lacks anything about this topic. But thanks to Andrew Knight, who gave me an initial overview how things are to be used and was always helpful whenever I had additional questions, I think I am getting the grip on things. In order to help others who want to join the efforts (and have all the things written down), I will cover some basic areas below.

Namespaces

The namespaces given in the documentation are always the same for the CX usage of the classes,  just with “ABI” added as the root namespace. So for StreamSocket, Windows::Networking::Sockets becomes ABI::Windows::Networking::Sockets. Additionally, you probably need Microsoft::WRL (and also Microsoft::WRL::Wrappers). WRL stands for “Windows Runtime C++ Template Library” and is used for direct COM access in Windows Runtime applications – but you will also need its functionality when omitting CX (for creating instances for example).

Creating instances

When not using CX, most of the classes cannot be accessed directly. Instead, there are interface classes which need to be used. These interfaces are marked by an ‘I’ in front of the class name so that StreamSocket becomes IStreamSocket. As these interfaces are abstract classes, they cannot be instantiated directly. First of all, you have to create a string which represents the class’s classId.
HStringReference classId(RuntimeClass_Windows_Networking_Sockets_StreamSockets);

These RuntimeClass_Windows… constructs are defined in the related header files and expand to strings like “Windows.Networking.Sockets.StreamSocket” for example. The way objects can be instantiated depends on whether the class is default constructable or not. If it is, ActivateInstance can be used to obtain an object of the type you are after.

IStreamSocket *streamSocket = 0;
if (FAILED(ActivateInstance(classId.Get(), &streamSocket)) {
// handle error
}

Unfortunately, the ActivateInstance convenience function fails for StreamSocket in that case as it expects a ComPtr as parameter. In order to avoid that failure one has to take the long way using RoActivateInstance

IInspectable *inspectable = 0;
if (FAILED(RoActivateInstance(classId.Get(), &inspectable)) {
// handle error
}
if (FAILED(inspectable->QueryInterface(IID_PPV_ARGS(&streamSocket)))) {
// handle error
}

If the class is not default constructable, it has to use a factory in order to create instances. These factories can be obtained by calling GetActivationFactory with the appropriate class Id. One example of a class like that would be HostName:

IHostNameFactory *hostnameFactory;
HStringReference classId(RuntimeClass_Windows_Networking_HostName);
if (FAILED(GetActivationFactory(classId.Get(), &hostnameFactory))) {
// handle error
}
IHostName *host;
HStringReference hostNameRef(L"http://qt-project.org");
hostnameFactory->CreateHostName(hostNameRef.Get(), &host);
hostnameFactory->Release();

People who are used to Windows development probably have already noticed that all this is COM based. That means that all this has been around for ages and is loved everywhere.

Calling static functions

For classes which have static functions there is an extra interface for these functions. These interfaces are marked by “Statics” at the end of the “basic” interface name and can also be obtained by using GetActivationFactory. One example would be IDatagramSocketStatics which contains GetEndpointPairsAsync for example.

IDatagramSocketStatics *datagramSocketStatics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics);


IAsyncOperation<IVectorView *> *endpointpairoperation;
HSTRING service;
WindowsCreateString(L"0", 1, &service);
datagramSocketStatics->GetEndpointPairsAsync(host, service, &endpointpairoperation);
datagramSocketStatics->Release();
host->Release();

The endpointpairoperation defines the callback(s) for this asynchronous function, but that topic could be covered in another post. The interesting parts here are how the datagramSocketStatics pointer is filled by calling GetActivationFactory and the actual call to the static function by datagramSocketStatics->GetEndpointPairsAsync(...).

ComPtr

There is a way to use reference counted memory management even without using CX. It can be achieved by using the Microsoft-provided smart pointer ComPtr. So
IStreamSocket *streamSocket
would become
ComPtr<IStreamSocket> streamSocket.
When using these, we had some memory access errors we could not explain (but did not investigate much further). In addition to that, Qt Creator does not support code completion with “streamSocket->” but one would have to call “streamSocket.Get()->”. Thus we decided not to use ComPtr but keep using “normal” pointers. All you have to do is to remember to call “Release” as soon as you are done with the pointer.

All in all, we try to avoid these extensions even though it might not make the code beautiful. If you want to contribute though and feel at home using these, feel free to create a patch containing CX code. If you have any further questions or advice, feel free to add them in the comments or join us in #qt-winrt on freenode.

QUItIndicators: Introduction

Few months ago I wrote a normal mapping series with part I and part II. That was a good experience, so series it is again! This time about implementing dynamic QML components, with an example case being busy&progress indicators. We'll call these specific ones QUItIndicators.

Let's start with obligatory video which demonstrates these components, BusyIndicator and ProgressIndicator, with few examples:



Traditionally indicators like these would be implemented as an animated GIF or a sprite. Cons of that approach are zero customization and memory consumption: 2s animation of 256x256px 32-bit color indicator at 60fps would mean 2*60*256*256*4 = 31.5Mb memory consumption. That's quite a bit for just one indicator, so usually frames are animated slower than 60fps which makes animation less smooth.

Alternative way to implement animated indicator would be using imperative drawing API (QPainter, Cairo, Skia etc.). Drawing freely to a canvas gives a lot of possibilities, but can easily lead to non-optimal performance. Many of these APIs have OpenGL backends which sounds good in theory, but the reality is that they can't take full gains out of modern GPUs. Like wise Tro^H^H^HDigians have said, combining QPainter with OpenGL backend doesn't make a perfect harmony.

So as you probably guessed, our indicators use Qt5+QML+GLSL instead. The pros of this approach compared to sprites or imperative drawing are rendering performance, low memory consumption and customization possibilities. There is also at least one con: Indicator needs to be designed so that required animations can be achieved with vertex & fragment shaders.

Next blog post goes through design thoughts behind these indicators. In the meantime, you can get the sources from here and try yourself!

Qt-project.org under Open Governance


Right before Qt Developer Days in Berlin, November 2012, we began discussing with the qt-project.org moderators how to bring rest of the Qt Project into Open Governance. This includes the content management system, forums, wikis and so on – everything run as a real community-driven project, as the Qt development itself has been run since October 2011.

Open Governance structure

This figure shows the different roles in the Open Governance structure. A detailed explanation is found on the Web Open Governance page[1].

To make a proper plan, we’ve been running a series of structured IRC meetings, open for all, starting in December last year, continuing through February this year. As the meeting summaries show[2], we started the planning sessions with a discussion on the purpose of the Qt Project Web. Then we continued with discussion and investigation on how maintenance can be done, including co-development of the web content management system. Technical issues, such as improvement with single sign-on and improvements to the wiki-system were discussed. Privacy, internationalization and license issues have also been looked at.

Here are some key topics and actions crystallizing out of these meetings:

  • Single sign-on and a wiki which handles merges (not losing work) Enabling system rights for developing, testing and rolling out new features, including maintenance has to be established.
  • From a roles perspective: several new roles with extended rights are needed, especially giving more access to different admin rights as group management and access to specific web pages.
  • From a process perspective: lazy approval, task prioritization and a conflict resolution board, if needed, in case of (hopefully very few) unresolved conflicts.
  • Also the licensing issue was raised, making the Qt Project Web user agreement clearer, also including licensing to maintain privacy when doing system administration, testing, and development tasks on the site.

Next steps

We are now working on four parallel activities to make Open Governance happen.

  • For CMS development, we are on our way to implement a three-stage infrastructure with a development server and a staging server before production. Today, this is a two-stage setup. We want three stages, which allows the OS to be more flexible in doing the development.
  • We are working at implementing a new access-rights model to allow access to different parts of the CMS.
  • We have identified the need for a “system admin” agreement which is needed before granting extended group admin rights and giving access to fully developed new features, including editing web pages on the site. This agreement is designed to respect privacy laws and simplify the implementation of the planned staged development setup.
  • It seems like the biggest obstacle in the current system is the wiki lacking support for merges when co-writing. Also the single sign on has been identified as one of the key features requested. Given our limited resources, it might be best if these features were to be actively co-developed with Digia together with the community.

There are a couple of other things currently being worked on, such as cleaning up the CSS, simplifying the site navigation, removing old links, and a walk through of the old bugs in the bug-tracker. This work is currently under way.

Since these processes are being run in parallel with the upkeep and maintenance of qt-project.org site from day to day, it’s a little difficult to give an exact time span on when each step will be implemented. We will give progress updates on the Qt Project malinglist[3].

Please have a look at the references below for more information. We welcome your feedback.

1. http://qt-project.org/wiki/Qt_Project_Web_Open_Governance
2. http://qt-project.org/wiki/Qt_Project_Web_Meeting_Summary
3. http://lists.qt-project.org/mailman/listinfo/web

Using gcc’s 4.8.0 Address Sanitizer with Qt


One of the cool new features of gcc 4.8 is the built in “Address Sanitizer”: a memory error detector for C/C++ that will tell you instantly when you e.g. access already deleted memory. This is actually a Google project from Clang/LLVM, so for LLVM users this might be old stuff, but it wasn’t for me :) Since documentation on every day use is still a bit scarce on the web, I’m dumping the gist of how to put it to good use here, especially in the Qt context …

How does it work?

It basically overwrites malloc and free, and does check the memory before every access (see the project wiki for the details). Apparently it does that in a very efficient manner, since the slow down is only about 2x compared to uninstrumented execution! Who knows, maybe we can enable it for the Qt-Project CI system at one point?

Be warned though that it only works so far on Linux and Mac. No luck for MinGW :(

How to enable it?

Since it is part of the compiler suite enabling it is easy: just add -fsanitize=address -fno-omit-frame-pointer to the compiler calls, and -fsanitize=address to the linker calls. Anyhow, to catch issues where the memory is allocated, de-allocated or accessed by Qt you do not only have to instrument your application, but also Qt. There’s a tentative patch for Qt 5.2 which makes this easy:

https://codereview.qt-project.org/#change,43420

It is scheduled for the dev branch (Qt 5.2) because it’s a new feature, but you should be fine cherry-picking it to e.g. Qt 5.0. You can then configure Qt with -address-sanitizer, and run qmake CONFIG+=address_sanitizer for your own applications.

If you don’t want to cherry-pick, you can also pass the additional command line arguments to qmake by explicitly setting QMAKE_CXXFLAGS, QMAKE_CFLAGS, and QMAKE_LFLAGS manually:

$ qmake QMAKE_CXXFLAGS+="-fsanitize=address -fno-omit-frame-pointer" \
QMAKE_CFLAGS+="-fsanitize=address -fno-omit-frame-pointer" \
QMAKE_LFLAGS+="-fsanitize=address"

How to use it?

Just run your application! If you happen to hit a memory issue it will abort, and show you a stack trace with module names and addresses. You will need a separate tool called asan_symbolize.py to get the symbols, and then maybe c++filt to de-mangle the C++ symbols.

Demo!

$ mkdir addresssanitizertest
$ echo "
#include <QDebug>
int main(int, char *[]) {
const char *str = QString("Evil!").toLocal8Bit().constData();
qDebug() << str;
}
" > addresssanitizertest/main.cpp
$ cd addresssanitizertest && qmake -project && qmake CONFIG+=address_sanitizer

$ ./addresssanitizertest 2>&1 | asan_symbolize.py | c++filt
=================================================================
==32195== ERROR: AddressSanitizer: heap-use-after-free on address 0x600c0000bcd8 at pc 0x4016ce bp 0x7fff7ccd86c0 sp 0x7fff7ccd86b8
READ of size 1 at 0x600c0000bcd8 thread T0
    #0 0x4016cd in QString::fromUtf8(char const*, int) /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/tools/qstring.h:478
    #1 0x401b1e in QDebug::operator<<(char const*) /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/io/qdebug.h:117
    #2 0x401282 in main /tmp/addresssanitizertest/main.cpp:6 (discriminator 1)
    #3 0x7fac5c1e3a14 in __libc_start_main ??:?
    #4 0x401118 in _start /home/abuild/rpmbuild/BUILD/glibc-2.17/csu/../sysdeps/x86_64/start.S:123
0x600c0000bcd8 is located 24 bytes inside of 64-byte region [0x600c0000bcc0,0x600c0000bd00)
freed by thread T0 here:
    #0 0x7fac5eab9c5a in __interceptor_free _asan_rtl_
    #1 0x7fac5d353e59 in QArrayData::deallocate(QArrayData*, unsigned long, unsigned long) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qarraydata.cpp:125 (discriminator 2)
    #2 0x401c21 in QTypedArrayData::deallocate(QArrayData*) /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/tools/qarraydata.h:230
    #3 0x401630 in QByteArray::~QByteArray() /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/tools/qbytearray.h:396 (discriminator 1)
    #4 0x401231 in main /tmp/addresssanitizertest/main.cpp:5 (discriminator 1)
    #5 0x7fac5c1e3a14 in __libc_start_main ??:?
previously allocated by thread T0 here:
    #0 0x7fac5eab9e7f in __interceptor_realloc _asan_rtl_
    #1 0x7fac5d35944e in QByteArray::reallocData(unsigned int, QFlags) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qbytearray.cpp:1472
    #2 0x7fac5d358d05 in QByteArray::resize(int) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qbytearray.cpp:1431
    #3 0x7fac5d77e452 in QUtf8::convertFromUnicode(QChar const*, int, QTextCodec::ConverterState*) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/codecs/qutfcodec.cpp:130
    #4 0x7fac5d780e91 in QUtf8Codec::convertFromUnicode(QChar const*, int, QTextCodec::ConverterState*) const /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/codecs/qutfcodec.cpp:507
    #5 0x7fac5d77a483 in QTextCodec::fromUnicode(QString const&) const /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/codecs/qtextcodec.cpp:807
    #6 0x7fac5d48dd26 in QString::toLocal8Bit() const /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qstring.cpp:4020
    #7 0x401215 in main /tmp/addresssanitizertest/main.cpp:5
    #8 0x7fac5c1e3a14 in __libc_start_main ??:?
Shadow bytes around the buggy address:
  0x0c01ffff9740: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c01ffff9750: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c01ffff9760: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c01ffff9770: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c01ffff9780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c01ffff9790: fa fa fa fa fa fa fa fa fd fd fd[fd]fd fd fd fd
  0x0c01ffff97a0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
  0x0c01ffff97b0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c01ffff97c0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c01ffff97d0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
  0x0c01ffff97e0: 00 00 00 00 00 00 01 fa fa fa fa fa 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:     fa
  Heap righ redzone:     fb
  Freed Heap region:     fd
  Stack left redzone:    f1
  Stack mid redzone:     f2
  Stack right redzone:   f3
  Stack partial redzone: f4
  Stack after return:    f5
  Stack use after scope: f8
  Global redzone:        f9
  Global init order:     f6
  Poisoned by user:      f7
  ASan internal:         fe
==32195== ABORTING

Have fun hunting down memory issues :)

Update: Apparently a stock gcc 4.8.0 has still issues with address-sanitizer: libasan isn’t linked automatically, an internal compiler error in qtbase … I’m personally using a gcc from 4.8 branch.