diff options
author | Robert Griebl <robert.griebl@pelagicore.com> | 2018-12-13 19:56:34 +0100 |
---|---|---|
committer | Robert Griebl <robert.griebl@pelagicore.com> | 2018-12-18 14:51:41 +0000 |
commit | c79166130d28a8dbe8529d285a78d40768dc5d72 (patch) | |
tree | ebaf460a2906634718bb2394eae1c8012bbb0496 | |
parent | 62af7b9b752d8ffe63bffab43b0c8e1f717b486f (diff) |
Add documentation for the Intents QML API
Change-Id: Ib1a99c2aed7a09a86635ee1d2300e023b924cfbe
Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
-rw-r--r-- | doc/QtApplicationManagerDoc | 3 | ||||
-rw-r--r-- | doc/applicationmanager-project.qdocconf | 4 | ||||
-rw-r--r-- | doc/elements-common.qdoc | 3 | ||||
-rw-r--r-- | src/intent-client-lib/intentclient.cpp | 51 | ||||
-rw-r--r-- | src/intent-client-lib/intentclientrequest.cpp | 136 | ||||
-rw-r--r-- | src/intent-client-lib/intenthandler.cpp | 56 | ||||
-rw-r--r-- | src/intent-server-lib/intent.cpp | 56 | ||||
-rw-r--r-- | src/intent-server-lib/intent.h | 1 | ||||
-rw-r--r-- | src/intent-server-lib/intentserver.cpp | 80 | ||||
-rw-r--r-- | src/manager-lib/intentaminterface.cpp | 2 |
10 files changed, 388 insertions, 4 deletions
diff --git a/doc/QtApplicationManagerDoc b/doc/QtApplicationManagerDoc index 523e87d2..2b2b4aab 100644 --- a/doc/QtApplicationManagerDoc +++ b/doc/QtApplicationManagerDoc @@ -4,7 +4,8 @@ #include <QtAppManCrypto/QtAppManCrypto> #include <QtAppManDBus/QtAppManDBus> #include <QtAppManInstaller/QtAppManInstaller> -#include <QtAppManIpc/QtAppManIpc> +#include <QtAppManIntentClient/QtAppManIntentClient> +#include <QtAppManIntentServer/QtAppManIntentServer> #include <QtAppManLauncher/QtAppManLauncher> #include <QtAppManMain/QtAppManMain> #include <QtAppManManager/QtAppManManager> diff --git a/doc/applicationmanager-project.qdocconf b/doc/applicationmanager-project.qdocconf index 0532d1d7..cced11ee 100644 --- a/doc/applicationmanager-project.qdocconf +++ b/doc/applicationmanager-project.qdocconf @@ -20,6 +20,8 @@ headerdirs += \ ../src/application-lib \ ../src/package-lib \ ../src/installer-lib \ + ../src/intent-client-lib \ + ../src/intent-server-lib \ ../src/notification-lib \ ../src/window-lib \ ../src/launcher-lib \ @@ -36,6 +38,8 @@ sourcedirs += \ ../src/application-lib \ ../src/package-lib \ ../src/installer-lib \ + ../src/intent-client-lib \ + ../src/intent-server-lib \ ../src/notification-lib \ ../src/window-lib \ ../src/launcher-lib \ diff --git a/doc/elements-common.qdoc b/doc/elements-common.qdoc index 6c68c089..866c70b8 100644 --- a/doc/elements-common.qdoc +++ b/doc/elements-common.qdoc @@ -46,4 +46,7 @@ declarations may be nested, creating parent-child relationships between the item \annotatedlist common-instantiatable +\section1 Non-Instantiable QML Types + +\annotatedlist common-non-instantiable */ diff --git a/src/intent-client-lib/intentclient.cpp b/src/intent-client-lib/intentclient.cpp index 786d30fc..0c5d5264 100644 --- a/src/intent-client-lib/intentclient.cpp +++ b/src/intent-client-lib/intentclient.cpp @@ -55,6 +55,34 @@ QT_BEGIN_NAMESPACE_AM +/*! + \qmltype IntentClient + \inqmlmodule QtApplicationManager + \ingroup common-singletons + \brief Singleton that provides functions to create Intent requests. + + This type can be used both in applications as well as within the System-UI to create intent + requests. This type is only the factory, returning instances of the type IntentRequest. See + the IntentRequest documentation for details on how to actually handle these asynchronous calls. + + Here is a fairly standard way to send an intent request and react on its result (or error + message): + + \qml + MouseArea { + onClicked: { + var request = IntentClient.sendIntentRequest("show-image", { url: "file://x.png" }) + request.onReplyReceived.connect(function() { + if (request.succeeded) + var result = request.result + else + console.log("Intent request failed: " + request.errorMessage) + }) + } + } + \endqml +*/ + IntentClient *IntentClient::s_instance = nullptr; IntentClient *IntentClient::createInstance(IntentClientSystemInterface *systemInterface) @@ -143,11 +171,34 @@ void IntentClient::unregisterHandler(IntentHandler *handler) } } +/*! \qmlmethod IntentRequest IntentClient::sendIntentRequest(string intentId, var parameters) + + Sends a request for an intent with the given \a intentId to the system. The additional + \a parameters are specific to the requested \a intentId, but the format is always the same: a + standard JavaScript object, which can also be just empty if the requested intent doesn't + require any parameters. + + Returns an IntentRequest object that can be used to track this asynchronous request. + + \note The returned object has JavaScript ownership, which means that you do not have to worry + about freeing resources. Even just ignoring the return value is fine, if you are not + interested in the result (or error condition) of your request. +*/ IntentClientRequest *IntentClient::sendIntentRequest(const QString &intentId, const QVariantMap ¶meters) { return sendIntentRequest(intentId, QString(), parameters); } +/*! \qmlmethod IntentRequest IntentClient::sendIntentRequest(string intentId, string applicationId, var parameters) + \overload + + Instead of letting the system-ui (or the user) choose which application should handle your + request, you can use this overload to hardcode the \a applicationId that is required to handle + it. The request will fail, if this specified application doesn't exist or can't handle this + specific request, even though other applications would be able to do it. + + \sa sendIntentRequest +*/ IntentClientRequest *IntentClient::sendIntentRequest(const QString &intentId, const QString &applicationId, const QVariantMap ¶meters) { diff --git a/src/intent-client-lib/intentclientrequest.cpp b/src/intent-client-lib/intentclientrequest.cpp index 903e335b..27358307 100644 --- a/src/intent-client-lib/intentclientrequest.cpp +++ b/src/intent-client-lib/intentclientrequest.cpp @@ -51,6 +51,118 @@ QT_BEGIN_NAMESPACE_AM +/*! \qmltype IntentRequest + \inqmlmodule QtApplicationManager + \ingroup common-non-instantiable + \brief Each instance represents an outgoing or incoming intent request. + + This type is used both in applications as well as within the System-UI to represent an intent + request. This type can not be instantiated directly, but will be returned by + IntentClient::sendIntentRequest() (for outgoing requests to the system) and + IntentHandler::requestReceived() (for incoming requests to the application) + + See the IntentClient type for a short example on how to send intent requests to the system. + + The IntentHandler documenatation provides an example showing the use of this type when receiving + requests from the system. +*/ + +/*! \qmlproperty uuid IntentRequest::requestId + \readonly + + Every intent request in the system gets an unique requestId assigned by the server that will be + used throughout the life-time of the request in every context (requesting application, handling + application and intent server). + \note Since this requestId is generated by the server, any IntentRequest object generated by + IntentClient::sendIntentRequest() will start with a null requestId. The property will + be updated asynchronously once the server has assigned a new requestId to the + incoming request. + + \note Constant for requests received by IntentHandlers, valid on both sent and received requests. +*/ + +/*! \qmlproperty IntentRequest::Direction IntentRequest::direction + \readonly + + This property describes if this instance is an outgoing or incoming intent request: + + \list + \li IntentRequest.ToSystem - The request object was generated by IntentClient::sendIntentRequest(), + i.e. this request is sent out to the system side for handling. + \li IntentRequest.ToApplication - The request object was received by IntentHandler::requestReceived(), + i.e. this request was sent from the system side to the + application for handling. + \endlist + + \note Constant, valid on both sent and received requests. +*/ + +/*! \qmlproperty string IntentRequest::intentId + \readonly + + The requested intent id. + + \note Constant, valid on both sent and received requests. +*/ + +/*! \qmlproperty string IntentRequest::applicationId + \readonly + + The id of the application which should be handling this request. Returns an empty string if + no specific application was requested. + + \note Constant, valid on both sent and received requests. +*/ + +/*! \qmlproperty var IntentRequest::parameters + \readonly + + All parameters attached to the request as a JavaScript object. + + \note Constant, valid on both sent and received requests. +*/ + +/*! \qmlproperty bool IntentRequest::succeeded + \readonly + + As soon as the replyReceived() signal has been emitted, this property will show if the + intent request was actually successful. + + \note Valid only on sent requests. +*/ + +/*! \qmlproperty string IntentRequest::errorMessage + \readonly + + As soon as the replyReceived() signal has been emitted, this property will hold a potential + error message in case the request failed. + + \note Valid only on sent requests. + + \sa succeeded +*/ + +/*! \qmlproperty var IntentRequest::result + \readonly + + As soon as the replyReceived() signal has been emitted, this property will hold the result in + form of a JavaScript object in case the request succeeded. + + \note Valid only on sent requests. + + \sa succeeded +*/ + +/*! \qmlsignal IntentRequest::replyReceived() + + This signal gets emitted when a reply to an intent request is available. The signal handler + needs to check the succeeded property to decided whether errorMessage or result are actually + valid. + + \note This signal will only ever by emitted for request objects created by + IntentClient.sendIntentRequest(). +*/ + IntentClientRequest::Direction IntentClientRequest::direction() const { @@ -104,6 +216,18 @@ QString IntentClientRequest::errorMessage() const return m_errorMessage; } +/*! \qmlmethod IntentRequest::sendReply(var result) + + An IntentHandler needs to call this function to send its \a result back to the system in reply + to an request received via IntentHandler::requestReceived(). + + Only either sendReply() or sendErrorReply() can be used on a single IntentRequest. + + \note This function only works for request objects received from IntentHandler::requestReceived(). + It will simply do nothing on requests created by IntentClient::sendIntentRequest(). + + \sa sendErrorReply +*/ void IntentClientRequest::sendReply(const QVariantMap &result) { //TODO: check that result only contains basic datatypes. convertFromJSVariant() does most of @@ -126,6 +250,18 @@ void IntentClientRequest::sendReply(const QVariantMap &result) } } +/*! \qmlmethod IntentRequest::sendErrorReply(string errorMessage) + + IntentHandlers can use this function to indicate that they are unable to handle a request that + they received via IntentHandler::requestReceived(), stating the reason in \a errorMessage. + + Only either sendReply() or sendErrorReply() can be used on a single IntentRequest. + + \note This function only works for request objects received from IntentHandler::requestReceived(). + It will simply do nothing on requests created by IntentClient::sendIntentRequest(). + + \sa sendReply +*/ void IntentClientRequest::sendErrorReply(const QString &errorMessage) { if (m_direction == Direction::ToSystem) { diff --git a/src/intent-client-lib/intenthandler.cpp b/src/intent-client-lib/intenthandler.cpp index b32d08a2..24579aef 100644 --- a/src/intent-client-lib/intenthandler.cpp +++ b/src/intent-client-lib/intenthandler.cpp @@ -45,6 +45,62 @@ QT_BEGIN_NAMESPACE_AM +/*! \qmltype IntentHandler + \inqmlmodule QtApplicationManager.Application + \ingroup common-instantiatable + \brief A handler for intent requests received by applications. + + Any application that has intents listed in its manifest file needs to have a corresponding + IntentHandler instance that is actually able to handle incoming requests. This class gives + you the flexibility to handle multiple, different intent ids via a single IntentHandler + instance or have a dedicated IntentHandler instance for every intent id (or any combination of + those). + + Here is a fairly standard way to handle an incoming intent request and send out a result or + error message: + + \qml + Image { + id: viewer + } + + IntentHandler { + intentIds: [ "show-image" ] + onRequestReceived: { + var url = request.parameters["url"] + if (!url.startsWith("file://")) { + request.sendErrorReply("Only file:// urls are supported") + } else { + viewer.source = url + request.sendReply({ "status": source.status }) + } + } + } + \endqml + +*/ + +/*! \qmlproperty list<string> IntentHandler::intentIds + + Every handler needs to register at least one unique intent id that it will handle. Having + multiple IntentHandlers that are registering the same intent id is not possible. + + \note Any changes to this property after component completion will have no effect. This + restriction will likely be removed in a future update. +*/ + +/*! \qmlsignal IntentHandler::requestReceived(IntentRequest request) + + This signal will be emitted once for every incoming intent \a request that this handler was + registered for via its intentIds property. + Handling the request can be done synchronously or asynchronously. As soon as your handler has + either produced a result or detected an error condition, it should call either + IntentClientRequest::sendReply() or IntentClientRequest::sendErrorReply respectively to send a + reply back to the requesting party. + Only the first call to one of these functions will have any effect. Any further invocations + will be ignored. +*/ + IntentHandler::IntentHandler(QObject *parent) : QObject(parent) { } diff --git a/src/intent-server-lib/intent.cpp b/src/intent-server-lib/intent.cpp index caaa78a2..b1151910 100644 --- a/src/intent-server-lib/intent.cpp +++ b/src/intent-server-lib/intent.cpp @@ -47,6 +47,62 @@ QT_BEGIN_NAMESPACE_AM + +/*! + \qmltype Intent + \inqmlmodule QtApplicationManager.SystemUI + \ingroup system-ui-non-instantiable + \brief This type represents an Intent definition on the System-UI side. + + This is a QML gadget class representing a single Intent definition for a specific application. + It is not creatable from QML code and all properties are read-only. Only functions and + properties of IntentServer will return instances of this class. +*/ + +/*! \qmlproperty bool Intent::valid + \readonly + Set to \c true, if this instance reprensents a valid intent, or \c false otherwise. +*/ + +/*! \qmlproperty string Intent::intentId + \readonly + The id of the intent. +*/ + +/*! \qmlproperty string Intent::applicationId + \readonly + The id of the application that is handling this intent. +*/ + +/*! \qmlproperty Intent.Visibility Intent::visibility + \readonly + The visibility of this intent for other applications. + + \list + \li Intent.Public - Any application can request this intent. + \li Intent.Private - Only the handling application can request this intent (this will be more + useful once application background services have been implemented). + \endlist +*/ + +/*! \qmlproperty list<string> Intent::requiredCapabilities + \readonly + An \l{ApplicationObject}{application} requesting this intent needs to have all of the given + capabilities. + + \sa ApplicationObject::capabilities +*/ + +/*! \qmlproperty var Intent::parameterMatch + \readonly + A handling application can limit what parameter values it accepts. One example would be an + open-mime-type intent that is implemented by many applications: there would be a \c mimeType + parameter and each application could limit the requests it wants to receive by setting a + parameterMatch on this \c mimeType parameter, e.g. \c{{ mimeType: "^image/.*\.png$" }} + +*/ + + Intent::Intent() { } diff --git a/src/intent-server-lib/intent.h b/src/intent-server-lib/intent.h index 4a56ac75..2ed3ad68 100644 --- a/src/intent-server-lib/intent.h +++ b/src/intent-server-lib/intent.h @@ -62,7 +62,6 @@ class Intent public: enum Visibility { Public, - Hidden, Private }; Q_ENUM(Visibility) diff --git a/src/intent-server-lib/intentserver.cpp b/src/intent-server-lib/intentserver.cpp index 780ebaba..eac17a44 100644 --- a/src/intent-server-lib/intentserver.cpp +++ b/src/intent-server-lib/intentserver.cpp @@ -59,6 +59,34 @@ QT_BEGIN_NAMESPACE_AM +/*! + \qmltype IntentServer + \inqmlmodule QtApplicationManager.SystemUI + \ingroup system-ui-singletons + \brief The System-UI side singleton representing the Intents sub-system. + + This singleton serves two purposes: for one, it gives the System-UI access to the database of + all the available intents via intentList, plus it exposes the API to deal with ambigous intent + requests. Intent requests can be ambigous if the requesting party only specified the \c + intentId, but not the targeted \c applicationId in its call to + IntentClient::sendIntentRequest(). In these cases, it is the responsibility of the System-UI to + disambiguate these requests by reacting on the disambiguationRequest() signal. +*/ + +/*! \qmlsignal IntentServer::intentAdded(Intent intent) + Emitted when a new \a intent gets added to the intentList (e.g. on application installation). +*/ + +/*! \qmlsignal IntentServer::intentRemoved(Intent intent) + Emitted when an existing \a intent is removed from the intentList (e.g. on application + deinstallation). +*/ + +/*! \qmlsignal IntentServer::intentListChanged() + Emitted when either a new \a intent gets added to or an existing \a intent is remove from the + intentList. +*/ + IntentServer *IntentServer::s_instance = nullptr; IntentServer *IntentServer::createInstance(IntentServerSystemInterface *systemInterface) @@ -249,11 +277,27 @@ QVector<Intent> IntentServer::filterByRequestingApplicationId(const QVector<Inte return result; } +/*! \qmlproperty list<Intent> IntentServer::intentList + + The list of all registered \l{Intent}{Intents} in the system. +*/ + IntentList IntentServer::intentList() const { return convertToQml(all()); } +/*! \qmlmethod Intent IntentServer::find(string intentId, string applicationId, var parameters = {}) + + This method exposes the same functionality that is used internally to match incoming Intent + requests for the intent identified by \a intentId and targeted for the application identified by + \a applicationId. + Although you could iterate over the intentList yourself in JavaScript, this function has the + added benefit of also checking the \a parameters against any given \l{Intent::parameterMatch} + {parameter matches}. + + If no matching Intent is found, the function will return an \l{Intent::valid}{invalid} Intent. +*/ Intent IntentServer::find(const QString &intentId, const QString &applicationId, const QVariantMap ¶meters) const { auto it = std::find_if(m_intents.cbegin(), m_intents.cend(), @@ -379,11 +423,47 @@ IntentList IntentServer::convertToQml(const QVector<Intent> &intents) return vl; } +/*! + \qmlsignal IntentServer::disambiguationRequest(uuid requestId, list<Intent> potentialIntents, var parameters) + + This signal is emitted when the IntentServer receives an intent request that could potentially + be handled by more than one application. + + \note This signal is only emitted, if there is a receiver connected at all. If the signal is not + connected, an arbitrary application from the list of potential matches will be chosen to + handle this request. + + The receiver of this signal gets the requested \a requestId and its \a parameters. It can + then either call acknowledgeDisambiguationRequest() to choose from one of the supplied \a + potentialIntents or call rejectDisambiguationRequest() to reject the intent request completely. + In both cases the unique \a requestId needs to be sent along to identify the intent request. + + Not calling one of these two functions will result in memory leaks. + + \sa IntentClient::sendIntentRequest +*/ + +/*! \qmlmethod IntentServer::acknowledgeDisambiguationRequest(uuid requestId, Intent selectedIntent) + + Tells the IntentServer to go ahead with the sender's intent request identified by \a requestId. + The chosen \a selectedIntent needs to be one of the \c potentialIntents supplied to the + receiver of the disambiguationRequest signal. + + \sa IntentClient::sendIntentRequest +*/ void IntentServer::acknowledgeDisambiguationRequest(const QUuid &requestId, const Intent &selectedIntent) { internalDisambiguateRequest(requestId, false, selectedIntent); } + +/*! \qmlmethod IntentServer::rejectDisambiguationRequest(uuid requestId) + + Tells the IntentServer to ignore the sender's intent request identified by \a requestId. + The original sender will get an error reply back in this case. + + \sa IntentClient::sendIntentRequest +*/ void IntentServer::rejectDisambiguationRequest(const QUuid &requestId) { internalDisambiguateRequest(requestId, true, Intent()); diff --git a/src/manager-lib/intentaminterface.cpp b/src/manager-lib/intentaminterface.cpp index 43b427b3..713b2039 100644 --- a/src/manager-lib/intentaminterface.cpp +++ b/src/manager-lib/intentaminterface.cpp @@ -151,8 +151,6 @@ void IntentAMImplementation::addApplicationIntents(AbstractApplication *app, Int if (visibilityStr == qL1S("private")) visibility = Intent::Private; - else if (visibilityStr == qL1S("hidden")) - visibility = Intent::Hidden; else if (!visibilityStr.isEmpty() && (visibilityStr != qL1S("public"))) { throw Exception(Error::Intents, "intent visibilty %3 is invalid (intent %2, app %1)") .arg(app->id()).arg(id).arg(visibilityStr); |