Qt Installer Framework 3.0.2 Released

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

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

  • Add possibility to reopen admin query –  Previously in Windows you had 2 minutes to answer to the admin query if installer requested one. If query was not answered within the time frame, installer aborted. Now you have ability to reopen the admin query and continue install.
  • Implement package download resume – package downloads now recover after network failures from the same position, which helps installations of large packages over flaky networks. The download resume also works after switching a network connection or even after resuming a computer from suspended power-save state. This fix was contributed by Ville Voutilainen.
  • Do not reset core when pressing ‘Restart’ – This enables to restart the installer with the same command line arguments.

The full list of bug fixes can be found from ChangeLog.

Sources and precompiled binaries for the Installer Framework are available at download.qt.io (open source), or in your Qt Account. The binaries are built with Qt 5.9.0.

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

How to Add Chat Service and Cross-Platform Leaderboard with User Profiles to Your iOS or Android App

A user chat, friend system or leaderboards increase app retention and engagement rates. This applies for games as well as business apps. V-Play Engine makes it easy to add such features with ready-made social services.

Boost Retention and Engagement Rates with Gamification Services

App retention and user engagement are important key drivers to build up your user base. Many games include features like leaderboards, friend systems or an in-app user chat. They help to keep players engaged and boost long-term retention. It is important to allow your users to connect, compete and form social relationships.

V-Play Engine offers a ready-made solution to help you do that. With the SocialView services, you can add Gamification features within minutes. You can for example:

  • Add User Accounts, Authentication and User Profiles
  • Show Leaderboards with User Highscores
  • Integrate an In-app Chat and Friend System
  • Store Custom User Data in the Cloud
  • and much more.

See this 10-minute video tutorial for a quick overview how it works:

How to Add a Leaderboard Cloud Service with User Profiles

Use a Cross-platform User Login Service for Authentication

It’s easy to integrate gamification features to your app. As everything starts with your users, the first step is clear. Your app has to provide user authentication and user account management.

To make this as easy as possible, the SocialView services work without registration. Every user that installs your app gets a unique user account linked to his device. The following example app takes care of the service configuration and shows the profile of the logged-in user:

import VPlay 2.0
import VPlayApps 1.0

App {

 // service configuration
 VPlayGameNetwork {
   id: gameNetwork
   gameId: 285
   secret: "AmazinglySecureGameSecret"
 }

 // social view setup
 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
 }
}

These few code lines are sufficient. Here is how the application looks like on iOS and Android:

SocialView User Profile

The default profile view supports changing the user name, country or profile picture. Furthermore, the profile is also extensible with a Facebook login. This allows to share the same synchronized user profile across different devices.

Show a Leaderboard in Your iOS or Android App

Apart from the user profile, there are many other SocialView pages you can use in your app. The following example extends the app with a leaderboard page. The user score of this demo matches the total number of app starts. It also adds a main navigation with two menu items. This means, that users can now switch between the profile and leaderboard page.

import VPlay 2.0
import VPlayApps 1.0
import QtQuick 2.9

App {

 // app navigation
 Navigation {
   NavigationItem {
     title: "User Profile"
     icon: IconType.user
     NavigationStack {
       initialPage: socialView.profilePage
     }
   }

   NavigationItem {
     title: "Leaderboard"
     icon: IconType.flagcheckered
     NavigationStack {
       initialPage: socialView.leaderboardPage
     }
   }
 }

 // service configuration
 VPlayGameNetwork {
   id: gameNetwork
   gameId: 285
   secret: "AmazinglySecureGameSecret"

   // increase leaderboard score by 1 for each app start
   Component.onCompleted: gameNetwork.reportRelativeScore(1)
 }

 // social view setup
 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer
   visible: false // we show the view pages on our custom app navigation
 }
}

You get a native tab navigation on iOS, while Android users get a drawer menu. If this is not what you want, you can also change the default navigation mode for the platforms.

socialview-cross-platform-leaderboard

How to Integrate an In-App Chat Service and Store User Data in the Cloud

Add In-App Chat with Friend System and Push Notifications

Adding an in-app chat and friend system to your app is easy as well! With a few more configuration settings, the SocialView turns into a full-featured messenger.

SocialView Chat with Push Notification

This example replaces the leaderboard with a chat and adds the required configuration:

import VPlay 2.0
import VPlayApps 1.0

App {

 // app navigation
 Navigation {
   NavigationItem {
     title: "User Profile"
     icon: IconType.user
     NavigationStack {
       initialPage: socialView.profilePage
     }
   }

   NavigationItem {
     title: "Chat"
     icon: IconType.comment
     NavigationStack {
       initialPage: socialView.inboxPage
     }
   }
 }

 // service configuration
 VPlayGameNetwork {
   id: gameNetwork
   gameId: 285
   secret: "AmazinglySecureGameSecret"
   multiplayerItem: multiplayer
 }

 VPlayMultiplayer {
   id: multiplayer
   appKey: "dd7f1761-038c-4722-9f94-812d798cecfb"
   pushKey: "a4780578-5aad-4590-acbe-057c232913b5"
   gameNetworkItem: gameNetwork
 }

 // social view setup
 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer
   visible: false // we show the view pages on our custom app navigation
 }
}

When you open the chat, you first see the inbox page with all ongoing conversations. From this view you can start new chats or write with existing contacts. The chat service also allows to configure support for push notifications. Users are then notified whenever a new message comes in.

SocialView Chat Inbox and Friend System

As soon as you add the chat to your app, your users can also become friends. This is possible by sending friend requests using the chat system. The SocialView is your single access point for all services. It also shows your friends in a separate section of your leaderboard.

Use Cloud Storage to Store and Search Custom User Details

Another cool feature of the SocialView is the integrated cloud storage: You can enrich your user accounts with custom data for your project. For example, you can let users enter their favorite music genre or food:

SocialView User-based Cloud Storage

The following snippet extends the user profile with custom UI elements to enter and view this data:

 // …

 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer
   visible: false // we show the view pages on our custom app navigation

   // extend user profile with fields to allow storing additional user details
   profileUserDelegate: SocialUserDelegate {
     height: otherUserCol.visible ? otherUserCol.height : userDetailCol.height

     // parse the JSON data stored in customData property, if it is set
     property var userCustomData: !!gameNetworkUser && !!gameNetworkUser.customData ? JSON.parse(gameNetworkUser.customData) : {}

     // column visible for logged-in user, allows editing the custom fields
     Column {
       id: userDetailCol
       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent
       width: parent.width - 2 * x
       spacing: x
       // only show if profile of logged-in user
       visible: gameNetworkUser.userId === gameNetworkItem.user.userId 

       AppText {
         text: "Edit the fields below to set your details."
       }

       // custom data fields
       Column {
         spacing: parent.spacing

         Row {
           spacing: parent.spacing
           Icon {
             id: inputIcon
             icon: IconType.music; color: Theme.tintColor
             anchors.verticalCenter: parent.verticalCenter
           }
           AppTextField {
             id: songInput
             text: !!userCustomData.song ? userCustomData.song : ""
             width: userDetailCol.width - parent.spacing - inputIcon.width
             placeholderText: "Enter your favorite music genre."
             borderWidth: px(1)
           }
         }

         Row {
           spacing: parent.spacing
           Icon {
             icon: IconType.cutlery; color: Theme.tintColor
             anchors.verticalCenter: parent.verticalCenter
           }
           AppTextField {
             id: foodInput
             text: !!userCustomData.food ? userCustomData.food : ""
             width: userDetailCol.width - parent.spacing - inputIcon.width
             placeholderText: "Enter your favorite food."
             borderWidth: px(1)
           }
         }
       }

       // save button
       SocialViewButton {
         text: "Save"
         onClicked: {
           var customData = JSON.stringify({ "song": songInput.text, "food": foodInput.text })
           gameNetworkItem.updateUserCustomData(customData) // store stringified JSON data
         }
       }
     }

     // column visible when viewing other users, show data of custom fields
     Column {
       id: otherUserCol
       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent
       width: parent.width - 2 * x
       spacing: x
       // only show if profile of other user
       visible: gameNetworkUser.userId !== gameNetworkItem.user.userId 

       // show custom data
       Grid {
         spacing: parent.spacing
         columns: 2
         Icon { icon: IconType.music; color: Theme.tintColor }
         AppText { text: !!userCustomData.song ? userCustomData.song : "" }
         Icon { icon: IconType.cutlery; color: Theme.tintColor }
         AppText { text: !!userCustomData.food ? userCustomData.food : "" }
       }
     }
   }
 }

With a single API call, you can load or store JSON objects to the cloud storage. The above example consists of two bigger Column elements. The first one holds all input fields for entering and storing the data. It is only shown when viewing your own profile. Other users see the second item, which only displays the data.

SocialView Profile User Details

With this, your app offers a customized profile view and stores personal user details. But there are much more customization options to extend the SocialView. You can provide a unique user experience for your app with little effort. To learn more about the SocialView and available customization features, see this blog post.

Create Your Own App with Gamification in Minutes!

Gamification features like an in-app chat, a friend system or leaderboards increase app retention. As shown above, V-Play Engine makes it easy to add such features with the SocialView.

SocialView Inbox Chat and UserSearch

SocialView Leaderboard Profile and User Search

You can copy the full example code with all features mentioned above from below. It also shows how to add custom pages to the view and only requires ~230 lines of code!

import VPlay 2.0
import VPlayApps 1.0
import QtQuick 2.9

App {

 // app navigation
 Navigation {
   NavigationItem {
     title: "User Profile"
     icon: IconType.user
     NavigationStack {
       initialPage: socialView.profilePage
     }
   }

   NavigationItem {
     title: "Leaderboard"
     icon: IconType.flagcheckered
     NavigationStack {
       initialPage: socialView.leaderboardPage
     }
   }

   NavigationItem {
     title: "Chat"
     icon: IconType.comment
     NavigationStack {
       initialPage: socialView.inboxPage
     }
   }

   NavigationItem {
     title: "Search"
     icon: IconType.search
     NavigationStack {
       initialPage: mySearchPage
     }
   }
 }

 // service configuration
 VPlayGameNetwork {
   id: gameNetwork
   gameId: 285
   secret: "AmazinglySecureGameSecret"
   multiplayerItem: multiplayer

   // increase leaderboard score by 1 for each app start
   Component.onCompleted: gameNetwork.reportScore(1)
 }

 VPlayMultiplayer {
   id: multiplayer
   appKey: "dd7f1761-038c-4722-9f94-812d798cecfb"
   pushKey: "a4780578-5aad-4590-acbe-057c232913b5"
   gameNetworkItem: gameNetwork
 }

 // social view setup
 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer
   visible: false // we show the view pages on our custom app navigation

   // add button to user profile, which opens a custom user detail page
   profileUserDelegate: SocialUserDelegate {
     id: userDelegate
     SocialViewButton {
       anchors.horizontalCenter: !!parent ? parent.horizontalCenter : null
       text: "Show User Details"
       onClicked: {
         // show custom social page and pass gameNetworkUser
         parentPage.navigationStack.push(userDetailPage, { gameNetworkUser: userDelegate.gameNetworkUser  })
       }
     }
   }
 }

 // page for entering and showing user details
 Component {
   id: userDetailPage
   SocialPage {
     title: "User Details"
     // add a property for the user we want to show on the page
     property GameNetworkUser gameNetworkUser: null

     // parse the JSON data stored in customData property, if it is set
     property var userCustomData: !!gameNetworkUser && !!gameNetworkUser.customData ? JSON.parse(gameNetworkUser.customData) : {}

     // for logged-in user, allow editing the custom fields
     Column {
       id: userDetailCol
       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent
       y: x // padding top
       width: parent.width - 2 * x
       spacing: x
       visible: gameNetworkUser.userId === gameNetworkItem.user.userId // only show if profile of logged-in user

       AppText {
         text: "Edit the fields below to set your details."
       }

       // custom data fields
       Column {
         spacing: parent.spacing

         Row {
           spacing: parent.spacing
           Icon {
             id: inputIcon
             icon: IconType.music; color: Theme.tintColor
             anchors.verticalCenter: parent.verticalCenter
           }
           AppTextField {
             id: songInput
             text: !!userCustomData.song ? userCustomData.song : ""
             width: userDetailCol.width - parent.spacing - inputIcon.width
             placeholderText: "Enter your favorite music genre."
             borderWidth: px(1)
           }
         }

         Row {
           spacing: parent.spacing
           Icon {
             icon: IconType.cutlery; color: Theme.tintColor
             anchors.verticalCenter: parent.verticalCenter
           }
           AppTextField {
             id: foodInput
             text: !!userCustomData.food ? userCustomData.food : ""
             width: userDetailCol.width - parent.spacing - inputIcon.width
             placeholderText: "Enter your favorite food."
             borderWidth: px(1)
           }
         }
       }

       // save button
       SocialViewButton {
         text: "Save"
         onClicked: {
           var customData = JSON.stringify({ "song": songInput.text, "food": foodInput.text })
           gameNetworkItem.updateUserCustomData(customData)
         }
       }
     }

     // for other users, show data of custom fields
     Column {
       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent
       y: x // padding top
       width: parent.width - 2 * x
       spacing: x
       visible: gameNetworkUser.userId !== gameNetworkItem.user.userId // only show if profile of other user

       // show custom data
       Grid {
         spacing: parent.spacing
         columns: 2
         Icon { icon: IconType.music; color: Theme.tintColor }
         AppText { text: !!userCustomData.song ? userCustomData.song : "" }
         Icon { icon: IconType.cutlery; color: Theme.tintColor }
         AppText { text: !!userCustomData.food ? userCustomData.food : "" }
       }
     }
   }
 }

 // page for searching users based on entered details
 Component {
   id: mySearchPage
   SocialUserSearchPage {
     filterToUsersWithCustomData: true // only show results for users with custom data
     userSearchUserDelegate: SocialUserDelegate {
       height: userSearchCol.height + 2 * userSearchCol.spacing

       // parse the JSON data stored in customData property, if it is set
       property var userCustomData: !!gameNetworkUser && !!gameNetworkUser.customData ? JSON.parse(gameNetworkUser.customData) : {}

       // background of user item
       Rectangle {
         anchors.fill: parent
         color: "white"
         border.width: px(1)
         border.color: socialViewItem.separatorColor
       }

       // show user details
       Column {
         id: userSearchCol
         x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent
         y: x // padding top
         width: parent.width - 2 * x
         spacing: x
         anchors.verticalCenter: parent.verticalCenter

         // profile image + user name
         Row {
           spacing: parent.spacing
           SocialUserImage {
             height: dp(26)
             width: height
             source: gameNetworkUser.profileImageUrl
           }
           AppText {
             text: gameNetworkUser.name;
             anchors.verticalCenter: parent.verticalCenter
           }
         }

         // show custom data
         Grid {
           spacing: parent.spacing
           columns: 2
           Icon { icon: IconType.music; color: Theme.tintColor }
           AppText { text: !!userCustomData.song ? userCustomData.song : "" }
           Icon { icon: IconType.cutlery; color: Theme.tintColor }
           AppText { text: !!userCustomData.food ? userCustomData.food : "" }
         }
       }

       // open profile when selected
       MouseArea {
         anchors.fill: parent
         onClicked: socialViewItem.pushProfilePage(gameNetworkUser, parentPage.navigationStack)
       }
     }
   }
 }
}

You can also find the full source code of this example on GitHub:

 

To try out the SocialView and test all features, have a look at this year’s Qt World Summit Conference App:

Qt World Summit 2017 Business Meet and Chat

You can download the app for iOS and Android here:
App Store Google_Play_Badge-1

The full source code of the Qt World Summit demo is also available on GitHub:

 

 

 

More Posts Like This

 

Release 2.14.1: Update to Qt 5.9.3 | Use Live Code Reloading on macOS and Linux
V-Play Update 2.12.1: Qt Quick Designer Improvements

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

How to Make a Qt app

The post How to Add Chat Service and Cross-Platform Leaderboard with User Profiles to Your iOS or Android App appeared first on V-Play Engine.

Writing a Custom Qt 3D Aspect – part 2

Introduction

In the previous article we gave an overview of the process for creating a custom aspect and showed how to create (most of) the front end functionality. In this article we shall continue building our custom aspect by implementing the corresponding backend types, registering the types and setting up communication from the frontend to the backend objects. This will get us most of the way there. The next article will wrap up by showing how to implement jobs to process our aspect's components.

As a reminder of what we are dealing with, here's the architecture diagram from part 1:

Creating the Backend

One of the nice things about Qt 3D is that it is capable of very high throughput. This is achieved by way of using jobs executed on a threadpool in the backend. To be able to do this without introducing a tangled web of synchronisation points (which would limit the parallelism), we make a classic computer science trade-off and sacrifice memory for the benefit of speed. By having each aspect work on its own copy of the data, it can schedule jobs safe in the knowledge that nothing else will be trampling all over its data.

This is not as costly as it sounds. The backend nodes are not derived from QObject. The base class for backend nodes is Qt3DCore::QBackendNode, which is a pretty lightweight class. Also, note that aspects only store the data that they specifically care about in the backend. For example, the animation aspect does not care about which Material component an Entity has, so no need to store any data from it. Conversely, the render aspect doesn't care about Animation clips or Animator components.

In our little custom aspect, we only have one type of frontend component, FpsMonitor. Logically, we will only have a single corresponding backend type, which we will imaginatively call FpsMonitorBackend:

[sourcecode lang="cpp" title="fpsmonitorbackend.h"]
class FpsMonitorBackend : public Qt3DCore::QBackendNode
{
public:
FpsMonitorBackend()
: Qt3DCore::QBackendNode(Qt3DCore::QBackendNode::ReadWrite)
, m_rollingMeanFrameCount(5)
{}

private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override
{
// TODO: Implement me!
}

int m_rollingMeanFrameCount;
};
[/sourcecode]

The class declaration is very simple. We subclass Qt3DCore::QBackendNode as you would expect; add a data member to mirror the information from the frontend FpsMonitor component; and override the initializeFromPeer() virtual function. This function will be called just after Qt 3D creates an instance of our backend type. The argument allows us to get at the data sent from the corresponding frontend object as we will see shortly.

Registering the Types

