Migrating code from 5.11 to 5.12

Qt Application Manager 5.12 is not API compatible with the 5.11 release. In this document we go through the main API breaks and how to port affected code from the 5.11 to the new 5.12 API. The API breaks lie solely on the System UI side, therefore application code remains unchanged.

There are also cases where there's no API break but instead new, better, APIs for achieving the same result in 5.12. This document also covers some of such situations.

Import statements

Most of the content of the QtApplicationManager QML module was moved into two new modules: QtApplicationManager.SystemUI and QtApplicationManager.Application. The following table briefly explains each of them:

QML Module NameContent
QtApplicationManagerComponents and types in common to applications and System UI. Both System UI and application code can import this module.
QtApplicationManager.SystemUIComponents and types that a System UI can use. Applications should not import this module.
QtApplicationManager.ApplicationComponents and types that an application can use. System UI code should not import this module.

In order to avoid compatibility problems with old code expecting the old APIs, all imports have been bumped up to version 2.0. Importing the 1.0 versions will just yield a QML error.

ApplicationManager and applications

Refactored ApplicationObject

In 5.11, the object type representing an application was named Application. But since Qt also has an object type with the same name, in order to be able to reference enumerations defined in it you had to import QtApplicationManager in a separate namespace. In 5.12, that object type was renamed to ApplicationObject and thus it no longer clashes with Qt's own Application type.

For example, if you have code like

import QtApplicationManager 1.0 as AppMan
...
if (application.state === AppMan.Application.Installed) {
    ...
}

you can rewrite it as

import QtApplicationManager.SystemUI 2.0
...
if (application.state === ApplicationObject.Installed) {
    ...
}

Starting and stopping applications

The ApplicationObject is smarter now, moving away from being mostly a plain-old-data structure to also contain all actions pertaining to the application at hand, making for a more object oriented API. This is reflected in the way you can start and stop applications in 5.12.

For example, if you have code like

import QtApplicationManager 1.0
...
var application = ApplicationManager.fromId("com.example.music");
...
ApplicationManager.startApplication(application.id);

you can rewrite it as

import QtApplicationManager.SystemUI 2.0
...
var application = ApplicationManager.fromId("com.example.music");
...
application.start();

WindowManager and windows

Windows are now represented by instances of the WindowObject type instead of being Item instances. WindowObjects cannot be displayed directly and have to be assigned to a WindowItem to be rendered on the screen.

This is also reflected in WindowManager model roles, which are now fewer and different. The windowItem role has been replaced with the window role. The isFullscreen role has been removed and there's no replacement for it. isMapped and isClosing were replaced with a single role named contentState.

For example, if you have code like

import QtApplicationManager 1.0
...
Connections {
    target: WindowManager
    onWindowReady: {
        window.parent = windowContainer;
        window.width = Qt.binding(function() { return windowContainer.width; });
        window.height = Qt.binding(function() { return windowContainer.height; });
    }
    ...
}
...
Item {
    id: windowContainer
    ...
}

you can rewrite it as

import QtApplicationManager.SystemUI 2.0
...
Connections {
    target: WindowManager
    onWindowAdded: {
        windowItem.window = window;
    }
    ...
}
...
WindowItem {
    id: windowItem
    ...
}

See the new Hello World and Animated Windows examples for further explanations on the new way of manipulating windows in your System UI.

WindowManager signals

Signals in WindowManager related to the window lifecycle have all changed. windowReady is the only signal thas has an equivalent in the new API, as seen in the previous code snippet. For others there's no exact match, although the new API has similar signals.

For example, if you have code like

import QtApplicationManager 1.0
...
Connections {
    target: WindowManager
    onWindowClosing: {
        ...
    }
    onWindowLost: {
        ...
    }
    ...
}

you can rewrite it as

