Qtified JavaScript

Published Thursday 16, 2013 | by Jörg Bornemann

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

Published Tuesday 14, 2013 | by Tuukka Turunen

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

Published Tuesday 14, 2013 | by Knut Yrvin

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

Published Tuesday 14, 2013 | by Eike Ziller

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

How to tile widgets in a multiple document interface application

Published Monday 29, 2013 | by Titta Heikkala

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

Published Thursday 25, 2013 | by Sami Makkonen

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

Published Thursday 25, 2013 | by Morten Johan Sørvig

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

Published Tuesday 23, 2013 | by Tommi Laitinen

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!

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

Published Friday 19, 2013 | by Oliver Wolff

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.

Qt-project.org under Open Governance

Published Thursday 18, 2013 | by Knut Yrvin

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

  1. Pages:
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. ...
  10. 148