We now have simple implementations of the frontend and backend components. The next step is to register these with the aspect so that it knows to instantiate the backend node whenever a frontend node is created. Similarly for destruction. We do this by way of an intermediary helper known as a node mapper.

To create a node mapper, just subclass Qt3DCore::QNodeMapper and override the virtuals to create, lookup and destroy the backend objects on demand. The manner in which you create, store, lookup and destroy the objects is entirely up to you as a developer. Qt 3D does not impose any particular management scheme upon you. The render aspect does some fairly fancy things with bucketed memory managers and aligning memory for SIMD types, but here we can do something much simpler.

We will store pointers to the backend nodes in a QHash within the CustomAspect and index them by the node's Qt3DCore::QNodeId. The node id is used to uniquely identify a given node, even between the frontend and all available aspect backends. On Qt3DCore::QNode the id is available via the id() function, whereas for QBackendNode you access it via the peerId() function. For the two corresponding objects representing the component, the id() and peerId() functions return the same QNodeId value.

Let's get to it and add some storage for the backend nodes to the CustomAspect along with some helper functions:

[sourcecode lang="cpp" title="customaspect.h"]
class CustomAspect : public Qt3DCore::QAbstractAspect
{
Q_OBJECT
public:
...
void addFpsMonitor(Qt3DCore::QNodeId id, FpsMonitorBackend *fpsMonitor)
{
m_fpsMonitors.insert(id, fpsMonitor);
}

FpsMonitorBackend *fpsMonitor(Qt3DCore::QNodeId id)
{
return m_fpsMonitors.value(id, nullptr);
}

FpsMonitorBackend *takeFpsMonitor(Qt3DCore::QNodeId id)
{
return m_fpsMonitors.take(id);
}
...

private:
QHash<Qt3DCore::QNodeId, FpsMonitorBackend *> m_fpsMonitors;
};
[/sourcecode]

Now we can implement a simple node mapper as:

[sourcecode lang="cpp" title="fpsmonitorbackend.h"]
class FpsMonitorMapper : public Qt3DCore::QBackendNodeMapper
{
public:
explicit FpsMonitorMapper(CustomAspect *aspect);

Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const override
{
auto fpsMonitor = new FpsMonitorBackend;
m_aspect->addFpsMonitor(change->subjectId(), fpsMonitor);
return fpsMonitor;
}

Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const override
{
return m_aspect->fpsMonitor(id);
}

void destroy(Qt3DCore::QNodeId id) const override
{
auto fpsMonitor = m_aspect->takeFpsMonitor(id);
delete fpsMonitor;
}

private:
CustomAspect *m_aspect;
};
[/sourcecode]

To finish this piece of the puzzle, we now need to tell the aspect about how these types and the mapper relate to each other. We do this by calling QAbstractAspect::registerBackendType() template function, passing in a shared pointer to the mapper that will create, find, and destroy the corresponding backend nodes. The template argument is the type of the frontend node for which this mapper should be called. A convenient place to do this is in the constructor of the CustomAspect. In our case it looks like this:

[sourcecode lang="cpp" title="customaspect.cpp"]
CustomAspect::CustomAspect(QObject *parent)
: Qt3DCore::QAbstractAspect(parent)
{
// Register the mapper to handle creation, lookup, and destruction of backend nodes
auto mapper = QSharedPointer<FpsMonitorMapper>::create(this);
registerBackendType<FpsMonitor>(mapper);
}
[/sourcecode]

And that's it! With that registration in place, any time an FpsMonitor component is added to the frontend object tree (the scene), the aspect will lookup the node mapper for that type of object. Here, it will find our registered FpsMonitorMapper object and it will call its create() function to create the backend node and manage its storage. A similar story holds for the destruction (technically, it's the removal from the scene) of the frontend node. The mapper's get() function is used internally to be able to call virtuals on the backend node at appropriate points in time (e.g. when properties notify that they have been changed).

The Frontend-Backend Communications

Now that we are able to create, access and destroy the backend node for any frontend node, let's see how we can let them talk to each other. There are 3 main times the frontend and backend nodes communicate with each other:

  1. Initialisation — When our backend node is first created we get an opportunity to initialise it with data sent from the frontend node.
  2. Frontend to Backend — Typically when properties on the frontend node get changed we want to send the new property value to the backend node so that it is operating on up to date information.
  3. Backend to Frontend — When our jobs process the data stored in the backend nodes, sometimes this will result in updated values that should be sent to the frontend node.

Here we will cover the first two cases. The third case will be deferred until the next article when we introduce jobs.

Backend Node Initialisation

All communication between frontend and backend objects operates by sending sub-classed Qt3DCore::QSceneChanges. These are similar in nature and concept to QEvent but the change arbiter that processes the changes has the opportunity to manipulate them in the case of conflicts from multiple aspects, re-order them into priority, or any other manipulations that may be needed in the future.

For the purpose of initialising the backend node upon creation, we use a Qt3DCore::QNodeCreatedChange which is a templated type that we can use to wrap up our type-specific data. When Qt 3D wants to notify the backend about your frontend node's initial state, it calls the private virtual function QNode::createNodeCreationChange(). This function returns a node created change containing any information that we wish to access in the backend node. We have to do it by copying the data rather than just dereferencing a pointer to the frontend object because by the time the backend processes the request, the frontend object may have been deleted - i.e. a classic data race. For our simple component our implementation looks like this:

[sourcecode lang="cpp" title="fpsmonitor.h"]
struct FpsMonitorData
{
int rollingMeanFrameCount;
};
[/sourcecode]

[sourcecode lang="cpp" title="fpsmonitor.cpp"]
Qt3DCore::QNodeCreatedChangeBasePtr FpsMonitor::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<FpsMonitorData>::create(this);
auto &data = creationChange->data;
data.rollingMeanFrameCount = m_rollingMeanFrameCount;
return creationChange;
}
[/sourcecode]

The change created by our frontend node is passed to the backend node (via the change arbiter) and gets processed by the initializeFromPeer()
virtual function
:

[sourcecode lang="cpp" title="fpsmonitorbackend.cpp"]
void FpsMonitorBackend::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<FpsMonitorData>>(change);
const auto &data = typedChange->data;
m_rollingMeanFrameCount = data.rollingMeanFrameCount;
}
[/sourcecode]

Frontend to Backend Communication

At this point, the backend node mirrors the initial state of the frontend node. But what if the user changes a property on the frontend node? When that happens, our backend node will hold stale data.

The good news is that this is easy to handle. The implementation of Qt3DCore::QNode takes care of the first half of the problem for us. Internally it listens to the Q_PROPERTY notification signals and when it sees that a property has changed, it creates a QPropertyUpdatedChange for us and dispatches it to the change arbiter which in turn delivers it to the backend node's sceneChangeEvent() function.

So all we need to do as authors of the backend node is to override this function, extract the data from the change object and update our internal state. Often you will then want to mark the backend node as dirty in some way so that the aspect knows it needs to be processed next frame. Here though,
we will just update the state to reflect the latest value from the frontend:

[sourcecode lang="cpp" title="fpsmonitorbackend.cpp"]
void FpsMonitorBackend::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == Qt3DCore::PropertyUpdated) {
const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
if (change->propertyName() == QByteArrayLiteral("rollingMeanFrameCount")) {
const auto newValue = change->value().toInt();
if (newValue != m_rollingMeanFrameCount) {
m_rollingMeanFrameCount = newValue;
// TODO: Update fps calculations
}
return;
}
}
QBackendNode::sceneChangeEvent(e);
}
[/sourcecode]

If you don't want to use the built in automatic property change dispatch of Qt3DCore::QNode then you can disable it by wrapping the property notification signal emission in a call to QNode::blockNotifications(). This works in exactly the same manner as QObject::blockSignals() except that it only blocks sending the notifications to the backend node, not the signal itself. This means that other connections or property bindings that rely upon your signals will still work.

If you block the default notifications in this way, then you need to send your own to ensure that the backend node has up to date information. Feel free to subclass any class in the Qt3DCore::QSceneChange hierarchy and bend it to your needs. A common approach is to subclass Qt3DCore::QStaticPropertyUpdatedChangeBase,
which handles the property name and in the subclass add a strongly typed member for the property value payload. The advantage of this over the built-in mechanism is that it avoids using QVariant which does suffer a little in highly threaded contexts in terms of performance. Usually though, the frontend properties don't change too frequently and the default is fine.

Summary

In this article we have shown how to implement most of the backend node; how to register the node mapper with the aspect to create, lookup and destroy backend nodes; how to initialise the backend node from the frontend node in a safe way and also how to keep its data in sync with the frontend.

In the next article we will finally make our custom aspect actually do some real (if simple) work, and learn how to get the backend node to send updates to the frontend node (the mean fps value). We will ensure that the heavy lifting parts get executed in the context of the Qt 3D threadpool so that you get an idea of how it can scale. Until next time. continue reading

The post Writing a Custom Qt 3D Aspect – part 2 appeared first on KDAB.

Looking for Qt Champions

The end of the year is closing in fast, and it is time to look back at 2017 and think who helped you out most during the past year.

In case you forgot, Qt Champions are the people in the community who go above and beyond the normal activity in the community, and help people out every time. They are the stars that make you feel at home.

It’s time to nominate the Qt Champions for 2017. Please take a minute to think fill in the name and reasons you think this person is a Qt Champion.

Qt Champions can be found in all walks of the Qt Community. The categories we have are:

  • Community Builder
  • Content Creator
  • Quality Assurer
  • Developer
  • Ambassador
  • Rookie of the year
  • Maverick

However if you think someone should be raised in several categories, or has done something that does not fit in these categories, please mention that!

We’ll keep the nominations open until the end of 2017 and then ask the current Qt Champions to evaluate the nominees.

Qt Champions receive hand picked Qt Champion items and a full Qt license for a year. So nominating someone is a nice way of saying Thank you!

Qt Champions

 

The post Looking for Qt Champions appeared first on Qt Blog.

Towards an Improved Qt 3D Studio Runtime

Now that Qt 3D Studio 1.0 has been released, it is time to have a sneak peek at some of the upcoming developments. As outlined in the release announcement, there is work on-going to move the runtime, meaning the engine that renders and runs the scenes, on top of Qt 3D. Let’s take a closer look at this.

Overview

Scenes and Layers

Qt 3D Studio is a design tool that allows rapid development of 3D scenes, focused on, but not limited to, 3D user interfaces. Once assets like 3D models and texture maps are imported, designers create scenes by placing and transforming 3D models, applying materials, and setting up keyframe-based animations that target properties of the models, materials and layers. The concept of layers map naturally to what one may be familiar with from tools like Photoshop: each layer contains a 3D scene with its own camera. These are then composited together based on their position, size and blending settings, thus forming the final output of the rendering.

On the layer level there are multiple antialiasing techniques available, like multisampling, supersampling, progressive and temporal antialiasing. See the documentation for an overview of these.

Slides

All this is complemented by a slide system, not unlike presentation tools like Powerpoint. A slide could be thought of as a state: it defines the set of active (visible) objects, the property changes that get applied to the various scene objects, and the set of animations that start when entering the slide in question. This is complemented by the concept of the master slide, which allows defining a set of objects and animations that are present on all slides.

Materials

When the default material, that provides pixel-based lighting, directional, point and area lights, shadow mapping, screen space ambient occlusion, image-based lighting and a number of other features, is not sufficient, custom materials can be applied. These provide custom (fragment) shader code together with a set of properties that form the input to the shaders. Such properties are editable and animatable in the editor just like the built-in ones. While many custom materials will contain a single shader, they can also contain multiple ones, thus defining multiple passes that run in order, each of them further processing the results of the previous passes.

Effects

To apply effects on the content of a given layer, post-processing effects can be used. These are similar to custom materials, but take the output of the 3D rendering from a given layer as their input. Conceptually they map to the ShaderEffect items of Qt Quick but are somewhat more powerful.

Sub-presentations

While one presentation (a single .uip file) describes a single scene (albeit with multiple layers, hence it is more like a 2D composition of multiple 3D scenes), it is possible to have multiple presentations loaded and run in parallel. Here one presentation serves as the “main” one, which is the presentation that gets rendered to the screen. The others serve as sub-presentations that are first rendered offscreen, and then used as texture maps in the materials of the main scene. They can also be used as the source for one or more of the layers of the main presentation.

Building on this, Qt 3D Studio also offers interoperation with Qt Quick. This is achieved by the familiar QQuickRenderControl. This means that interactive Qt Quick scenes can be displayed inside the Qt 3D Studio scene.

This list, while already long enough, does not cover everything. See the documentation for more details.

Qt 3D Studio in action

Qt 3D Studio in action

The screenshot shows many of the facilities mentioned above:

  • The slide management pane on the left,
  • the pane on the right that displays either basic objects (that can be dragged into the scene) or the presentation and asset browser (where 3D models and texture maps are dragged and dropped in order to import assets, and then dragged into the scene or the scene browser below),
  • the bottom pane contains the scene browser (note how the example has two layers, each with its own camera, lights and models) and the timeline that is used to define and edit keyframes,
  • the bottom-right pane, showing the properties for the currently selected model, material or other object.

What’s in a Runtime?

The main editor application is complemented by the so-called runtime component, which consists of the C++ and OpenGL-based engine that renders and runs the presentations created with the editor both in the viewer application shipped with Qt 3D Studio and in any other Qt applications. The APIs provided allow integrating Qt 3D Studio scenes into Qt Quick, QWidget and QWindow-based applications, and also provide facilities for rendering completely offscreen in order to generate videos for example. The rendering APIs are complemented by a set of QML and C++ APIs that allow changing properties of the scene objects at runtime and controlling the slide and animation system. See the links to the documentation for more details.

Qt 3D Studio Viewer example

The same scene in the standalone Qt 3D Studio Viewer application

For an impression of what the APIs Qt application developers would use look like, let’s look at the source of two of the included examples. First, a straightforward pure QWindow-based application (can be found under example/studio3d/surfaceviewer):

#include <QtStudio3D/Q3DSSurfaceViewer>
#include <QtStudio3D/Q3DSViewerSettings>
#include <QtStudio3D/Q3DSPresentation>
#include <QtStudio3D/Q3DSSceneElement>
#include <QtStudio3D/Q3DSElement>
...
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QWindow window;

    QSize size(1200, 800);
    window.resize(size);
    window.setSurfaceType(QSurface::OpenGLSurface);
    window.setTitle(QStringLiteral("Qt 3D Studio surface viewer example"));
    window.create();

    QOpenGLContext context;
    context.setFormat(window.format());
    context.create();

    Q3DSSurfaceViewer viewer;
    viewer.presentation()->setSource(QUrl(QStringLiteral("qrc:/presentation/circling_cube.uip")));
    viewer.setUpdateInterval(0);
    viewer.settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
    viewer.settings()->setShowRenderStats(true);

    Q3DSSceneElement sceneElement(viewer.presentation(), QStringLiteral("Scene"));
    Q3DSElement counterElement(viewer.presentation(), QStringLiteral("Scene.Layer.Loopcounter"));

    viewer.initialize(&window, &context);

    window.show();

    int n = 0;
    QString loopCounter = QStringLiteral("Loop %1");
    QObject::connect(&sceneElement, &Q3DSSceneElement::currentSlideIndexChanged, [&]() {
        if (sceneElement.currentSlideIndex() == 1)
            n++;
        counterElement.setAttribute(QStringLiteral("textstring"), loopCounter.arg(n));
    });

    return app.exec();
}

In practice one will likely rather use the Qt Quick integration, at the core of which stands the Studio3D element. Under the hood this is built on QQuickFramebufferObject. (the snippet here is from examples/studio3d/qmldynamickeyframes).

import QtQuick 2.7
import QtStudio3D 1.0