import QtApplicationManager.SystemUI 2.0
...
Connections {
    target: WindowManager
    onWindowContentStateChanged: {
        if (window.contentState === WindowObject.SurfaceNoContent) {
            // code from onWindowClosing
            ...
        } else if (window.contentState === WindowObject.NoSurface) {
            // code from onWindowLost
            ...
        }
    }
    ...
}

You can also check and track the content state of a window from its WindowObject.contentState property.

Releasing windows

In the new API there's no longer the concept of releasing windows. Thus the signal WindowManager.windowReleased and the method WindowManager.releaseWindow() have been removed. Instead, a WindowObject is destroyed once it no longer has a backing surface (ie, its contentState is WindowObject.NoSurface) and it is not assigned to any WindowItem.

Window properties

The window properties of a given window are now set, queried and tracked from its WindowObject; the corresponding, old API in the WindowManager singleton has been removed. The code becomes more readable and modular this way:

For example, if you have code like

import QtApplicationManager 1.0
...
WindowManager.setWindowProperty(window, "type", "dialog");
...
Connections {
    target: WindowManager
    onWindowPropertyChanged: {
        if (window === fooWindow) {
            console.log("fooWindow's property " + name + " is now " + value);
        }
    }
}

you can rewrite it as

import QtApplicationManager.SystemUI 2.0
...
window.setWindowProperty("type", "dialog");
...
Connections {
    target: fooWindow
    onWindowPropertyChanged: {
        console.log("fooWindow's property " + name + " is now " + value);
    }
}

Registering compositor views

In the new API, on the System UI side, there's no longer a need to explicitly call WindowManager.registerCompositorView on a Window to be able to composite client application surfaces on them (ie. have WindowItems rendering WindowObjects). This is now handled internally automatically and thus this function has been removed from the Qt Application Manager API.

For example, if you have code like

import QtApplicationManager 1.0
...
QtObject {
    Window {
        id: someSysUIWindow
        visible: true
        ...
        Component.onCompleted: {
            WindowManager.registerCompositorView(someSysUIWindow);
        }
    }
}

you can rewrite it as

import QtApplicationManager.SystemUI 2.0
...
QtObject {
    Window {
        id: someSysUIWindow
        visible: true
        ...
    }
}

SystemMonitor

The SystemMonitor singleton no longer exists. The functionality that it provided has been split into several new components, namely: MonitorModel, CpuStatus, GpuStatus, MemoryStatus, FrameTimer and IoStatus.

For example, if you have code like

import QtApplicationManager 1.0
...
Item {
    id: root
    ...
    Component.onCompleted: {
        SystemMonitor.reportingInterval = 1500;
        SystemMonitor.count = 20;
    }
    Binding { target: SystemMonitor; property: "cpuLoadReportingEnabled"; value: root.visible }

    // Draw a graph of CPU usage
    ListView {
        model: SystemMonitor
        ...
    }
}

you can rewrite it as

import QtApplicationManager 2.0
...
Item {
    id: root
    ...
    // Draw a graph of CPU usage
    ListView {
        model: MonitorModel {
            interval: 1500
            running: root.visible
            maximumCount: 20
            CpuStatus {}
        }
        ...
    }
}

ProcessMonitor

The ProcessMonitor component no longer exists. The functionality that it provided has been split into a couple of new components, namely: ProcessStatus, MonitorModel and FrameTimer.

For example, if you have code like

import QtApplicationManager 1.0
...
Item {
    id: root
    ...
    // Draw a graph of CPU usage
    ListView {
        model: ProcessMonitor {
            count: 20
            cpuReportingEnabled: root.visible
            reportingInterval: 1500
            applicationId: "foo.app"
        }
        ...
    }
}

you can rewrite it as

import QtApplicationManager 2.0
import QtApplicationManager.SystemUI 2.0
...
Item {
    id: root
    ...
    // Draw a graph of CPU usage
    ListView {
        model: MonitorModel {
            maximumCount: 20
            running: root.visible
            interval: 1500
            ProcessStatus {
                applicationId: "foo.app"
            }
        }
        ...
    }
}