// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \example applicationmanager/launch-intents \brief Learn how to use Intents to start applications from the System UI. \ingroup applicationmanager-examples \title Launch Applications Using Intents System UI Example \image launch-intents-example.png The Launch Intents example with two applications running. \examplecategory {Embedded} \note Please \l{wayland-dev-packages}{read this} if you want to build the example on a Linux machine. \section1 Introduction This example shows you how to use intents as a basis for a launcher in a System UI. \b Prerequisites: You're already familiar with the concepts and topics introduced in the \l {System UI Example: "Hello World!"}. This example uses the same folder structure and can be started in the same way. Unlike the \l{System UI Example: "Hello World!"}{Hello World} example, we are not using the ApplicationObject abstraction layer directly to launch appliations, but instead we are using \c launch intents registered by the packages. This way we can have multiple icons in a launcher that can start the same application, triggering different functionality within the application. \note \e Any intent directed at an application would launch it, if it was not already running. For the purpose of this example we are calling our intents \c launch, but the application manager does not attach a special meaning to this name. All the intents' icons and names that are in the \c launcher category are on the left. You can click on their icons to send the respective intent request to the system: if the corresponding application is not yet running, it will be started automatically. Doing a press-and-hold on the icon will stop the application via the ApplicationObject. Just like in the "Hello World!" example, the column layout on the right shows the windows of all running applications. The applications display their application name against a background of that color. In addition they also show how many times they have received an intent of the \c launch category. \section1 Implement the System UI Like any simple QML application, our example's code starts with some imports and a plain Item at the root. The only difference is that our System UI also imports the \c QtApplicationManager and \c QtApplicationManager.SystemUI modules, besides \c QtQuick. \quotefromfile applicationmanager/launch-intents/system-ui.qml \skipto import QtQuick \printuntil height: Unlike in the "Hello World!" example, we now create an IntentModel to get access to all intents that are in the \c launcher category. Since this model is unsorted by default, we also set the sorting order to descending based on the name of the intent. \note The name of the category could be anything you like it to be - as long as it is consistent between here and the applications' \c info.yaml metadata and the corresponding IntentHandler within the application. \printto Show intent names Next, we have a Column on the left side of the root Item where we place the icons of the available intents along with their names. \printto Show windows We use our IntentModel, which provides a row for each intent available. In each row, we have: \list \li an \c icon role with the icon URL \li a \c name role with the localized intent's name \li an \c intentId role that contains the id of the intent \li an \c applicationId role that contains the id of the handling application \endlist For information on the other roles available, see \l{IntentServer}{IntentServer QML Type}. Next, we place a \c Column anchored to the right side of the root \c Item. This item is exactly the same as in the "Hello World!" example, showing all the application windows. \section1 Implement the Application Our Launch Intents applications display their application name as text against a colored background. \quotefromfile applicationmanager/launch-intents/apps/launch-intents.blue/main.qml \skipto import QtQuick \printuntil /^\}/ The only difference between this example and the one from the "Hello World" example is that we are additionally handling incoming \c launch intent requests via an IntentHandler: this intent handler doesn't do anything useful in this example, besides increasing a counter in the Text object, so that you can see how many times the launch intent has been received. Have a look at the documentation for IntentHandler::requestReceived for more information on the IntentClientRequest::sendReply call. \section2 Application Metadata The \c info.yaml file contains the metadata about a package. It starts with some boilerplate describing that this file contains Qt Application Manager package metadata. \quotefromfile applicationmanager/launch-intents/apps/launch-intents.blue/info.yaml \printuntil -- Then comes the package ID, which uniquely identifies the package. It's recommended to follow a reverse DNS scheme, but it's not enforced. Here it's the "Blue" package from the "Launch Intents" example UI. \printline id: Then the icon filename: \printline icon: Next comes the user-visible name of the application in any number of languages. For this example, we only provide English: \printto applications: For each package, we define one application that gets the same id as the package itself (this is not a requirement, but useful approach to single-application packages. \printto intents: Every package will at least register one \c launch intent in the \c launcher category. The exact name of the intent does not really matter in this case, since the system-ui will just request all intents that are in the \c launcher category. The name and icon of an intent default to the name and icon of the package, but we override the name here: \printuntil \section2 Alias handling The red application does a bit more then the blue and green counterparts: it implements the deprecated "aliases" mechanism using intents. In its \c info.yaml file it defines a second intent in the \c launcher category, named \c another-launch: \quotefromfile applicationmanager/launch-intents/apps/launch-intents.red/info.yaml \skipto id: another-launch \printuntil In order to handle this intent, the IntentHandler in the \c main.qml file is extended to accept both intents: \quotefromfile applicationmanager/launch-intents/apps/launch-intents.red/main.qml \skipto IntentHandler { \printto onRequestReceived: The signal handler for incoming intent request can then disambiguate between the requested intents based on their \c intentId and increase either the normal \c counter or the \c anotherCounter property of the text field. \printuntil /\s+\}/ \note Instead of one IntentHandler handling both intents, this could have also been implemented using two separate IntentHandlers, handling one intent each. */