Item {
    ...
    
    Studio3D {
        id: studio3D
        anchors.fill: parent

        // ViewerSettings item is used to specify presentation independent viewer settings.
        ViewerSettings {
            scaleMode: ViewerSettings.ScaleModeFill
            showRenderStats: false
        }

        // Presentation item is used to control the presentation.
        Presentation {
            source: "qrc:/presentation/dyn_key.uip"

            // SceneElement item is used to listen for slide changes of a scene in the presentation.
            // You can also change the slides via its properties.
            SceneElement {
                id: scene
                elementPath: "Scene"
                onCurrentSlideIndexChanged: {
                    console.log("Current slide : " + currentSlideIndex + " ("
                                + currentSlideName + ")");
                }
                onPreviousSlideIndexChanged: {
                    console.log("Previous slide: " + previousSlideIndex + " ("
                                + previousSlideName + ")");
                }
            }

            // Element item is used to change element attributes
            Element {
                id: materialElement
                elementPath: "Scene.Layer.Sphere.Material"
            }

            property int desiredSlideIndex: 1
            property int colorIndex: 0
            property var colorArray: [
                [1.0, 1.0, 1.0],
                [1.0, 0.0, 0.0],
                [0.0, 1.0, 0.0],
                [0.0, 0.0, 1.0],
                [0.0, 1.0, 1.0],
                [1.0, 0.0, 1.0],
                [1.0, 1.0, 0.0]
            ]

            function nextSlide() {
                // Separate desiredSlideIndex variable is used to keep track of the desired slide,
                // because SceneElement's currentSlideIndex property works asynchronously.
                // This way the button click always changes the slide even if you click
                // it twice during the same frame.
                desiredSlideIndex = desiredSlideIndex != 3 ? desiredSlideIndex + 1 : 1;
                scene.currentSlideIndex = desiredSlideIndex
                slideButtonText.text = "Change Slide (" + desiredSlideIndex + ")"
            }

            function resetTime() {
                scene.goToTime(0);
            }

            function changeColor() {
                colorIndex = colorIndex >= colorArray.length - 1 ? colorIndex = 0 : colorIndex + 1;
                materialElement.setAttribute("diffuse.r", colorArray[colorIndex][0]);
                materialElement.setAttribute("diffuse.g", colorArray[colorIndex][1]);
                materialElement.setAttribute("diffuse.b", colorArray[colorIndex][2]);
                changeColorButton.color = Qt.rgba(colorArray[colorIndex][0],
                                                  colorArray[colorIndex][1],
                                                  colorArray[colorIndex][2], 1.0);
            }
        }
        onRunningChanged: console.log("Presentation running")
    }
    ...

(Before anyone asks: The ability to embed the output of the various Qt UI frameworks into each other opens up the possibility for creative recursive solutions indeed. However, while the idea of embedding a Qt Quick scene into a Qt 3D Studio scene embedded again in Qt Quick which then perhaps gets embedded into a plain Qt 3D scene which in turn can be part of another Qt Quick scene, … may sound exciting at first, it is best not to overdo it.)

Of course, the editor application itself also needs to display, edit and have fine-grained control over the scene. In the current iteration (1.0) not everything is unified in this respect, meaning the way the editor renders under the hood is not necessarily based on the same code as in the viewer or in the external applications. Longer term we expect to have a more unified approach in place. For now, let’s focus on the runtime from the perspective of a typical Qt application.

Towards Qt 3D Studio 2.0

You said C++ and OpenGL. Good enough, no?

The 1.0 runtime is pretty portable already and it comes with the necessary Qt integration bits as shown above. However, as it is based on the code inherited from the original NVIDIA contribution with only certain parts Qt-ified, and with a strong dependency to OpenGL, there is room for improvement. Fortunately, it turns out we have a good way forward – while staying fully compatible with presentations created with the already released version 1.0.

Qt 3D 2.0 (not to be confused with the Qt 3D 1.0 project from Qt 4 times) has been introduced to Qt 5 by developers from KDAB. See this post for an introduction. Besides providing the necessary building blocks, like an entity-component system and the concept of framegraphs that turn out to be an excellent tool for describing how to render multi-pass 3D scenes in a data-driver manner, its abstractions become handy also when looking towards the future where graphics APIs other than OpenGL will play an increasingly important role.

Therefore, back in April we started a little experiment under the Dragon3 internal codename to see what it would take to load and run those .uip presentations on top of Qt 3D. The new code base is developed with the familiar Qt style and conventions, thus providing a better, more maintainable, and more future-proof component in the larger Qt ecosystem. This is the project now often referred to as the Qt 3D Studio Runtime 2.0, with a first release due around May 2018 together with Qt 3D Studio 2.0. Like Qt 3D Studio itself, the code is available in public already today, although it does come with a huge disclaimer of being heavily work in progress.

Should I wait then?

Not at all. As mentioned before, compatibility is a priority, so for all practical purposes the 1.0 release is the thing to use. Naturally those who feel like experimenting are welcome to check out the code from the qt3d-runtime repository as well (which needs the dev (eventually 5.11) branch of qtbase and qt3d to build).

Let’s continue in the next post. In the meantime those who cannot wait and are keen on diving into the juicy details can check out my presentation at the Qt World Summit earlier this year.

That’s all for now, happy 3D hacking!

The post Towards an Improved Qt 3D Studio Runtime appeared first on Qt Blog.

Qbs 1.10 released

Qbs (pronounced “Cubes”) is The Qt Company’s latest build tool, which aims to be the replacement for qmake in the Qt build system. In addition to its use within Qt, for our customers Qbs will also provide faster build times coupled with a rich feature set in order to reduce build engineering complexity and decrease time to market.

Today I’m excited to introduce you to the latest release of Qbs – 1.10.

What’s New?

This release focuses on bug fixing and general enhancements, specifically to the Qbs language.

Language Improvements

Profiles can now be defined dynamically in a project using the new Profile language item. This is useful for when a project has specific, well-known requirements regarding the build environment and/or target platform.

Group nesting now works more naturally with respect to prefixes. If a Group does not define the prefix property, its value will be taken from the parent group (and so on until a prefix is found or the product level is reached).

Modules and file taggers may now set priority levels. This allows Qbs to disambiguate between multiple implementations of the same module whose conditions evaluate to true, or multiple file taggers that would tag the same files – essentially, a conflict resolution mechanism. Simply set the priority property of a Module or FileTagger to an integer value greater than zero. The instance with the highest value wins. For example, Qbs uses this to choose the cpp module implementation on different platforms. Because the Android implementation is a superset of the Linux implementation, both the Linux and Android implementations are available on Android, but because the latter has a higher priority level, that implementation gets chosen.

It is now possible to add file tags to generated artifacts by setting the new fileTags property in a group that has a fileTagsFilter. This allows you to “append” to the list of file tags assigned to artifacts created by a rule that is defined in a module which is outside your control.

Documentation

Another big focus of this release was enhancing the documentation (and even more significant changes in this area will come with Qbs 1.11).

To start with, we’ve added two new major pages. The first is a qmake porting guide, which contains an overview of various qmake variables and how to achieve the same functionality in Qbs. The second is a “how-to” page on how to create modules for third party libraries. We plan to have many more of these “how-to” style guides showing how to solve common build system problems with Qbs.

We also added in-depth descriptions of all command line tools and their respective options, and a man page for the qbs command line tool.

Platform Support

This release adds a few notable platform-specific features: initial support for the Universal Windows Platform, and the run command can now deploy and run Android apps on devices, and deploy and run iOS and tvOS apps on the simulator.

Qt Support

This release adds support for the Qt Quick compiler and for qmlcachegen.

Other New Features

  • The TextFile service can now append to existing files using the new TextFile.Append open mode.
  • Process and TextFile objects in rules, commands and configure scripts are now closed automatically after script execution.
  • Added the vcs module to provide VCS repository information. Git and Subversion are supported initially.
  • Added the cpufeatures module for abstracting compiler flags related to CPU features such as SSE.
  • Added property cpp.discardUnusedData abstracting linker options that strip unneeded symbols or sections.
  • Added property cpp.variantSuffix for making binary names unique when multiplexing products.
  • Added property cpp.compilerDefinesByLanguage providing the compiler’s pre-defined macros.
  • Added new command line sub-command list-products which lists the names of the products available in the project.

Try It!

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

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

Qbs 1.10 is also included in Qt Creator 4.5, which was also released this week.

The post Qbs 1.10 released appeared first on Qt Blog.

Qt 5.10 released

I’m happy to let you all know that Qt 5.10 has just been released. Qt 5.10 comes with a ton of new functionalities that I’m thrilled to talk to you about.

Before we dive into all the great new features of Qt 5.10, I want to talk to you about another exciting new addition to Qt being released today.

Qt 3D Studio

As the name suggests, Qt 3D Studio is a graphical editor used to create of 3D user interfaces and is derived from the NVIDIA Drive Design product that NVIDIA contributed to Qt earlier this year.

Qt 3D Studio consists of both a runtime component that is run in your application and a graphical design tool to design and create the UI. While the tool is a standalone application, the runtime can easily be integrated with the rest of Qt.

Qt 3D Studio will work with both Qt 5.9 and 5.10. The runtime and the 3D Studio application are both available under commercial and GPL licensing. For more details, please have a look at the separate blog post about it.

qt3dstudio_floorplan_preview

Qt Qml, Qt Quick, and Qt Quick Controls

A lot of exciting new things have happened in this area. Qt Quick has now gained a plugin that allows placing arbitrarily shaped items into the scene. Have a look at the blog post and documentation for more details.

shape_tiger

The new pointer handlers are the next big new feature in Qt Quick. This is a large step forward for Qt Quick that significantly improves how to handle many more complex multi-touch use cases. Instead of using Mouse- and TouchArea to handle those input events, you can now attach handlers for different types of pointer events to any item. Support for this is still in technology preview. Please have a look at the blog post and documentation for all the details.

On top of that, Qt Quick gained a larger amount of smaller enhancements. Chief among them the support to directly load ETC1 and ETC2 compressed textures, multisampling support for layers and some properties to tune font handling.

Qt Quick Controls 2 has also received many new functionalities. First of all, there are now two new styles available. One is an image-based style that makes it very easy to use your own artwork to create a custom look and feel. The other one, called Fusion style, gives a platform agnostic, desktop-oriented look and feel. Those styles also support propagating palettes.

Left: Imagine style - Right: Fusion style

Left: Imagine style – Right: Fusion style

We’ve also added Action, ActionGroup and MenuBar items. Outside of MenuBar, Actions are also supported in buttons, delegates, and menus. In addition, we added numerous smaller features to existing controls.

Qt Qml finally supports declaring enums in QML and dynamically retranslates all strings on language changes.

Graphics

A massive new feature in the graphics area is a new QPA plugin that allows streaming a full Qt User Interface to any WebGL enabled browser. You can find details in this blog post.

On the OpenGL side, QSurfaceFormat can now be used to request sRGB-compatible framebuffers, and the full set of the OpenGL ES 3.2 API is now available across platforms through QOpenGLExtraFunctions.

Qt 3D

Thanks to our friends at KDAB, Qt 3D has also gained a couple of new features. There are new node types that can be used in frame graphs, such as a proximity filter and a framebuffer blit. We now have support for Shader graphs that enable the creation of shaders from a graph based description, a technology preview of a skeletal animation system and a Scene2D Qt Quick element, which simplifies embedding Qt 3D content in a Qt Quick Scene.

Apart from that, the focus on Qt 3D development is now slowly shifting from developing all the required features to improving performance and memory consumption. Some of the results of that effort can be seen in the following blog post.

Qt 3D will also become much more important for Qt moving forward. We are currently working on basing the runtime for Qt 3D Studio on top of Qt 3D in order to unify the architecture for all our 3D related APIs and tools.

Qt Core and Network

Qt Core now has a brand new QStringView class, that is conceptually similar to std::string_view. For the moment, it’s still missing some const functions from QString, but that will get finalized for Qt 5.11.

Qt Core also received a new QRandomGenerator class that provides a high-quality random generator and access to seedless random numbers generated with hardware or operating system facilities. There’s now also a set of explicit big/little endian data types (qint16_le, etc), and a KeyValueIterator for our associative containers that provide STL compatible iteration semantics over those containers.

Qt Network now supports OpenSSL 1.1, stores HSTS (HTTP Strict Transport Security) policies in a persistent way in QNetworkAccessManager and has implemented the h2c protocol upgrade used by non-SSL HTTP/2.

Qt Widgets

We have added a couple of smaller features, such as QWidget::createWindowContainer() on Android, enabling QOpenGLWidget for rendering and grabbing offscreen content, adding a tabStopDistance property in QTextOption and QTextEdit and an API for better selection handling to QLineEdit. QDockWidgets can now be dropped side by side.

Additionally, a large set of bugs have been fixed in this module for Qt 5.10.

Embedded functionality

While most of the items above improve our overall offering, both for application development and device creation, we also have some items that focus on the embedded side.

The Qt Virtual Keyboard has gained support for many new languages and handwriting support for Arabic, Farsi, Chinese, Japanese and Korean.

A brand-new version of the device emulator is coming with Qt 5.10. It now supports multiple screens, multitouch and has received support for plugins. Have a look at the separate blog post for details.

On the Boot2Qt side, we updated our device images to Yocto 2.3 (Pyro), giving you a more up-to-date Linux to base your work upon.

Qt for Automation, containing the KNX and MQTT modules, is now also available in Qt 5.10.

Other modules

We updated Qt WebEngine to use Chromium 61. You can now pause and resume downloads and start them programmatically.

On Windows desktop, you can now use the UWP backend for Qt Bluetooth on Windows, and on X11, the Qt X11Extras module now allows peeking into the event queue.

Finally, Qt Network Authorization (providing support for OAuth 1 & 2) and the text-to-speech support in Qt Speech graduated from technology preview to being fully supported in 5.10.

For more details, have a look at the new features page on the wiki, our dedicated Qt 5.10 web page and our change logs for each Qt module.

I hope you will enjoy the release, and I’d like to thank everybody who has contributed to making it happen. As always, you can get this release from your Qt Account page or our download section on the web.

The post Qt 5.10 released appeared first on Qt Blog.

Qt Creator 4.5.0 released

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

CMake Support

Variables in the configuration UI in the Projects mode are now grouped by prefix, and have type-specific editors for boolean and path values. You can also change the type of variables and unset accidentally added ones. Also, we improved the handling of configuration changes outside of Qt Creator. The change notification now shows detailed information about how the cached values  differ from the values on disk.

Android Support

Integrated Adnroid SDK package manager - Qt Creator 4.4
Since Android SDK tools version 25.3.0, there is no UI tool available to manage the Android SDK packages. Because of that, we have added such UI to Qt Creator. Unfortunately, the command line tool for managing SDKs that is provided with the SDK cannot update packages on Windows, and fails with JDK 9, so this applies to Qt Creator as well. Also, we provide better information about problems with the installed SDK, such as missing components or not met minimum version requirements.

Qt Creator no longer supports local deployment nor Ant, starting with this version. Both features have been deprecated for a long time.

Other Improvements

We started on making the File System navigation pane more useful. It is showing a file system tree now, and you can select the root directory from a list containing the “computer” root, your home directory, your default projects directory, and the base directories of all the projects you have open in Qt Creator. More features are to come in the future.

Locator now does fuzzy camel case matching in the same way as code completion does. For example, you can type “c andesu” in the locator to open the “AndroidDebugSupport” class.

On Windows, we fixed detection of Visual Studio Build Tools 2017.

For iOS, we had to fix our mechanism for switching between simulator device types with Xcode 9, because that changed the behavior of the Simulator application.

If you used Tools > External > Text > Sort Selection before, and wonder if we have removed this useful feature, I can reassure you that we have not. On the contrary, we made it a first-class citizen instead of an external tool, and moved the menu entry to Edit > Advanced > Sort Selected Lines.

This release includes many more improvements and fixes. Please, take a look at our change log for a more detailed overview.

Get Qt Creator 4.5.0

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

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

How to Add In-App Chat or Gamification Features to Your Mobile App

Many successful apps allow users to interact, compete or build social relationships. Features like an in-app chat, a friend system or leaderboards help to increase app retention and engagement rates. This applies for games as well as apps. The SocialView makes it easy to add such features. It takes advantage of ready-made services and also offers e.g. user profiles & authentication, cloud storage and much more. If you think this sounds complex, don’t worry: This post shows you how to add such features without a hassle.

Using Social Services is Easy!

… at least with the SocialView, which includes many ready-made social features. This makes it easy for you to create apps with e.g. user profiles, leaderboards or a messaging and friend system. For example, this year’s conference management app for the Qt World Summit 2017 uses these services and allows you to:

  • Search conference attendees to schedule Business Meetings.
  • Store custom user data like the company, job position or main Qt interest.
  • View user details and find conference attendees that match certain criterias.
  • Log in via Facebook to synchronize your data across devices.
  • Become friends and get in touch with the included in-app chat.
  • See a leaderboard with a ranking of users that favor many talks and are active.

business-meet-and-chat

You can have a look and try out the features by downloading the app for iOS or Android:

App Store Google_Play_Badge-1

This is already a rich feature set, but there is much more you can do. The SocialView is extensible and allows to customize all features!

A cloud-based backend and easy-to-use client QML components build the core of the view. The SocialView integrates these cloud services so you can use them in your app. Among many other features, the SocialView services include:

  • User Profiles and Authentication: Each user registers with the social services as soon as he first opens your app. No registration required.
  • Social Leaderboards: You can let players compare against each other in a competitive way, keeping them playing.
  • Fully Customizable UI: With the strength of QML you can customize all views to your app and give an extra-polished look.
  • Integrated Cloud Storage: Store project-specific data for your users in the cloud.
  • Friend System: Add your friends or make new friends with other users you meet in-app.
  • In-App Chat & Push Notifications: You can chat with your friends, even if they’re not online. This makes it easy for your users to get in touch. They also receive Push Notifications for each incoming message.
  • Facebook Login & Account Synchronization: You can allow users to log-in with Facebook. This enables them to synchronize their profile and progress across devices.
  • Native Look and Feel: The view provides a native style and user experience on both iOS and Android.
  • Fully Cross-Platform: All features work cross-platform, so your iOS users can also connect or play with Android users.

mobile-chat

To see how to add such services, have a look at the Qt World Summit 2017 app. It shows how to use the SocialView and enriches it with custom features. The full updated source code is available for you on GitHub.

How to Add User Profiles or an In-App Chat with the SocialView

The SocialView offers a flexible usage for both games and apps. You can add user profiles, leaderboards or the messaging and friend system to any project.

Use the SocialView Standalone

The view contains several pages that each cover a certain use-case:

  • profilePage – shows the user profile a GameNetworkUser
  • leaderboardPage – shows the highscores for a certain leaderboard and time frame
  • inboxPage – shows the active chats of the currently logged-in user
  • chatPage – shows a chat of the logged-in user with another user
  • newMessagePage – shows a user search and allows to start a chat

If not specified otherwise, it shows the user profile of the logged-in user by default. This is how a minimum example setup for a full-featured SocialView integration looks like in QML:

import VPlay 2.0

GameWindow {
 VPlayGameNetwork {
   id: gameNetwork
   gameId: 285
   secret: "AmazinglySecureGameSecret"
   multiplayerItem: multiplayer
 }

 VPlayMultiplayer {
   id: multiplayer
   appKey: "dd7f1761-038c-4722-9f94-812d798cecfb"
   pushKey: "a4780578-5aad-4590-acbe-057c232913b5"
   gameNetworkItem: gameNetwork
 }

 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer
 }
}

No extra code needed. The view also is a full-featured NavigationStack type by itself. So you can configure the initialPage or e.g. push the default leaderboard with simple call to:

socialView.push(socialView.leaderboardPage)

This is the perfect way for integrating the view to V-Play Games.

Add SocialView Pages to your App Navigation

The SocialView contains several individual social pages. They are independent pages, but linked to the SocialView behind the scenes. Each page can work with any NavigationStack layout you might use in your existing V-Play App.

The following code snippet creates an app with two separate navigation tabs. One for the user profile, and one for showing the inbox of the friend and messaging service:

import VPlay 2.0
import VPlayApps 1.0

App {

 VPlayGameNetwork {
   id: gameNetwork
   gameId: 285
   secret: "AmazinglySecureGameSecret"
   multiplayerItem: multiplayer
 }

 VPlayMultiplayer {
   id: multiplayer
   appKey: "dd7f1761-038c-4722-9f94-812d798cecfb"
   pushKey: "a4780578-5aad-4590-acbe-057c232913b5"
   gameNetworkItem: gameNetwork
 }

 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer
   visible: false // hide social view, as we show the pages on custom NavigationStacks instead
 }

 // main navigation
 Navigation {

   // first navigation item: Profile
   NavigationItem {
     title: "Profile"
     icon: IconType.user

     NavigationStack {
       initialPage: socialView.profilePage
     }
   }

   // second navigation item: Chat Inbox
   NavigationItem {
     title: "Chat"
     icon: IconType.comment

     NavigationStack {
       initialPage: socialView.inboxPage
     }
   }
 }
}

This already shows the flexible usage possibilities of the new view. The approach in the above example works with the page properties of the SocialView. This is the fastest way for adding e.g. the own user profile or the default leaderboard to your app navigation.

You can also show a different user profile or leaderboard. The SocialView provides functions that let you pass your desired settings. For example, the following call displays the profile of a certain user:

socialView.pushProfilePage(gameNetworkUser, targetNavigationStack)

The function also allows to specify the target NavigationStack for adding the page. Similar functions exist for all available SocialView pages. So you can integrate the social pages anywhere in your app!

Customize the Features and Look of your Social Services

Each project is different and has its own unique style. To add your own style to the view, there are several customization options you can use. They allow to:

  • Match the view colors and fonts with your project style.
  • Enrich the UI with custom elements and features.
  • Introduce completely new social pages.

The V-Play Apps types build the core of the customizable SocialView UI. This means, it also comes with a native look and feel for Android and iOS and e.g. offers a native back navigation.

Change the View Colors and Fonts

The SocialView offers several properties for the general look of all social pages. It is possible to customize used fonts and colors to match your project style with a few lines of code.

The view tint matches the configured color of your app theme by default. No further adjustments needed if this is the color of your choice for the social pages.

The following example disables the user country feature and sets an orange tint. It also switches to the configured theme font instead of the default social view font:

SocialView {
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer

   // custom styling
   tintColor: "orange"
   tintLightColor: Qt.lighter(tintColor, 1.2)
   countryCodeEnabled: false
   bodyFontName: Theme.normalFont.name
   headerFontName: Theme.normalFont.name
 }

Add Custom UI Elements with Delegates

The V-Play Game Network service allows to store project-specific data of your users. In your app, this data is available with the customData property. The Qt World Summit app also sets this field to store personal information, e.g. the Qt interest, on the profile page.

profile-custom-views

But how can you display the UI for editing or showing this information in the user profile?

The SocialUserDelegate type lets you provide the full QML code of such additions. It is set up to represent a single GameNetworkUser, which the view displays in the social pages.

Let’s say you allow users to enter a custom description text somewhere in your app, which you store as custom data. This simple code snippet allows you to display the description in the user profile:

SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer

   // show custom user data in profile
   profileUserDelegate: SocialUserDelegate {
     AppText {
       text: gameNetworkUser.customData 

       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent / padding
       width: parent.width-x
       font.pixelSize: sp(14)
       wrapMode: AppText.WrapAtWordBoundaryOrAnywhere

       // add social view style to text
       font.family: socialViewItem.bodyFontName
       color: socialViewItem.bodyColor
     }
   }
 }

That is all you need! The new custom text now shows up in the user profile page:

Extend the profile page with a custom delegate.

The above example uses the profile user delegate, which is not set to a specific item by default.
Other delegates for e.g. the leaderboard and inbox page are already predefined. Each delegate item represents a single user of the displayed list in this case.

To customize these user lists, you can overwrite the used delegates. This example replaces each score entry of the leaderboard with a custom QML item:

SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer

   leaderboardUserDelegate: SocialUserDelegate {
     height: col.height

     // show user name and score below each other
     Column {
       id: col
       anchors.centerIn: parent
       AppText {
         anchors.horizontalCenter: parent.horizontalCenter // center name horizontally
         text: gameNetworkUser.name
       }
       AppText {
         anchors.horizontalCenter: parent.horizontalCenter // center score horizontally

          // it is possible to access each response entry of the related API request using modelData
         text: "Score: " + modelData.value
       }
     }
   }
 }

The new social delegate system is the perfect way to customize the social pages to your liking! But that is not all, you can even throw in completely custom social pages.

How to Create New Social Pages

The ability to add your own delegates also opens another possibility. You can extend the view with custom social pages, which extend the new SocialPage base type. It works together with SocialView to:

  • Offer quick access to the Game Network and Multiplayer features.
  • Show a loading indicator in the navigation bar. Your users will see that there’s a loading process going on whenever there are pending API requests.
  • Apply the configured SocialView styling like the view tint color or body font.

Let’s upgrade the profile page and add a button. It will take us to a new social page, where we show the custom data of the user:

SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer

   profileUserDelegate: SocialUserDelegate {
     id: userDelegate
     SocialViewButton {
       anchors.horizontalCenter: parent.horizontalCenter
       text: "Show User Details"
       onClicked: {
         // show custom social page and pass gameNetworkUser
         parentPage.navigationStack.push(userDetailPage, { gameNetworkUser: userDelegate.gameNetworkUser  })
       }
     }
   }
 }

Component {
   id: userDetailPage
   SocialPage {
     // add a property for the user we want to show on the page
     property GameNetworkUser gameNetworkUser: null

     // show custom data
     AppText {
       text: gameNetworkUser.customData

       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent/padding
       width: parent.width-x
       font.pixelSize: sp(14)
       wrapMode: AppText.WrapAtWordBoundaryOrAnywhere

       // add social view style to text
       font.family: socialViewItem.bodyFontName
       color: socialViewItem.bodyColor
     }
   }
 }

This addition uses the profileUserDelegate to extend the profile page. It adds a button, which takes us to a new custom social page:

Add buttons to integrate custom social pages.

That page only shows the plain string text value of customData. But of course you could do much more. The following example extends the above code to allow saving the favorite song and food for each user. The userDetailPage now shows input fields to edit and store the data for the logged-in user. When viewing the profiles of other users, it just displays the stored values:

import VPlay 2.0
import VPlayApps 1.0
import QtQuick 2.9

App {
 VPlayGameNetwork {
   id: gameNetwork
   gameId: 285
   secret: "AmazinglySecureGameSecret"
   multiplayerItem: multiplayer
 }

 VPlayMultiplayer {
   id: multiplayer
   appKey: "dd7f1761-038c-4722-9f94-812d798cecfb"
   pushKey: "a4780578-5aad-4590-acbe-057c232913b5"
   gameNetworkItem: gameNetwork
 }


 SocialView {
   id: socialView
   gameNetworkItem: gameNetwork
   multiplayerItem: multiplayer

   profileUserDelegate: SocialUserDelegate {
     id: userDelegate
     SocialViewButton {
       anchors.horizontalCenter: parent.horizontalCenter
       text: "Show User Details"
       onClicked: {
         // show custom social page and pass gameNetworkUser
         parentPage.navigationStack.push(userDetailPage, { gameNetworkUser: userDelegate.gameNetworkUser  })
       }
     }
   }
 }

 Component {
   id: userDetailPage
   SocialPage {
     title: "User Details"
     // add a property for the user we want to show on the page
     property GameNetworkUser gameNetworkUser: null

     // parse the JSON data stored in customData property, if it is set
     property var userCustomData: !!gameNetworkUser && !!gameNetworkUser.customData ? JSON.parse(gameNetworkUser.customData) : {}

     // for logged-in user, allow editing the custom fields
     Column {
       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent
       y: x // padding top
       width: parent.width-x
       spacing: x
       visible: gameNetworkUser.userId === gameNetworkItem.user.userId // only show if profile of logged-in user

       AppText {
         text: "Edit the fields below to set your details."
       }
       AppTextField {
         id: songInput
         text: !!userCustomData.song ? userCustomData.song : ""
         placeholderText: "Enter your favorite song."
       }
       AppTextField {
         id: foodInput
         text: !!userCustomData.food ? userCustomData.food : ""
         placeholderText: "Enter your favorite food."
       }
       SocialViewButton {
         text: "Save"
         onClicked: {
           var customData = JSON.stringify({ "song": songInput.text, "food": foodInput.text })
           gameNetworkItem.updateUserCustomData(customData)
         }
       }
     }

     // for other users, show data of custom fields
     Column {
       x: dp(Theme.navigationBar.defaultBarItemPadding) // add indent
       y: x // padding top
       width: parent.width-x
       spacing: x
       visible: gameNetworkUser.userId !== gameNetworkItem.user.userId // only show if profile of other user

       AppText {
         text: "Favorite Song: "+(!!userCustomData.song ? userCustomData.song : "")
       }
       AppText {
         text: "Favorite Food: "+(!!userCustomData.food ? userCustomData.food : "")
       }
     }
   }
 }
}

 

The detail page now allows to enter and store the custom data:
The final userDetailPage allows to enter your favorite song and food.

You can see all customization features in action with the Qt World Summit 2017 app on GitHub:

GitHub - Qt World Summit 2017 app

Now it is up to you to add customized social features to your apps – the SocialView is definitely the right tool for it!

 

 

More Posts Like This

 

Release 2.14.1: Update to Qt 5.9.3 | Use Live Code Reloading on macOS and Linux
V-Play Update 2.12.1: Qt Quick Designer Improvements

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

How to Make a Qt app

The post How to Add In-App Chat or Gamification Features to Your Mobile App appeared first on V-Play Engine.

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

V-Play 2.14.0 introduced V-Play Live Code Reloading, which reduces your deployment time from minutes to seconds. V-Play 2.14.2 now adds support for using native cross-platform plugins with live code reloading.

2.14.2 also adds improvements to the SocialView components and adds improvements for Navigation components.

What is V-Play Live Code Reloading

V-Play Live reloads your project on every connected device, within seconds after code changes. This reduces the long compilation and deployment times, to only a couple of seconds. V-Play Live also allows you to run and test your applications on iOS from a Windows or Linux desktop. You don’t need to install any native SDKs for deployment with V-Play Live.

how-does-v-play-live-work-compared-with-standard-deployment

Watch this video for a quick demo of V-Play Live in action:

 

V-Play Live displays your app or game with the Live Client application. The desktop Live Client is part of your V-Play installation. For Android and iOS, you can download the Live Client apps in the app stores. For most projects those Live Client apps are sufficient. They have several V-Play Plugins and most of the Qt modules configured, so you can use them with V-Play Live.

Soon you will have the option to extend your own project with the live reloading feature, to build custom Live Clients. This allows you to use any custom C++ or native code together with live reloading for QML & JavaScript. This will also make it possible to use even more V-Play Plugins and features with V-Play Live.

How to Use V-Play Live

V-Play Live is super easy to use. We already covered that in our last blog post, you can read it here: How to use V-Play Live

What are V-Play Plugins

Do you want to add advertisements to your app or game? Do you want to add analytics to track and understand your audience? Do you need push notifications or other cloud services?

V-Play got you covered! With V-Play Plugins, you can add such native cross-platform plugins with just a few lines of code.

 

v-play-native-cross-platform-plugins

 

Beginning with V-Play 2.14.2, you can use many of those plugins also with V-Play Live. This helps you test a plugin without performing any extra setup steps. V-Play Live has several plugins configured already, so you can use them right away. For some plugins, this is not possible yet.

Use V-Play Plugins with V-Play Live

Here is a short video showing how to use V-Play Plugins with V-Play Live:

 

The following list shows which plugins you can already use with V-Play Live. There are no extra setup steps needed. For some services you will need to create an account at the service provider website. You can find the website links in the code examples below.

Access V-Play Plugins

To use V-Play Plugins in your QML code, add

import VPlayPlugins 1.0

at the top of your QML file.

Google AdMob

The AdMob plugin offers several ad formats to optimize your monetization. It features banner ads, interstitial ads and rewarded videos.

AdMobBanner {
  // this is a public test Id, you can create your own at www.google.com/ads/admob/
  adUnitId: "ca-app-pub-3940256099942544/6300978111"
}

You can test the code examples in this post like this:

import QtQuick 2.0
import VPlayApps 1.0
import VPlayPlugins 1.0

App {
  NavigationStack {
    Page {
      title: "AdMob"

      AdMobBanner {
        adUnitId: "ca-app-pub-3940256099942544/6300978111"
      }
    }
  }
}

Chartboost

Charboost is another advertisement service that offers interstitial ads. You can also use it to cross-promote your apps & games.

Chartboost {
  appId: "your App Id from www.chartboost.com"
  appSignature: "your App Signature from www.chartboost.com"
  shouldRequestInterstitialsInFirstSession: true
 
  onPluginLoaded: {
    cacheInterstitial()
  }
  onInterstitialCached: {
    chartboost.showInterstitial()
  }
  onInterstitialFailedToLoad: {
    console.debug("InterstitialFailedToLoad at location:", location, "error:", error)
  }
}

Google Analytics

Google Analytics offers in-depth analysis how users interact with your apps & games.

GoogleAnalytics {
  propertyId: "your Property Id from analytics.google.com"
  
  onPluginLoaded: {
    logEvent("V-Play Live","Test App Loaded","Test Events", 1)
  }
}

Flurry Analytics

Flurry is another popular analytics service that’s provided as V-Play Plugin. Here is a short example how to use it:

Flurry {
  id: flurry
  apiKey: "your Api Key from y.flurry.com"

  onPluginLoaded: {
    flurry.logEvent("App started");
  }
}

V-Play Game Network & Cloud Services

V-Play Game Network offers cross-platform leaderboards and achievements. You can also use an integrated cloud storage for your apps & games.

You can find more about the offered services here: V-Play Game Network & Cloud Services

V-Play Multiplayer & Social Services

V-Play Multiplayer enables you to create real-time and round-based multiplayer games. You can also use those features in your apps, and connect your users with the integrated chat system.

You can read more about the offered services here: V-Play Multiplayer & Social Services

Local Push Notifications

Schedule local notifications based on an upcoming point in time or a time interval.

This code examples schedules a notification 5 seconds after pressing the button. If you close the app, or move it to the background, the notification will be received as push notification.

NotificationManager {
  id: notificationManager
  onNotificationFired: {
    // Log output when the notification is fired. You can find the log output in the Live Server
    console.debug("Notification fired: " + notificationId)
  }
}

Notification {
  id: testNotification
  notificationId: "testNotification"
  message: "Hey there!"
  timeInterval: 5 // in seconds
}

AppButton {
  text: "Schedule Notification"
  onClicked: {
    // Cancel old notification if scheduled
    notificationManager.cancelNotification(testNotification.notificationId)
    // Schedule testNotification
    notificationManager.scheduleNotification(testNotification)
  }
}

More Plugins

You can find the full list of V-Play Plugins here: V-Play Plugins

The following plugins will have no or limited functionality with V-Play Live at the moment: In-App purchases, Facebook, Google Firebase, Game Center, Google Cloud Messaging, OneSignal, HockeyApp.

Of course, you can still use those plugins with standard local deployment, as used to. Nothing changes for your existing projects.

SocialView Improvements

This update brings many new features for the SocialView. For example, you can now search users and start new chats with the newMessagePage. It is even possible to create a custom user search with the SocialUserSearchPage base type.

business-meet-and-chat

For a guide how to best use the SocialView in your projects, please see How to Add In-App Chat or Gamification Features to Your Mobile App.

Navigation Fix

The update also brings a fix for triggering NavigationItem signals like onSelected.

Changelog

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

 

How to Update V-Play

Test out these new features by following these steps:

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

V-Play Update in Maintenance Tool

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

 

 

 

More Posts Like This

v-play-2-14-1-live-reloading-windows-mac-linux-ios-android-qt

Release 2.14.1: Update to Qt 5.9.3 | Use Live Code Reloading on macOS and Linux

v-play-live-reloading-windows-mac-linux-ios-android-qt

Release 2.14.0: Live Code Reloading for Desktop, iOS & Android

 

feature

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

The post Release 2.14.2: Live Code Reloading with Native Cross-Platform Plugins appeared first on V-Play Engine.

Jump-Start Your Development with the Qt Starter Pack

If you want to impress today’s customers, you have to keep up with the slick and smooth UIs they’re used to from their smartphones and tablets. Fortunately, the Qt software framework is no slouch and can fulfill the highest product requirements for embedded and desktop solutions.

Driving the Qt technology and its road map, we’re very proud of how comprehensive the Qt framework is. However, the sheer amount of the libraries can seem a bit daunting for Qt developers, some of which are still pondering how to use them to their full potential. To help you with this challenge right out of the gate and save you time and money, we have created a new globally available service: The Qt Starter Pack.

What is The Qt Starter Pack?

The Qt Starter Pack consists of an on-site workshop with a dedicated Qt engineering specialist with additional consulting after the workshop. Our expert developers teach you how to move things forward quickly at the start of the project, reaching your project milestones and go-to-market in record time.

Sounds great coming from us, but here is what some of our customers had to say:

The Qt Starter Pack

The Qt consultants gave us initial training which really helped us kick start our project & avoid typical software development pitfalls enabling us to get to market faster.” Kristof Braem, CEO, Medec Benelux

With the support of Qt consultants we were able to leverage on their knowledge and create one of the most advanced In-Vehicle Infotainment (IVI) systems and instrument clusters on the market – from scratch.” Goran Haček, IVI development coordinator, Rimac Automobili

It was quite amazing for us to see that we were able to cut down the development time from 1000 – 1300 hrs to 50 hrs by being able to allow all developers and customers to work on the same IDE.” Rune Volden, R&D Manager, Ulstein Power & Control

Sounds interesting, tell me more!

A dedicated Qt specialist takes you on a deep dive into product design and development and sets the solution development with Qt on the right path.

Of course, we tailor the workshop to your specific needs, but here are some general topics you can expect.

  • Use cases walk-through and feasibility studies
  • Hardware evaluation and optimization best practices
  • Evaluation of different options for high-level architecture design
  • Implementation practices
  • Memory footprint configuration and optimization
  • Identification of possible risks and bottlenecks with recommendations
  • Covering your specific topics and questions

With our experience in product development, we will help you avoid common pitfalls, manage performance and memory consumption and build a solid foundation for your project.

How can I get it?

We are happy to tell you more about the Qt Starter Pack and how we can help you to succeed. Contact us to discuss how we can boost your development to the next level.

The post Jump-Start Your Development with the Qt Starter Pack appeared first on Qt Blog.

SDDM v0.17.0

We are happy to release a new SDDM with a few improvements.

SDDM is a Qt based graphical login manager developed in a collaborative fashion by people from Liri, KDE and LXQt.

This new version include the following changes:

* Added possibility to change border width of ComboBox widget.
* Added missing utmp/wtmp/btmp handling.
* Make greeter see icons set by AccountsServices.
* Fix sddm.conf man page syntax error and update.
* Fix ComboBox widget.
* Fix connection of PropertiesChanged event for LogindSeat.
* Avoid race conditions with Xsetup.
* Update de translation.
* Update lt translation.
* Update zh_TW translation.
* Adjust order of components in the default PATH.
* Set default input method to qtvirtualkeyboard.


Download it here.

Increasing the number of lights in Qt 3D

While it is possible to draw scenes with almost unlimited numbers of lights using deferred rendering in Qt 3D, the default materials in Qt 3D Extras have been limited to eight lights because they are tied to forward rendering. Although we apply a few tricks that allow you to define more than eight lights in the scene, we only select the eight closest lights when rendering.

In the scene below, we have defined 100 lights that float around, but because only 8 of them are in use at the time and you can see how they pop in and out:

Although it’s possible to support more lights in other pipelines (this is for instance the case with the Qt 3D Studio Runtime), we also want the default materials in Qt 3D Extras to be able to use a larger number of lights, even when used with forward rendering.

The reason behind the current limit is that we need to support a range of OpenGL architectures, including some which are quite limited in terms of how much uniform data can be passed to the shader. We therefore need to pass a small array of light structs to the shader and loop over the lights in the fragment shader. Unfortunately, such loops are also very expensive on hardware with limited resources because they compile to a large number of shader program instructions. Sometimes so many that the resulting shader program won’t compile at all.

We have therefore started work on a solution that will both allow us to increase the number of lights on beefy hardware and at the same time reduce the number of shader program instructions on weaker hardware. It is based on Qt 3D’s new internal shader graph, which was recently introduced by Kevin Ottens from KDAB.

The shader graph is a game changer for Qt 3D. It allows us to build shaders dynamically with a structure similar to the material graphs you find in many modern 3D modeling applications. Each node in the graph can be thought of as a function – it is defined as a computation, takes a set of input values, and produces output values. For instance, a surface node can take the incoming and outgoing angles of light, the light color, and the surface color, and compute the resulting light contribution. By connecting nodes in the graph, you define the flow of computations in the shader program, which is translated to instructions in a programming language. Because all the computations are abstract, they can easily be translated to many different shader languages (or dialects), making it trivial to produce the same material definitions for different architectures.

In terms of increasing the number of lights, the great thing about the shader graph is that we can easily define a shader node for each of the lights in the scene. The graph then results in the right number of light calculations when converted to shader code. Instead of having a for loop inside the shader itself, we loop over the lights when the shader is generated. This is basically unrolling the old loop, which is way more efficient and allows us to have a much higher number of lights.

I am currently working on a prototype where we have moved the lighting system on top of the shader graph. While this work is still highly experimental, it is already producing some promising results. Here’s the same scene as above, but this time we are actually seeing 100 lights in use at the same time:

Before this becomes part of the default materials in Qt 3D Extras, we also want to change how lights are gathered in a scene and passed on to the shaders. Currently, the light gathering is tightly coupled with the rendering code, but we want to reduce the number of assumptions we make and give you more control over how light information is passed to your shaders. In turn, this will also make it easier to create applications that can switch between rendering modes, for instance if you want to support both forward and deferred rendering of the same scene

If this sounds interesting for your applications, feel free to share thoughts on how you would like to work with lights in your code.

The post Increasing the number of lights in Qt 3D appeared first on Qt Blog.

Qt 5.10 Rendering Benchmarks

Qt 5.10.0 RC packages are available now and actual release is happening pretty soon. So this seems to be a good time to run some rendering benchmarks with 5.10, including new QML Shape element, QQuickPaintedItem and QNanoPainter.

After my previous blog post, some initial comments mentioned how QML Shape didn't reach their performance expectations. But I think that might be more of a "use the right tool for the job" -kind of thing. This demo application is very much designed to test the limits of how much heavily animated graphics can be drawn while keeping performance high and while having its own strengths, QML Shape likely isn't the tool for that.

To prove this point, there is a new 'flower' test case in QNanoPainter demo app which renders a nice flower path, animating gradient color & rotation (but not path). Combining it with new setting to render multiple items (not just multiple renders per item) and the outcome looks like this with 1 and 16 items:


Now when we know what the desired outcome looks like let's start testing with the first run. 

Test1: Nexus 6, 'Render flower' test:


Test1 conclusions: In this test QQuickPaintedItem (QImage backend) has clearly worst performance, CPU Raster paint engine and uploading into GPU is very non-optimal on Nexus 6. QML Shape performs the best, maintaining fluid 60fps still with 16 individual items. QNanoPainter manages quite well also and switching for QSGRenderNode backend instead of QQuickFramebufferObject to avoid rendering going through FBO gives a nice boost. When the amount of items increases this FBO overhead naturally also increases. QQuickPaintedItem with FBO backend is somewhat slower than QNanoPainter.

This test is kind of best-case-scenario for QML Shape. If path would animate that would be costly for QML Shape backend. Also for example enabling antialiasing turns tables, making QML Shape only render 2 items at 35fps while QNanoPainter manages fluid antialiased 60fps. But that's the thing, select the proper tool for your use case.

Next we can test more complex rendering where also paths animate and see how antialiasing affects the performance. In rest of the tests, instead of increasing item count we increase rendering count, meaning how many times stuff is rendered into a single QQuickItem. The default tests set contains ruler, circles, bezier lines, bars, and icons+text tests. With 1, 2 and 16 rendering counts it looks like this:



So let's continue to Test2: Nexus 6, all default tests enabled:


Test2 conclusions: Slowest performer is again QQuickPaintedItem (QImage). QML Shape becomes right after it, dropping quite a bit from lead position of Test1. Digging QML Shape performance a bit deeper and enabling different tests individually one can see that Bezier lines test makes the biggest fps hit. And disabling some code there revealed that biggest slowdown came from graph dots which were drawn with two PathArc, so improved fps by switching implementation to use QML Rectangle instead. QNanoPainter is fastest but even it only reaches 60fps with non antialiased single rendering. Note that QNanoPainter with QSGRenderNode is missing here and in all rest of the tests because when rendering only single item performance of it is almost the same as QNanoPainter with FBO.

Then we could switch to a bit more powerful hardware and repeat above test with that. 

Test3: Macbook Pro (Mid 2015, AMD R9 M370X), all default tests enabled:


Test3 conclusions: Macbook can clearly handle much more rendering than Nexus 6. As MSAA is fully supported here we are able to test both antialiased and non-antialiased for every rendering method. On macbook MSAA antialiasing is quite cheap which can be seen from QML Shape and QQuickPaintedItem reaching pretty similar frame rates with and without antialiasing. Slowest performer is antialiased QQuickPaintedItem (QImage) while QNanoPainter leading again, reaching solid 60fps with 16 render counts.

As we saw already earlier that Bezier lines test seemed particularly unsuitable for QML Shape, let's next repeat the above test except disabling that single test. After all we try to be fair here and avoid misinterpretations. 

Test4: Macbook Pro, all default tests except Bezier lines enabled:


Test4 conclusions: Most interesting data here comes from comparison to Test3 results. QQuickPaintedItem (QImage) results go up only few percentages, so bezier line test doesn't seem to influence much there. QQuickPaintedItem (FBO) results are now identical for antialiased and non antialiased so light blue line can't be seen under orange one. But not much changes in there either. QNanoPainter improves 30-50% reaching solid 60fps now with 32 render counts when antialiasing is disabled. And finally, QML Shape improves frame rates by whopping ~100% so we were right in this particular test being its Achilles' heel.

We are just scratching surface here. There would be plenty of things to test still and get deeper into individual tests. But for this blog post let's stop here.

General tips about about Qt 5.10 QML Shape usage could be:
  • Use QML Shape for simple shape items as part of QML UIs. Consider other options for more complex shapes which animate also the path. 
  • Also don't use non-trivial Shape elements in places where creation time matters e.g. ListView delegates or making multiple shapes inside Repeater, as parsing the QML into renderable nodes tree has some overhead.
  • When the need is to render rectangles, straight lines or circles, QML Rectangle element gives generally better performance than QML Shape counterpart. You can experiment with this enabling alternative code paths for RulerComponent and LinesComponent of the demo. 
  • If you target mostly hardware with NVIDIA GPU, GL_NV_path_rendering backend of QML Shape should be more performant. I didn't have suitable NVIDIA hardware available currently for testing so these results will have to wait, anyone else want to provide comparisons?

Follow up post is planned for comparing Windows side OpenGL vs. OpenGL ES + Angle rendering performances so stay tuned!

Sharing Files on Android or iOS from your Qt App

by Ekkehard Gentz [Independent Software Architect, Consultant] (Qt Blog)

It‘s a common usecase to share Files or Content from native Android or iOS Apps with other Apps on your phone. So I thought this would be an easy task to add sharing to my mobile Apps built with QtQuickControls2.

Found the Blog from Eskil Abrahamsen Blomfeld about Intents with Qt for Android, part 1. Please read that Blog to learn about Android Intents, Qt Android Extras, JNI and HowTo use it from Qt. All of this was new to me – never did JNI before. Also I‘m not an experienced native developer for Android or iOS – that‘s the reason why I‘m using Qt for mobile App development.

I also found Share on iOS and Android using QML, where I learned HowTo share Text and a URL and HowTo structure a QtCreator project for Android and iOS with native code integration.

Unfortunately all of this didn‘t help me to share Files on Android or iOS from Qt mobile Apps.

For a DropBox-like project at customer site I needed sharing:

  • download Files from cloud
  • store Files in App sandbox data
  • view or edit Files in other Apps
  • print Files to local Printer

It took me some time and thanks to much help from other developers at Qt Forum and Slack (QtMob) I found ways to solve my use-cases.

The hardest part was the ugly JNI and Obj-C syntax 😉

Hopefully my experiences will make it easier for others to integrate Sharing-functionality into their Android or iOS Apps.

Here‘s my Example App at Github.

The Example App demonstrates:

  • Share Text and URL
  • View File
  • Edit File
  • Send File as Stream to …

To easy understand the complex structure please take a look at this Overview:

share_overview

UI: SwipeView with some Tabs. Each Tab contains a Page with some Buttons to test features.

01_tab_bar

Share Text and URL is the easiest one:

02_android_share_text_url

ShareUtils is registered as „shareUtils“:

void ApplicationUI::addContextProperty(QQmlContext *context)
{
    context->setContextProperty("shareUtils", mShareUtils);
}

Click on the Button to share Text and URL:

Button {
    text: qsTr("Share Text and Url")
    onClicked: {
        shareUtils.share("Qt","http://qt.io")
    }
}

Here‘s the share() method:

Q_INVOKABLE void share(const QString &text, const QUrl &url);
void ShareUtils::share(const QString &text, const QUrl &url)
{
    mPlatformShareUtils->share(text, url);
}

ShareUtils delegates this to PlatformShareUtils:

  • AndroidShareUtils on Android
  • IosShareUtils on iOS

The magic to detect the right class can be found in ShareUtils:

#if defined(Q_OS_IOS)
    mPlatformShareUtils = new IosShareUtils(this);
#elif defined(Q_OS_ANDROID)
    mPlatformShareUtils = new AndroidShareUtils(this);
#else
    mPlatformShareUtils = new PlatformShareUtils(this);
#endif

The Compiler knows the Platform you‘re running on and instantiates the matching platform specificClass.

Android:

void AndroidShareUtils::share(const QString &text, const QUrl &url)
{
    QAndroidJniObject jsText = QAndroidJniObject::fromString(text);
    QAndroidJniObject jsUrl = QAndroidJniObject::fromString(url.toString());
    jboolean ok = QAndroidJniObject::callStaticMethod("org/ekkescorner/utils/QShareUtils",
                                              "share",
                                              "(Ljava/lang/String;Ljava/lang/String;)Z",
                                              jsText.object(), jsUrl.object());
    if(!ok) {
        emit shareNoAppAvailable(0);
    }
}

QAndroidJniObjects are created for text and url and a Method from QShareUtils.java will be called:

    public static boolean share(String text, String url) {
        if (QtNative.activity() == null)
            return false;
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, text + " " + url);
        sendIntent.setType("text/plain");
        // Verify that the intent will resolve to an activity
        if (sendIntent.resolveActivity(QtNative.activity().getPackageManager()) != null) {
            QtNative.activity().startActivity(sendIntent);
            return true;
        } else {
            Log.d("ekkescorner share", "Intent not resolved");
        }
        return false;
    }

In our QShareUtils.java we create the Intent with ACTION_SEND and EXTRA_TEXT and start the Activity using QtNative.activity().

It‘s important to test if the Intent can be resolved – otherwise your App will crash.

Here‘s the iOS implementation:

void IosShareUtils::share(const QString &text, const QUrl &url) {
    NSMutableArray *sharingItems = [NSMutableArray new];
    if (!text.isEmpty()) {
        [sharingItems addObject:text.toNSString()];
    }
    if (url.isValid()) {
        [sharingItems addObject:url.toNSURL()];
    }
    // get the main window rootViewController
    UIViewController *qtUIViewController = [[UIApplication sharedApplication].keyWindow rootViewController];
    UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
    if ( [activityController respondsToSelector:@selector(popoverPresentationController)] ) { // iOS8
        activityController.popoverPresentationController.sourceView = qtUIViewController.view;
    }
    [qtUIViewController presentViewController:activityController animated:YES completion:nil];
}

In this case we‘re using UIActivityViewController to get the share options displayed.

Let‘s take a look HowTo view or edit Files. My Example App contains an Image and a PDF File in assets:

03_assets

At first start of the Example App we copy these files from Assets to (QstandardPaths::AppDataLocation)/my_share_files. This simulates that you have downloaded the Files from your Cloud or WebService.

See all the details in the sources.

Now we want to view or edit these Files in another App. I learned that it‘s not possible to share Files from your AppData Location (Sandbox) – you must copy the Files from APP Data to USER Data – per ex. Documents Location. I create a app specific working directory at DocumentsLocation.

Attention: I‘m not checking if Permissions are set – this isn‘t the goal of this App. To access Files at DocumentLocation you have to set WRITE_EXTERNAL_STORAGE.

<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />

Using Files from DocumentsLocation sounds easy but makes things more complicated. We don‘t want to leave those Files at DocumentsLocation when sharing the File finished. Then we must delete them. And if the User edited the File we must know if the File was changed and saved or canceled. If the File was modified we must replace the origin File inside our AppData before deleting the File from DocumentsLocation.

Also after sending the File as a Stream per ex. to a Printer we must delete the copied File as soon as printing was done.

The workflows are different for Android and iOS.

Android needs

  • FilePath URI
  • a specific Action: ACTION_VIEW, ACTION_EDIT, ACTION_SEND
  • MimeType

to find matching Apps.

iOS needs

  • FilePath as NSURL

On iOS there‘s no way to limit the Apps for View or Edit capabilities.

Android does an in-place-Editing of the File, where iOS copies the File over to the other App. To get the modified File back a second manual step is required by the user.

file_flow

The interesting question now is „HowTo know when sharing is finished and if Edit mode was canceled or saved“ ?

Android gives us the startActivityForResult() to get a Result Code back.

Unfortunately I didn‘t found a way to get this Result Code back from the Java Code in QShareUtils.java.

Using Java code on the other side is much easier to read and write as JNI code.

There‘s a workaround: as soon as the Intent Activity is started, our Qt App changes ApplicationState to Suspended and when the Intent Activity closes, the ApplicationState goes back to Active. You can watch the ApplicationState to know when sharing was finished and you also can compare modified Timestamp of the File to recognize changes from Edit mode.

This workflow is marked ‚A‘ in the Overview at the beginning of this article.

More coding, but much more flexible is to use JNI to construct the complete Intent Activity and to go with QAndroidActivityResultReceiver To get the Result back.

Here‘s the method to construct the Edit Intent:

    QAndroidJniObject jniPath = QAndroidJniObject::fromString("file://"+filePath);
    if(!jniPath.isValid()) {
        emit shareError(requestId, tr("Share: an Error occured\nFilePath not valid"));
        return;
    }
    // next step: convert filePath Java String into Java Uri
    QAndroidJniObject jniUri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", jniPath.object());
    if(!jniUri.isValid()) {
        emit shareError(requestId, tr("Share: an Error occured\nURI not valid"));
        return;
    }
    // THE INTENT ACTION
    // create a Java String for the ACTION
    QAndroidJniObject jniParam = QAndroidJniObject::getStaticObjectField("android/content/Intent", "ACTION_EDIT");
    if(!jniParam.isValid()) {
        emit shareError(requestId, tr("Share: an Error occured"));
        return;
    }
    // then create the Intent Object for this Action
    QAndroidJniObject jniIntent("android/content/Intent","(Ljava/lang/String;)V",jniParam.object());
    if(!jniIntent.isValid()) {
        emit shareError(requestId, tr("Share: an Error occured"));
        return;
    }
    // THE FILE TYPE
    if(mimeType.isEmpty()) {
        emit shareError(requestId, tr("Share: an Error occured\nMimeType is empty"));
        return;
    }
    // create a Java String for the File Type (Mime Type)
    QAndroidJniObject jniType = QAndroidJniObject::fromString(mimeType);
    if(!jniType.isValid()) {
        emit shareError(requestId, tr("Share: an Error occured\nMimeType not valid"));
        return;
    }
    // set Data (the URI) and Type (MimeType)
    QAndroidJniObject jniResult = jniIntent.callObjectMethod("setDataAndType", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", jniUri.object(), jniType.object());
    if(!jniResult.isValid()) {
        emit shareError(requestId, tr("Share: an Error occured"));
        return;
    }
    QAndroidJniObject activity = QtAndroid::androidActivity();
    QAndroidJniObject packageManager = activity.callObjectMethod("getPackageManager",
                                                                 "()Landroid/content/pm/PackageManager;");
    QAndroidJniObject componentName = jniIntent.callObjectMethod("resolveActivity",
                                                              "(Landroid/content/pm/PackageManager;)Landroid/content/ComponentName;",
                                                              packageManager.object());
    if (!componentName.isValid()) {
        emit shareNoAppAvailable(requestId);
        return;
    }
    // now all is ready to start the Activity:
    // we have the JNI Object, know the requestId
    // and want the Result back into 'this' handleActivityResult(...)
    QtAndroid::startActivity(jniIntent, requestId, this);

Thanks to QAndroidActivityResultReceiver we‘ll get the Result back into:

void AndroidShareUtils::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data)
{
    Q_UNUSED(data);
    // we're getting RESULT_OK only if edit is done
    if(resultCode == RESULT_OK) {
        emit shareEditDone(receiverRequestCode);
    } else if(resultCode == RESULT_CANCELED) {
        emit shareFinished(receiverRequestCode);
    } else {
        emit shareError(receiverRequestCode, tr("Share: an Error occured"));
    }
}

Now it‘s easy to connect to the SIGNAL (shareEditDone, shareFinished, shareError) from QML.This workflow is marked as ‚B‘ in the Overview above.

Please note: the JNI code is different for VIEW/EDIT and SEND – please take a look at all the details in the sources.

Was not so easy to figure out all the details but now it‘s really easy for you: just copy the code into your app 🙂

On iOS we‘re using a UIDocumentInteractionController:

    NSString* nsFilePath = filePath.toNSString();
    NSURL *nsFileUrl = [NSURL fileURLWithPath:nsFilePath];
    static DocViewController* docViewController = nil;
    if(docViewController!=nil)
    {
        [docViewController removeFromParentViewController];
        [docViewController release];
    }
    UIDocumentInteractionController* documentInteractionController = nil;
    documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:nsFileUrl];
    UIViewController* qtUIViewController = [[[[UIApplication sharedApplication]windows] firstObject]rootViewController];
    if(qtUIViewController!=nil)
    {
        docViewController = [[DocViewController alloc] init];
        docViewController.requestId = requestId;
        // we need this to be able to execute handleDocumentPreviewDone() method,
        // when preview was finished
        docViewController.mIosShareUtils = this;
        [qtUIViewController addChildViewController:docViewController];
        documentInteractionController.delegate = docViewController;
        [documentInteractionController presentPreviewAnimated:YES];
    }

Know when Preview is done from DocViewController:

-
(void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller
{
#pragma unused (controller)
    self.mIosShareUtils->handleDocumentPreviewDone(self.requestId);
    [self removeFromParentViewController];
}

We detect the end of preview and call documentPreviewDone() in IosShareUtils:

void IosShareUtils::handleDocumentPreviewDone(const int &requestId)
{
    emit shareFinished(requestId);
}

Now from QML we can connect to the SIGNAL and know when sharing was done.

The good thing: the workflow now is similar for Android and iOS and easier to handle from common QML code.

Please take a look at .pro – there are some Android and iOS specific sections. Also dont forget to add AndroidExtras.

Now it‘s time to download from Github, build and run the Sharing Example App.

Some Screenshots

Open in… Dialog on Android. Select the App you want to use for View or Edit mode:

04_android_share_chooser

Edit the Image and cancel or save:

05_android_share_edit_image

ACTION_SEND enables you to print Text, Images or PDF Files.

Choose the Printer Plugin:

06_android_share_send_chooser

Then select your Printer, configure the Printer and print:

07_android_share_print

On iOS the UIDocumentInteractionController gives you a preview of the File and provides the iOS Share Button at bottom left:

08_ios_preview

The Share Button presents the available Apps:

09_ios_share

Conclusion: you can share Files on Android and iOS and integrate into your specific workflows. SIGNALS are mitted to let you know what the User has done.

There‘s even a call to check if for a given MimeType and Action Type any matching Apps are available on Android.

Call this check before downloading a File from Cloud, to provide a better UX: instead of downloading and then telling users that there‘s no App available you can inform in advance.

One question is open for now: HowTo suppress the Preview on iOS and only show what you get from clicking on the Share Button. Thanks to any tips from Qt / Obj-C experts.

I‘ll continue work on this app and add some more Intent Actions for Android.Also will add functionality to open the App from outside by providing a File URI or MimeType.

Now have fun!

The post Sharing Files on Android or iOS from your Qt App appeared first on Qt Blog.

Release 2.14.1: Update to Qt 5.9.3 | Use Live Code Reloading on macOS and Linux

V-Play 2.14.1 adds Live Code Reloading Support for macOS & Linux Desktop. With this addition, Live Code Reloading now allows to run and reload your projects on iOS and Android from all desktop platforms. No native iOS and Android build tools required.

V-Play 2.14.1 also introduces the new SocialView component for adding social features like user profile, leaderboard or even a full-featured messenger to your apps and games. It offers a cleaner and more customizable interface, compared to the more game-oriented VPlayGameNetworkView and VPlayMultiplayerView.

This update also adds support for Qt 5.9.3.

Live Code Reloading for Windows, macOS and Linux

Building your project takes some time. For mobile platforms, it can even take several minutes, depending on your development PC. This can become quite time-consuming. For example, if you are doing small iterations to fine-tune UI elements in apps. Same with animations, game-mechanics and so on. It slows down your development speed and therefore decreases your productivity.

V-Play Live reloads your project on every connected device, within seconds after code changes. This reduces the long compilation and deployment times, to only a couple of seconds. V-Play Live also allows you to run and test your applications on iOS from a Windows or Linux desktop. You don’t need to install any native SDKs for deployment with V-Play Live. See here for a quick demo:

 

This video shows a project opened in Qt Creator (left) on Windows. The project runs with V-Play Live. In the bottom right corner, the screens from an Android Nexus 7 and an iPhone 5s are shared with screen mirror tools so you can see what is going on there. In the center, you can see the desktop client. After connecting the 2 devices to the Live Server (top right), we change the code in Qt creator. After we save the changes, all connected clients update their view, within a second!

Qt Charts with V-Play Live

After some of you requested it, this update also contains the powerful Qt Charts module with V-Play Live. Including charts in your app could not be easier.

V-Play Live Reload Benefits

Save Time: Deploy and Test in Seconds

V-Play Live reduces deployment time, from several minutes to a couple of seconds. It deploys your code changes to all connected devices, automatically after saving.

Let’s play a bit with numbers. If you have a really decent development PC, you might be able to deploy your application to Android within one minute. With V-Play Live, it will take 1-2 seconds.

1 - newTime/oldTime = 1 - 2/60 = 0.9667

You just saved 96.67% of time for deployment. If you deploy only 10 times per hour, you spent 20 seconds deploying, instead of 10 minutes. That is 2 extra coffee breaks per hour. Or more time to spend productive.

In this demo, you see all connected clients (Desktop, Android and iOS) update within a second after clicking save in the development environment:

v-play-live-code-change-reload-windows-android-ios

Feel free to do the calculation with numbers that are more realistic in your own case.

More V-Play Live Benefits

You can find more benefits in last week’s blog post.

How to Use V-Play Live

1. Get the Latest Version of V-Play

If you haven’t installed V-Play yet, go get it on our download page. If you already have V-Play installed, see the update instructions below.

2. Start V-Play Live

To start V-Play Live for your active project, click on the LIVE-Run button in Qt Creator:

v-play-live-run-button

The V-Play Live Server (below right) will start, and open a local V-Play Live Client (below left).

vplay-live-server-and-client-ui

The Live Server allows you to:

  • Manage your connected clients, both desktop and mobile.
  • See the log output of each connected client in a separate tab.
  • Detect code changes and reload all connected clients.
  • Select the qml file you would like to run. The default is the main entry point.

3. Connect Live Clients

If you do not want to connect any mobile device now, you are already set and can start development with your local Client. To connect a mobile device, download the V-Play Live App, for Android or iOS.

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

V-Play Live uses your local network to communicate between server and clients. Make sure that your device is connected to the same network as your development PC running the Live Server, for example the same Wi-Fi. The V-Play Live App will try connecting to the server once you run it on your mobile device. The Live Server then displays this dialog for the connection request:

vplay-live-client-connection-requesti

Accept the mobile device connection on the Server. Now all code changes are automatically sent to your connected mobile device(s).

Add Social Features to your Apps with the SocialView

Custom social features in your app boost retention and engagement rates. Many successful apps allow users to interact, compete or build social relationships. This is because social features are one of the key drivers to build up your user base.

The V-Play Game Network and V-Play Multiplayer & Messaging services include many ready-made social services. This makes it easy for you to create apps with e.g. user profiles, leaderboards or a messaging and friend system. This year’s conference management app for the Qt World Summit 2017 uses these services and allows to:

  • Search conference attendees to schedule Business Meetings.
  • Store custom user data like the company, job position or main Qt interest.
  • View user details and find conference attendees that match certain criteria.
  • Log in via Facebook to synchronize your data across devices.
  • Become friends and get in touch with the included messenger.
  • See a leaderboard with a ranking of users that work with the app, favor many talks and are active.

business-meet-and-chat

You can have a look and try out the features by downloading the app for iOS or Android:

App Store Google_Play_Badge-1

A cloud-based backend and easy-to-use client QML components allow to use these features. The VPlayGameNetworkView and VPlayMultiplayerView provide a default UI for your V-Play Apps. These types include several child views you can show or hide using view states. But there are several drawbacks to this approach. The new SocialView type completely changes the way you can use social services in your apps or games:

  • V-Play Apps Compatibility: The SocialView integrates with your App Navigation. You can show the available view pages anywhere in your app!
  • Easier Customization: Extend the view with QML elements to weave in your custom user data. Touching the QML source code of the view is not required.
  • Native Look and Feel: The default UI of the new view uses a native style and user experience on iOS and Android.
  • Clean Separation into App Pages: Each page instance works standalone and is a unique view. This also allows to introduce custom social pages to work with the V-Play social services.

mobile-chat

The Qt World Summit 2017 app shows how to use the SocialView and enriches it with custom features. The full updated source code is available for you on GitHub.

Dynamic App Navigation for Android and iOS

You don’t have to worry about how to show a drawer menu on Android, and a tab navigation on iOS. The V-Play App Navigation components take care of providing a native main menu.

But you also want change the general menu setup in some cases. For example to:

  • Only make certain features visible based on specific conditions.
  • Add more quick-links to your Android menu, as there’s more available space in the drawer than in the iOS tab bar.
  • Switch between different configurations of a certain menu item.

You can now set conditions for showing a menu item with NavigationItem::showItem. This allows to hide and show items in your main navigation without a hassle. For example, it is now easy to show different navigation entries for iOS and Android:

NavigationItem {
  title: "Only on iOS"
  icon: IconType.apple
  showItem: Theme.isIos

  // ...
}

 

Besides the highlights mentioned above, there are many other fixes and improvements for the SDK. For a full list of improvements and fixes to V-Play in this update, please check out our change log!

How to Update V-Play

Test out these new features by following these steps:

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

V-Play Update in Maintenance Tool

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

 

 

More Posts Like This

v-play-live-reloading-windows-mac-linux-ios-android-qt

Release 2.14.0: Live Code Reloading for Desktop, iOS & Android

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

How to Make a Qt app

The post Release 2.14.1: Update to Qt 5.9.3 | Use Live Code Reloading on macOS and Linux appeared first on V-Play Engine.

Qt 3D Studio 1.0 Released


We are happy to announce that Qt 3D Studio 1.0 has now been released. Qt 3D Studio provides a 3D user interface authoring system that caters for both software developers and graphic designers.

Qt 3D Studio Editor

Qt 3D Studio is the authoring tool for creating interactive 3D presentations and applications. Editor is a cross-platform Qt application which can be used in Windows, Mac and Linux. You can import design assets from popular authoring tools such as Photoshop, Autodesk Maya and The Foundry MODO.

qt3dstudioviewer

Qt 3D Studio Editor & Viewer with the remote connection feature

Qt 3D Studio Viewer

Qt 3D Studio Viewer is a great tool for testing the design in action. You can also use the remote connection feature built in to the Studio to connect to a device running the Viewer to see immediately the design changes in the device. We have published the Viewer application in the Google Play for easy start with Android devices.

Viewer can also generate image sequences  from Qt 3D Studio scenes which can then be animated or combined into a video. This is especially useful for example if you are using the same user interface also in devices which don’t have enough resources to run a full-blown 3D user interface. This allows you to use the same tools and workflow in both cases. This feature can be used to create videos you can easily share during the design process.

Installation & Platform support

Editor & Viewer are released for Windows & macOS. Linux is also supported, but pre-built binaries are not yet provided with the 1.0 release. So Linux users need to build from source. Please also refer to the build instructions if you are creating applications for Android or embedded targets. In addition to Windows, Mac, Linux and Android the Qt 3D Studio 1.0 supports embedded Linux as well as INTEGRITY and QNX real-time operating systems as deployment targets. In the future we will continue adding more platforms such as iOS. For detailed platform support please refer to documentation.

Easiest way to install the Qt 3D Studio is through the online installer where you can find it under Tools -section. If you don’t yet have the online installer you can get from our download page. If you are an existing commercial license holder you can find the relevant packages from Qt Account. Also offline installer packages are provided.

Please also remember that Qt 3D Studio relies on the development host and target device graphics adapter and drivers. During the development we have encountered some occasions where updating to latest drivers have fixed the issues user has been experiencing. If you encounter some issues, please post a report in our bug tracker.

How to get started – Documentation & Examples

As part of the installation packages we are providing sample projects and we have also added some demonstration applications to a separate git repository https://git.qt.io/public-demos/qt3dstudio. We will be adding examples and demo applications along the way so stay tuned. Documentation is available at http://doc.qt.io/qt3dstudio/index.html

Home Automation demo implemented with Qt 3D Studio and Qt Quick

Licensing

The Qt 3D Studio Editor is available for all Qt commercial licensees without any additional cost. Also the Qt 3D Studio Runtime can be used as part of desktop and mobile Qt applications without any additional cost. For open-source users Qt 3D Studio Editor and Runtime are available under GPLv3 license. For embedded devices, a separate distribution agreement is needed to cover the Qt 3D Studio Runtime (i.e. joint hardware and software distribution).

Way forward

We are planning on releasing bug fix releases as needed and the next feature release (1.1.0) will introduced around early February. Biggest change in next feature release is the new Data Node API which introduces a clearer separation between UI and application logic. Data Nodes works a “contract” between the UI designer and application developer and makes it easier to use the same data in several UI components. Also as mentioned already earlier we are working on a new Qt 3D Studio Runtime which is built on top of Qt 3D. The new Runtime will be released as part of Qt 3D Studio 2.0 release, planned for May 2018.

The post Qt 3D Studio 1.0 Released appeared first on Qt Blog.

Cutelyst 1.11.0 released!

Cutelyst the Qt Web framework got a new release, this is likely to be the last of the year and will be one of lasts releases of the 1.x.x series. I'd like to add HTTP/2 support before branching 1.x.x and having master as 2.0 but I'm not yet sure I'll do that yet.

For the next year I'd like to have Cutelyst 2 packaged on most distros soon due Ubuntu's LTS being released in April, and H2 might delay this or I delay it since it can be done using a front-end server like Nginx.

The 1.11.0 version includes three new plugins written by Matthias Fehring, a Memcached plugin that simplifies talking to a memcached server, a memcached based session store, that stores session information on the memcached server, and a static compressed plugin to serve compressed versions of static files.

Besides that I extended the EngineRequest class to serve as a base class for Engine's requests allowing to get rid of some ugly casts and void pointers that carry the real request/connection. This doesn't affect user code as long as they don't implement their own engine.

Setting a Json reply is now a bit simpler now that two overloads directly accepting QJsonObject and QJsonArray were added.

Cutelyst license preamble on files was fixed to state it's LGPLv2.1+, and finally pkg-config is now fully supported.

Go get/break/package/.* it!

https://github.com/cutelyst/cutelyst/archive/v1.11.0.tar.gz

Update to Linux perf report

Linux perf is an immensely useful and powerful tool suite for profiling of C/C++ applications.
I have used it extensively and successfully on various customer projects, both for desktop applications as well as automotive or industrial projects targeting low-end embedded Linux targets running on ARM hardware.

The biggest problem with perf really is its usability, or lack thereof. Over the years I have tried my best in educating people on how to use the tool suite, both in form of conference talks as well as during KDABs Linux profiling trainings and workshops and, most recently, by creating hotspot.

Additionally, I have started contributing upstream to the Linux kernel repository to alleviate some of the problems. A short time ago, one important patch series of mine got merged and will be part of Linux 4.15, which drastically improves Linux perf usability when dealing with common C++ workloads.

The patch series completely reworked the representation and handling of inlined frames in perf report.

Up until recently, inlined frames were not shown at all in the report. This made the interpretation of reports from C++ applications very hard, since the compiler will inline a lot of templates.

continue reading

The post Update to Linux perf report appeared first on KDAB.

Porting Applications to Qt

https://youtu.be/Y0TgaevFKx0?rel=0&showinfo=0

KDAB has unique experience in porting the code base for toolkits like Qt 3, Qt 4, Motif, Java, Tcl, GTK, .NET, MFC, and Photon to Qt 5. Porting legacy GUI toolkits to Qt 5 is a job where proven experience saves a lot of time.

In this presentation we highlight the main problems facing developers using legacy toolkits, what migrations are and which approaches to migrations are possible. We give you a short overview of common guidelines in starting migrations including common pitfalls and also discuss how KDAB can assist in porting your legacy code base to a modern Qt-based system using our tooling for automatic conversions.

View the slides.


For detailed information on migration, read our whitepaper: Modernizing Legacy Systems continue reading

The post Porting Applications to Qt appeared first on KDAB.

Get certified and prove your Qt expertise

Qt certification program has been alive since 2009, although we have not shouted out loud about it during the past few years. The exams have been updated to include Qt5 content, including Qt Quick and QML, so now it is possible to test your QML skills as well.

Why to get certified?

Join the group of 4,500 certified developers.

A certificate formalizes and proves you have practical Qt knowledge, when you are looking for new challenges. Yes, we mean practical knowledge. Although you do not have to write any C++ or QML code in the exams, there are plenty of code snippets, which you need to understand well to be able to answer to the exam questions.

With certified developers, companies can have a selling point when pitching their company’s credentials as an expert Qt shop.

Certificates and exams

Currently, we offer three kinds of certifications and corresponding certificates:

  • Certified Qt and QML Developer
  • Certified Qt C++ Specialist
  • Certified Qt Quick Specialist

certificate_sample

To become a certified developer, candidates must pass the Qt and QML Essentials exam. After additionally passing either of the specialist exams, candidates achieve the certified specialist status. We have developed the Widget UI and Application Engine exam for candidates, who want to test their widget and Qt C++ programming expertise. Candidates, preferring QML programming, can take the Qt Quick UI exam and become certified Qt Quick specialists.

Exams consist of multiple choice questions. In each exam, candidates have 60 minutes to reply the questions. The number of questions depends on the exam. The essential exam has 50 questions, from which 31 must be answered correctly. In the specialist exams, the passing score is 16, while the total number of questions is 30. A question example is given below:

Select all statements, which are true in terms of QString

  • QString extends QObject.
  • It is an implicitly shared value type.
  • QString stores the data in the compressed binary format, so it is more memory efficient than QByteArray.
  • QString stores a string as Unicode characters.

We do not expect you remember all the Qt classes and QML types by heart. However, you should know some essential classes, like QObject, QString, QWidget, QQuickItem very well. In addition, make sure to understand the essential Qt programming concepts, such as Qt object memory management, meta-object system, widget layout management or QML bindings and signal handlers. Familiarise yourself with exam requirements and curriculums in https://www.qt.io/qt-certification.

Are my old Qt certificates still valid?

We have good news to everyone, who already has old Nokia Qt certificates. We have decided to keep old certificates still valid. Thus, if you want to get Qt Quick Specialist certificate and you already are Nokia Certified Qt Developer, you can just take the new Qt Quick UI exam.

How to prepare and make an exam appointment?

One of the frequently asked questions is, which material I need to read to prepare for the exam. Look at our extensive offering of trainings, training materials, and tutorials in https://www.qt.io/qt-training. Use the exam curriculums to study the relevant topics. If you are totally new to Qt, one week may not be enough to prepare for the essentials exam. Writing Qt programs is very efficient way to learn. After 4-6 weeks of using Qt classes and QML types, you may find essentials exam almost trivial. If you unlucky and fail the exam, you can get 50 per cent discount to re-take the exam.

Certification exams can be taken in any of the 3,000 authorized Pearson VUE test centers. Visit http://www.pearsonvue.com/qtcompany and find the nearest test center to you. In addition, you can create a Pearson VUE account to manage exams and exam appointments. Exam prices vary a lot between the test centers. So, ask the test center to get the exact price. An average price is about 200 €.

We print and send certificates to exam candidates once in a month. So, in the best case you will get your certificate within a few days after the exam.

Show your Qt expertise and get certified today!

If you have any further queries about certification, please do not hesitate to send an email to certification@qt.io.

The post Get certified and prove your Qt expertise appeared first on Qt Blog.

Swift 4.0-rc3: Now available

A new release candidate for Swift 4.0 is now available for download.

Swift 4.0-rc3 can now be downloaded from our releases page and includes the Dutch and German translations updates made since 4.0-rc2.

With this release we provide a new binary package, an AppImage for 64-bit Linux systems. This works on CentOS, Ubuntu, Debian and most other Linux distributions. It’s a single file binary package, including Swift and all its dependencies. Simply download it and mark it executable (chmod +x) to run it.

We encourage everyone to download the new build and try it out, and give us feedback to help us further improve Swift as we move toward a final release candidate.

Webinars in December / January: Sign up now!

Hi everyone!

Here’s an overview of our free webinars for the upcoming weeks. They usually take place at 6pm CET, 1pm EDT and 10am PDT so you can participate live and ask our experts any questions you may have.

Don’t have the time to participate live? Sign up anyway – we will send you a recording and the presentation slides to your email address!

7 December: Pointer handlers for Fluid Applications in Qt Quick
Over the last few years, we have discussed adding a new way in QtQuick to handle events from pointing devices such as touchscreens, mice and graphics tablets. Now it is on track to ship in Qt 5.10.

14 December: An Interactive Digital Out-of-Home Software Developed by Using Qt Libraries

An Interactive Digital Out-of-home (DOOH) software has specific requirements like astonishing real-time visual effects, multiple cameras and touch devices support, remote monitoring and control, over the air deployment, statistics and the ability to easily create eye-catching apps. This webinar will explore the different features of the interactive DOOH software and underline the integration of the Qt libraries within the software.

9 January: Meet Qt 5.10 Asia and EU time zone 11 January: US and EU time zone

Overview of the new features in the latest release of the Qt framework and tools. Qt 5.10 is a quality upgrade spiced with several new features on top of the previous release,  Qt 5.9 LTS. New features in Qt 5.10 include a mechanism to use graphical assets in UI design created and maintained in a 3rd party tool, Vulkan support, improved gesture enablers, WebGL based remote applications, solutions for M2M communications, Qt Creator 4.5 and much more.

16 January: Introduction to 3D Studio EU and Asia time zones – 18 January: US and EU time zone

In this webinar, we will go through the Qt 3D Studio key features, show how you can create interactive 3D user interfaces with Qt 3D Studio and answer your questions live.

25  January: Functional Safety with Qt and Qt Safe Renderer

In this webinar, we talk about functional safety and how the Qt Safe Renderer can be used to create functionally safe systems.

Missed a webinar such as our Qt Graphics AMA session or the one on the controversial million-dollar-question “Qt or HTML5”? No problem! You can find recordings of all our webinars in the on-demand section! Download them and get smart!

The post Webinars in December / January: Sign up now! appeared first on Qt Blog.

QtVirtualKeyboard on Wayland

For the last couple of years my focus was on the Osmocom project to bring Free Software to the world of telecommunication. With a group of enthusiasts we have implemented the components necessary to run a complete network using Free Software. The Rhizomatica project is using the software to connecting people that were left behind. Our tools enabled high impact security research leading, leading to improvements to privacy and security for all of us….

But during the last months I had the opportunity to return to C++ and Qt work and it feels like coming home to the world of ARM powered hardware. When I left, the transition from consumer electronics (e.g. settop boxes) to automative (e.g. IVI) began and it seems it successfully completed! On Friday I explored a regression in OpenSSL and today I had the pleasure to understand input method handling of wayland a little bit better.

I wanted to see if I can use wayland and run QtVirtualKeyboard only in the Compositor. I couldn’t find answers in the documentation and started to read the code. Once I understood how it should work, I found a simple example in QtWayland. Isn’t Qt wonderful?

As I have gone down the rabbit hole let me try to share some of my reading. At the core is the unstable (API subject to change) text-input protocol. Upstream of wayland-protocols is still at v1 of the protocol but QtWayland includes a copy of v2 and has rather complete support for the compositor and client (thanks KDAB!).

Compositor/Server

To make it work the compositor needs to signal support for the “zwp_text_input_manager_v2” interface. In QML/Quick this needs to be done by adding the following inside the WaylandCompositor component:

...
TextInputManager {
}
...

This will instantiate a QWaylandTextInputManager and call ::initialize on it. Then auto-generated code will use wl_global_create to register the interface in the global registry. Clients will request a text_input and the manager will create one or use a QWaylandTextInput and then send events down to the client. E.g. if there is a soft keyboard set a breakpoint in QWaylandTextInput::sendKeyEvent in the compositor and see from where it is coming and how it will send the event to a client.

Client

Once the client starts the QWaylandIntegration will create a QWaylandDisplay and then query/initialize the registry. The answer will call QWaylandDisplay::registry_global for every registered interface. For the the zwp_text_input_manager_v2 interface the integration will initialize a QtWayland::zwp_text_input_manager_v2 and for each input device a QtWaylandClient::QWaylandTextInput (different namespace) will be created.

Communication

Now Compositor and Client will communicate through the wayland connection (no dbus). With Qt APIs the client will notice which element has been focused and will request the input method to be shown (QtWaylandClient::QWaylandInputContext::showInputPanel) and the Compositor  will forward this to the QInputMethod (see QWaylandTextInputPrivate::zwp_text_input_v2_show_input_panel)

Putting it together

In the end this is rather simple.. create a TextInputManager, use the InputPanel of the QtVirtualKeyboard and start your compositor with QT_IM_MODULE=qtvirtualkeyboard. Done!

 

Writing a Custom Qt 3D Aspect – part 1

Introduction

Qt 3D has a flexible and extensible architecture that allows us to easily add our own new functionality to it without disrupting the existing features.
The functionality of Qt 3D is divided among so-called aspects, each of which encapsulates a particular subject domain such as rendering, input, or animation.

This short series of articles will walk you through the process of adding a new aspect that provides component types and behaviour for a new domain not covered by Qt 3D out of the box. For this example we have chosen to implement an aspect that allows calculating running means of the frame rate. Of course this could legitimately be added to the renderer, but it's simple enough that it makes a nice example for our purposes today. The full source code for the example is available for download.

Overview

The application that we will build looks like this. It's a very simple Qt 3D scene and the window shows the current mean frame rate.

Custom Aspect Screenshot

There are a few parts that we need to consider when adding such new functionality (see the diagram):

  • Aspect — Responsible for orchestrating any jobs that need executing each frame and for managing the storage of any backend objects.
  • Components — Provided by your library/application are what an Entity will aggregate to give it new behaviour. The components are the main API you will need to create.
  • Nodes — Just as for components except that subclasses of QNode typically provide supporting data required by a component.
    For example QAnimationClipLoader is a node that provides animation key frame data to a QClipAnimator component.
  • Backend Nodes — The backend counterparts to any frontend components or nodes provided by your library/application. These are the objects typically processed by jobs running on the threadpool as dictated by the aspect itself.
  • Mapper — Custom mappers are registered with the aspect and are responsible for creating, fetching, and destroying backend nodes on demand. The mapper is used by QAbstractAspect and QAspectEngine to synchronise lifetimes of the frontend and backend objects.
  • Jobs — Created and scheduled by the aspect and which process the backend nodes. Jobs may also send events to the frontend nodes and components if properties change.
  • Change Arbiter — Responsible for delivering events between and among the frontend and backend objects. No need to do anything with this but be aware of its existence.

Adding the Aspect

Writing the initial aspect itself is really trivial. Just subclass QAbstractAspect and register it with the QAspectEngine:

[sourcecode lang="cpp" title="customaspect.h"]
class CustomAspect : public Qt3DCore::QAbstractAspect
{
Q_OBJECT
public:
explicit CustomAspect(QObject *parent = nullptr)
: Qt3DCore::QAbstractAspect(parent)
{}

protected:
QVector<Qt3DCore::QAspectJobPtr> jobsToExecute(qint64 time) override
{
qDebug() << Q_FUNC_INFO << "Frame time =" << time;
return {};
}
};
[/sourcecode]

[sourcecode lang="cpp" highlight="6" title="main.cpp"]
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
Qt3DExtras::Quick::Qt3DQuickWindow view;

view.engine()->aspectEngine()->registerAspect(new CustomAspect);

view.setSource(QUrl("qrc:/main.qml"));
view.show();
return app.exec();
}
[/sourcecode]

QAbstractAspect has a few more virtuals that you can override to do initialisation and cleanup should you need them. However, for this simple example all we need to do is to implement the jobsToExecute() virtual. Later we will use this to schedule a job to execute on the threadpool each frame, but for now we just output some debug text to return an empty vector (no jobs to run). Note that these virtual functions will only be called once you have registered the aspect with the QAspectEngine (see above) so that it is part of the simulation. We will return and complete the aspect a little later.

The FpsMonitor Component

We wish to add functionality to report on the mean frame rate averaged over a given number of frames. With this is mind we might come up with an API something like this:

[sourcecode lang="cpp" title="fpsmonitor.h"]
class FpsMonitor : public Qt3DCore::QComponent
{
Q_OBJECT
Q_PROPERTY(int rollingMeanFrameCount READ rollingMeanFrameCount WRITE setRollingMeanFrameCount NOTIFY rollingMeanFrameCountChanged)
Q_PROPERTY(float framesPerSecond READ framesPerSecond NOTIFY framesPerSecondChanged)

public:
explicit FpsMonitor(Qt3DCore::QNode *parent = nullptr);

float framesPerSecond() const;
int rollingMeanFrameCount() const;

public slots:
void setRollingMeanFrameCount(int rollingMeanFrameCount);

signals:
void framesPerSecondChanged(float framesPerSecond);
void rollingMeanFrameCountChanged(int rollingMeanFrameCount);

private:
float m_framesPerSecond;
int m_rollingMeanFrameCount;
};
[/sourcecode]

Note that we use a declarative, property-based API so that this class can easily be used from QML as well as from C++. The property rollingMeanFrameCount is a regular read-write property and the implementation of the setter and getter functions are completely standard. This property will be used to control the number of frames over which we calculate the moving average frame rate. The framesPerSecond property is a read-only property which will later be set from a job that we will write to process FpsMonitor components on the Qt 3D threadpool.

Creating a Small Test Application

Before we can utilise our custom component from QML, we must register the type with the QML type system. This is a simple one-liner that we can add to our main function:

[sourcecode lang="cpp" title="main.cpp"]
qmlRegisterType<FpsMonitor>("CustomModule", 1, 0, "FpsMonitor");
rootContext->setContextProperty("_window", &view);
[/sourcecode]

where we also took the opportunity to export the window to the QML context too (we'll need that in a moment).

Once that is done, we can import the CustomModule QML module and make use of the FpsMonitor component just as we would for any of the built in types.

[sourcecode lang="js" title="main.qml"]
Entity {
components: [
FpsMonitor {
rollingMeanFrameCount: 20
onFramesPerSecondChanged: {
var fpsString = parseFloat(Math.round(framesPerSecond * 100) / 100).toFixed(2);
_window.title = "CustomAspect: FPS = " + fpsString
+ " (" + rollingMeanFrameCount + " frame average)"
}
}
]
}
[/sourcecode]

Of course at this point, the FpsMonitor doesn't do much except for setting the value of the rollingMeanFrameCount property. Once we complete the backend, the above code will update the window title to show the current mean frame rate and the number of frames used to calculate it.

In the next part we will implement the corresponding backend node for FpsMonitor and make sure it gets created and destroyed on demand and set up communications between the frontend and backend.

continue reading

The post Writing a Custom Qt 3D Aspect – part 1 appeared first on KDAB.

Say hello to Qt Quick Pointer Handlers

We’ve known for several years that our multi-touch support in Qt Quick has been inadequate for many use cases.  We have PinchArea, to handle two-finger scaling, rotation and dragging; and MultiPointTouchArea, which can at least be used to show some sort of interactive feedback for the touchpoints, or maybe you could write a little state machine in JavaScript to recognize some kind of gesture.  As for the rest of Qt Quick though, the main problems are 1) support for mouse events came first; 2) Qt assumes there is only one mouse (the “core pointer”); 3) QMouseEvent and QTouchEvent (and a few more) have no suitable intermediate base class, so they end up being delivered independently; 4) that being hard, shortcuts were taken early on, to treat touch events as mouse events and deliver them the same way.  So the result is that you cannot interact with two MouseAreas or Flickables at the same time, for example.  This means you cannot press two Buttons at the same time, or drag two Sliders at the same time, if they are implemented with MouseArea.

At first I hoped to fix that by making MouseArea and Flickable both handle touch events separately.  The patches to do that were quite complex, adding a lot of duplicated logic for the full parallel delivery path: a QMouseEvent would take one path and a QTouchEvent would take another, in the hope that the interaction would work as much the same as possible.  It was months of work, and at the end it mostly worked… but it was hard to keep all the existing autotests passing, and colleagues worried about it being a behavior change.  MouseArea proclaims by its name that it handles mouse events, so as soon as it begins to handle touch events separately, it becomes a misnomer.  Suddenly you would be able to press two Buttons or Tabs or Radio Buttons at the same time, in applications and sets of controls which weren’t designed for it.  (So we tried adding a bool property to opt in, but needing to set that in every MouseArea would be ugly.)  MouseArea and Flickable also need to cooperate a lot, so the changes would have to be done together to keep everything working.  It was possible, but narrowly missed shipping in Qt 5.5 due to uncertainty.

So eventually we took a different route, after we found a reasonable combination of ideas that had been proposed.

One idea was that since we cannot refactor the QEvent hierarchy (yet) due to the binary compatibility mandate, we could instead create wrapper classes which make the events look like we want them to, complete with properties for the benefit of QML, and deliver those instead, using a mostly-unified event delivery path in QQuickWindow and QQuickItem.

Another idea was the realization that dynamically creating and destroying these wrapper events is silly: instead we use a pool of instances, as we have been doing in other cases where an “event” object is emitted by a signal (for example the object emitted by MouseArea.positionChanged is always the same instance, since Qt 5.8).  With that optimization, wrapping one event with another is no longer a big performance hit.

Another idea was suggested: maybe it would be nice if handling an event from a pointing device were as easy as using the Keys attached property: for example, Mouse.onClicked: { ... } or PointingDevice.onTapped: { ... } But soon after came the realization that there can be only one instance of an attached property per Item to which it is attached.  One of the problems with MouseArea is that it tries to do too much, so it didn’t make sense to simply re-implement all the functionality in a monolithic MouseAttached.  We wanted the ability to handle a click or a tap without caring which device it comes from, for example, because that’s what every Button control needs to do.  It’s the same with any gesture that can be performed with either the mouse or a single finger.  Perhaps there could be one attached property per gesture rather than one per device type, then?

Since QML is a declarative language, it’s nice to be able to declare constraints rather than writing if/else statements in JavaScript signal callbacks.  If an object which handles events is designed not to care which device a gesture comes from, there will nevertheless be cases when your application does care: you want to perform a different action depending on whether it is tapped on the touchscreen or clicked with the right mouse button, or you want to do something different if the control key is held down while dragging an object.  By allowing multiple instances of these handler objects, we can declare the constraints on them by setting properties.  It should be OK to have as many instances as you like.  Each instance should be lightweight so that you don’t fear to have too many instances.  The implementation should be in C++, and it should be simple and understandable.  Each handler should do one, or at most a few very closely-related things, and do them well.

Those concerns have taken us away from the idea of using attached properties, for now.  What we have instead is a new family of classes in Qt Quick: Pointer Handlers.

A Pointer Handler is a type of object which you can declare inside any Item, which handles events from pointing devices on behalf of that Item.  You can declare as many of them as you need: typically, one per interaction scenario.  All the common constraints that we could think of are declarable: you can make the handler react only if it’s a touch event, only to certain mouse buttons, only if the correct number of fingers are pressed within the bounds of the Item, only if a particular modifier key is held, etc.

Draggin’ balls

Common gestures are represented by their own handler types.  For example, if you declare

Rectangle {
    width: 50; height: 50; color: "green"
    DragHandler { }
}

then you have a Rectangle which can be dragged around the scene via either mouse or touch, without writing any Javascript, and without even needing to bind the handler to its parent in any way.  It has a target property, and the default is the same as its parent.  (But by setting the target to a different Item, you can capture events within one item, but manipulate the other.)

Of course, if you have two of those green rectangles with DragHandlers in them, you can drag them both at the same time with different fingers.

Every Pointer Handler is a QObject, but it’s not a QQuickItem, and it doesn’t have too many of its own variables, so each instance is about as small as a practical QObject subclass can be.

Every single-point handler has the point property, to expose all the details about the touchpoint or mouse point that we can find. There are properties for pressure and ellipseDiameters: some devices may have force sensors, while others may measure the size of the contact patch (but many devices don’t provide either). It has a velocity property which is guaranteed to be defined: we calculate and average the velocity over the last few movements for a slightly smoother reaction. Having the velocity available could potentially enable velocity-sensitive gestures: perhaps a flick should be done at a certain minimum speed. (Is that the right way to distinguish a flick from a drag? It hasn’t been easy to make that distinction before.) Or, if you have the velocity at the time of release, a drag gesture can end with momentum: the object keeps moving a short distance in the same direction. This makes your UI feel more alive. So far we have not formalized MomentumAnimation into a supported animation type, but there is a pure-QML prototype of it in tests/manual/pointer/content/MomentumAnimation.qml.

two red balls being dragged simultaneously with DragHandler

Tap dancing

TapHandler handles all the press-and-release gestures: single quick taps or clicks, double-taps, some other number of taps, holding it pressed for a configurable period of time, or holding it for various periods of time, all in unique ways. (When you touch a touchscreen, it often doesn’t make any sound, but you can tap a mouse button; so we thought “tap” is a more future-proof name for this gesture than “click”.)  You can show feedback proportional to how long it has been held (an expanding circle, progress bar or something like that).

TapHandler detecting a triple-tap and then a long press

Pinch me if this is for real

There is a PinchHandler.  If you declare it inside an Item, you will be able to scale, rotate and drag that Item using the pinch gesture.  You can zoom into any part of the Item that you like (an improvement on PinchArea).  It can handle larger numbers of fingers, too: you can declare PinchHandler { minimumTouchPoints: 3 } to require a 3-finger pinch gesture.  All the transformations then occur relative to the center point between the three fingers, and the scaling is relative to the average increase or decrease in spread between them.  The idea came from the way that some versions of Ubuntu use the 3-finger pinch for window management: apparently they thought the content in the window may have some use for a 2-finger gesture, but most applications don’t use 3 fingers for anything, so it’s OK to reserve the 3-finger pinch to scale and move windows around the desktop.  Now since you can write a Wayland compositor in QML, you can easily recreate this experience.

zooming into a map with PinchHandler

Getting to the points

Finally, there is PointHandler.  Unlike the others, it doesn’t manipulate its target Item: it exists only to expose the point property.  It’s similar to an individual TouchPoint in MultiPointTouchArea, and can be used for the same purpose: to provide interactive feedback as touchpoints and the mouse cursor move around the scene.  Unlike MultiPointTouchArea, it does not exclusively grab the touchpoints or the mouse, so having this interactive feedback does not prevent interacting with other handlers in other Items at the same time.  In the animations on this page, it’s used to get the finger sprites to follow my fingers around.

Are we there yet?

So now I’ll get to the reasons why this stuff is in Tech Preview in 5.10.  One reason is that it’s incomplete: we are still missing support for mouse hovering, the mouse wheel, and tablet stylus devices (a stylus is still treated as a mouse for now).  None of the handlers have velocity-sensitive behavior.  We can imagine a few more Handlers that could be written.  There should be public C++ API so that you can create your own, too.  Handlers and Flickable are getting along somewhat, but Flickable is a complex monolithic Item, and we think maybe it can be refactored later on.  There is a FakeFlickable manual test which shows how it’s possible to re-create a lot of its functionality in QML with two ordinary Items, plus a DragHandler and a few animations.

FakeFlickable: a componentized Flickable

Another reason is the naming.  “Pointer Handlers” sounds OK in isolation, but there is pre-existing terminology which makes it confusing: a pointer might be a variable which points to a memory location (but that’s not what we mean here), and a handler might be a sort of callback function that you write in JavaScript.  If you write TapHandler { onActiveChanged: ... } do you then say that your handler has a handler?  We could start using the word “callback” instead, but it’s an anachronism in some circles, and in QML our habits are hard to change now.

Another reason is that QtLocation has some complex use cases which we want to use as a case study, to prove that it’s possible to navigate a map (and any interactive content upon it) with small amounts of readable code.

Perhaps I’ll continue this later with another post about another way of doing gesture recognition, and how that might affect how we think about Pointer Handlers in the future.  I haven’t explained the passive grab concept yet.  There’s also more to be defined about how to build components which internally use Pointer Handlers, but give the application author freedom to override behavior when necessary.

So to wrap up for now, Pointer Handlers are in Tech Preview in 5.10.  We hope you will play with them a lot.  Especially if you have some old frustrations about interaction scenarios that weren’t possible before.  Even more so if you ever wanted to create a touch-intensive UI (maybe even multi-user?) without writing a C++ event-forwarding and QObject-event-filtering mess.  We need to start getting feedback from everyone with unique use cases while we still have the freedom to make big changes if necessary to make it easy for you.

So far the usage examples are mostly in tests/manual/pointer. Manual test source code isn’t included in release build packages, so to try those out, you’ll need to download Qt source packages, or get them from the git repo. Some of those can be turned into examples for upcoming releases.

Since it’s in tech preview, the implementation will continue to be refined during the 5.10 series, so follow along on the 5.10 git branch to keep up with the latest features and bug fixes.

There’s an upcoming webinar in a couple of weeks.

The post Say hello to Qt Quick Pointer Handlers appeared first on Qt Blog.

Are you ready for Qt Quick Controls 2.3?

This blog post takes a brief look at some of the new features in Qt Quick Controls 2.3 released as part of Qt 5.10. See also New Features in Qt 5.10 for a more detailed list.

New styles

We are introducing two new styles: Fusion and Imagine. The Fusion style looks familiar to those who have been using Qt Widgets. This is a QML-based implementation of the same design.

The Fusion style

The Fusion style

The Imagine style is based on configurable image assets, giving designers full control over how the style looks like. The style comes with a default set of image assets that have been exported from Sketch.

The Imagine style

The Imagine style

With the Imagine style it is possible to style the controls without a single line of code. There will be also examples for Illustrator and Photoshop. These designs are provided as starting points for those creating their own designs. See Qt Quick Controls 2: Imagine Style from Mitch for more details.

Menus and actions

Menus and friends have taken big steps forward. We have added new QML types called MenuBar, Action and ActionGroup, and Menu has gained support for sub-menus. It is now possible nest menus, as expected on desktop platforms. We also added support for mnemonics in menus and buttons.

MenuBar and cascading Menus

MenuBar and cascading Menus

The usage is identical to the earlier generation of Qt Quick Controls:

import QtQuick 2.10
import QtQuick.Controls 2.3

ApplicationWindow {
    id: window
    width: 500
    height: 400
    visible: true

    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            Action { text: qsTr("&New...") }
            Action { text: qsTr("&Open...") }
            Action { text: qsTr("&Save") }
            Action { text: qsTr("Save &As...") }
            MenuSeparator { }
            Action { text: qsTr("&Quit") }
        }
        Menu {
            title: qsTr("&Edit")
            Action { text: qsTr("Cu&t") }
            Action { text: qsTr("&Copy") }
            Action { text: qsTr("&Paste") }
            MenuSeparator { }
            Menu {
                title: qsTr("&Find/Replace")
                Action { text: qsTr("Find &Next") }
                Action { text: qsTr("Find &Previous") }
                Action { text: qsTr("&Replace...") }
            }
        }
        Menu {
            title: qsTr("&Help")
            Action { text: qsTr("&About") }
        }
    }
}

These are important steps bringing Qt Quick Controls 2 menus functionality-wise on par with native platform menus. This makes it feasible to start considering the next steps integrating native platform menus as a backend for Qt Quick Controls 2 menus.

Palettes

We have added support for configurable palettes, currently supported by the Default, Fusion, and Imagine styles. The other styles are coming later. Here’s a screenshot of the Default style with a custom dark palette:

The Default style with a custom dark palette

The Default style with a custom dark palette

Q & A:

What about TableView?
– We have made great progress with a new TableView based on the same Qt Quick item view framework ListView and GridView are based on. The current implementation is already able to manage a two-dimensional set of visible items for the current viewport. The performance is on the same level with ListView and GridView. Large amount of columns does not kill the performance like in the ListView-based TableView in Qt Quick Controls 1. Stay tuned for a blog post on the subject.

When is the famous “Object destroyed during incubation” problem going to be fixed?
– We believe we have now the necessary ingredients for finally tackling this issue. I have prepared a patch to the QML engine that allows us to defer the execution of the built-in delegates so that a) replacing them with custom delegates at construction time won’t cause troubles for asynchronous incubation and b) the performance (in terms of construction time) of a customized control is not affected by the built-in delegates. As soon as the necessary patch to the QML engine has landed, we can start making use of it in Qt Quick Controls 2. We are targeting the 5.9.x LTS series. I’ll report status updates to QTBUG-50992.

The post Are you ready for Qt Quick Controls 2.3? appeared first on Qt Blog.

Qt Quick Controls 2: Imagine Style

Back in April we wrote about image-based styling for Qt Quick Controls 2. Since then, we have made good progress and nailed down some aspects that were still under consideration. We call the new style “Imagine”.

The style works by scanning a directory of images and applying those images to the controls. For example, when a Button is created, the style will look for button-background.9.png (or button-background.png for non-resizable buttons). As an example of what that image could look like, here’s button-background.9.png from the default assets:

Imagine Style Button background image.

When the user presses the button, the style then looks for button-background-pressed.9.png (or button-background-pressed.png). In the case of the default assets, that would look like this:

Imagine Style pressed Button background image.

The .9.png extension represents 9-Patch images. Using this format, we’re able to encode information about how the control should look when it is resized into the image itself. Combine this with the pre-defined file naming convention and you’ve got a style that can be customized without ever touching QML, giving designers complete control over what they do best, and allowing developers to focus on writing applications, not styles.

To provide a starting point for creating your own style, we’ve created a complete asset template in Sketch:

Default Imagine style Sketch template

Default Imagine style Sketch template (Sketch)

For those who prefer Illustrator or Photoshop, we’ve provided smaller templates, each with their own example that uses the assets:

Qt Quick Controls 2 - Imagine Style Example: Automotive

Qt Quick Controls 2 – Imagine Style Example: Automotive (AI)

Qt Quick Controls 2 - Imagine Style Example: Music Player

Qt Quick Controls 2 – Imagine Style Example: Music Player (PSD)

The Imagine style is available with Qt 5.10. For more information, see the documentation.

The post Qt Quick Controls 2: Imagine Style appeared first on Qt Blog.

Release 2.14.0: Live Code Reloading for Desktop, iOS & Android

V-Play 2.14.0 adds Live Code Reloading for Desktop, iOS & Android. It allows you to run and reload apps & games within a second on iOS and Android from Windows and Linux. No Mac and Android SDKs required. It also updates the way we distribute Android & iOS updates. If you have V-Play for iOS or Android installed, make sure to follow the steps described here.

Live Code Reloading

Building your project takes some time. For mobile platforms it can even take several minutes, depending on your development PC. This can become quite time-consuming. For example if you are doing small iterations to fine-tune UI elements in apps. Same with animations, game-mechanics and so on. It slows down your development speed and therefore decreases your productivity.

V-Play Live reloads your project on every connected device, within seconds after code changes. This reduces the long compilation and deployment times, to only a couple of seconds. V-Play Live also allows you to run and test your applications on iOS from a Windows or Linux desktop. You don’t need to install any native SDKs for deployment with V-Play Live. See here for a quick demo:

This video shows a project opened in Qt Creator (left) on Windows. The project runs with V-Play Live. In the bottom right corner, the screens from an Android Nexus 7 and an iPhone 5s are shared with screen mirror tools so you can see what is going on there. In the center, you can see the desktop client. After connecting the 2 devices to the Live Server (top right), we change the code in Qt creator. After we save the changes, all connected clients update their view, within a second!

How to Use V-Play Live

1. Get the Latest Version of V-Play

If you haven’t installed V-Play yet, go get it on our download page. V-Play Live is available starting with this V-Play version, 2.14.0. If you are running an older V-Play version, see the update instructions below.

Note: This feature is available on Windows only at the moment. Linux and macOS developers will receive an update including V-Play Live next week.

2. Start V-Play Live

To start V-Play Live for your active project, click on the LIVE-Run button in Qt Creator:

v-play-live-run-button

The V-Play Live Server (below right) will start, and open a local V-Play Live Client (below left).

vplay-live-server-and-client-ui

The Live Server allows you to:

  • Manage your connected clients, both desktop and mobile.
  • See the log output of each connected client in a separate tab.
  • Detect code changes and reload all connected clients.
  • Select the qml file you would like to run. The default is the main entry point.

3. Connect Live Clients

If you do not want to connect any mobile device now, you are already set and can start development with your local Client. To connect a mobile device, download the V-Play Live App, for Android or iOS.

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

 

V-Play Live uses your local network to communicate between Server and Clients. Make sure that your device is connected to the same network as your development PC running the Live Server, for example the same WiFi. Once you run the V-Play Live App on your mobile device, it will connect to the Server. You will see this dialog in the Live Server:

vplay-live-client-connection-requesti

Accept the mobile device connection on the Server. Now all code changes are automatically sent to your connected mobile device(s).

 

V-Play Live Reload Benefits

Save Time: Deploy and Test in Seconds

V-Play Live reduces deployment time, from several minutes to a couple of seconds. It deploys your code changes to all connected devices, automatically after saving.

Let’s play a bit with numbers. If you have a really decent development PC, you might be able to deploy your application to Android within one minute. With V-Play Live, it will take 1-2 seconds.

1 - newTime/oldTime = 1 - 2/60 = 0.9667

You just saved 96.67% of time for deployment. If you deploy only 10 times per hour, you spent 20 seconds deploying, instead of 10 minutes. That is 2 extra coffee breaks per hour. Or more time to spend productive.

In this demo you see all connected clients (Desktop, Android and iOS) update within a second after clicking save in the development environment:

v-play-live-code-change-reload-windows-android-ios

Feel free to do the calculation with numbers that are more realistic in your own case.

Test on All Your Devices at Once

You can connect as many devices as you want, and every single one is updated simultaneously. We didn’t even include this in the calculation above.

Easy Setup

Setting up V-Play Live is as easy as it gets. In fact, there is nothing to set up. To connect your mobile devices, just download and install the V-Play Live App for Android or iOS.

iOS Deployment from Windows & Linux

With V-Play Live, you can test your V-Play projects on your iPhone and iPad, even from Windows or Linux. No more need to ask your office neighbor with that shiny Mac, to test you application on iOS.

No Native SDKs Required

You don’t need to install native mobile SDK for Android or iOS for developing and testing.

Debug Log Output on Mobile Devices

The Live Server displays debug log output from any connected client, including the mobile clients for iOS and Android. You can debug issues on different platforms even easier now.

Test V-Play Plugins Easily

plugins

Test V-Play Plugins like Admob Ads, Facebook Login, Google Analytics, Firebase or push notifications. With V-Play Live you can skip the individual setup steps.

Qt Quick / QML Applications

V-Play Live can also be used for Qt Quick applications and files without V-Play.

Your Source Code is Safe

V-Play Live works simple and safe, using your private local network. The Live Server is running locally on your development PC. You can connect your mobile devices using the Live Client app, available for Android and iOS. Your project files are transferred directly from your server to the clients, without ever leaving the local network.

 

Important Update Notes for existing Android & iOS Projects

With this update, developers for Android & iOS have a new “V-Play Kit” available. The benefit of this new solution is, that updating to future V-Play versions that use a different Qt version internally gets a lot easier, because the Qt version is now automatically updated for you.

Follow these steps on macOS and Linux because otherwise you will not be able to use the new features of this update and your existing projects will not compile without this change. This is a one-time step required to make updating V-Play versions easier in the future:

  1. Open the MaintenanceTool and select the Add or remove components option:
    windows-installer-v-play-add-components
  2. Add the V-Play packages for Android and iOS:
    v-play-2.14.0-initial-state-qt-5.9.2-selected
  3. Unselect the Qt 5.9.2 package like shown below:
    v-play-2.14.0-updated-state-qt-5.9.2-unselected
  4. In Qt Creator, now choose the new kit for Android and iOS based on V-Play packages:
    v-play-2.14.0-updated-state-qt-creator-kit

 

Support for Xcode 9

With update 2.14.0, we updated all our wizards and examples to be compatible with iOS apps submitted to the App Store with Xcode 9. If you still use a previous version of Xcode, you can optionally perform these steps or do them as soon as you’re switching to Xcode 9.

Apps submitted with Xcode 9 need an Asset catalog. You can copy the Asset catalog we provide and modify it to your needs:

xcode9-asset-migration-steps

To migrate your existing project to the new format, perform steps described in this guide.

Besides the highlights mentioned above, there are many other fixes and improvements for the SDK. For a full list of improvements and fixes to V-Play in this update, please check out our change log!

 

 

More Posts Like This

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

How to Make a Qt app

The post Release 2.14.0: Live Code Reloading for Desktop, iOS & Android appeared first on V-Play Engine.

Qt Creator 4.5 RC released

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

We think that we are pretty close to what we want to release as Qt Creator 4.5.0, so please take this opportunity to give us final feedback through the bug tracker, our mailing list, or on IRC (#qt-creator on chat.freenode.net). For information about the new features and improvements in this version, please have a look at the beta blog post or our change log.

Get Qt Creator 4.5 RC

The opensource version is available on the Qt download page, and you find commercially licensed packages on the Qt Account Portal. Qt Creator 4.5 RC is also available under Preview > Qt Creator 4.5.0-rc1 in the online installer (as an update to the beta). Please post issues in our bug tracker. You can also find us on IRC on #qt-creator on chat.freenode.net, and on the Qt Creator mailing list.

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