summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@pelagicore.com>2018-12-13 19:56:34 +0100
committerRobert Griebl <robert.griebl@pelagicore.com>2018-12-18 14:51:41 +0000
commitc79166130d28a8dbe8529d285a78d40768dc5d72 (patch)
treeebaf460a2906634718bb2394eae1c8012bbb0496
parent62af7b9b752d8ffe63bffab43b0c8e1f717b486f (diff)
Add documentation for the Intents QML API
Change-Id: Ib1a99c2aed7a09a86635ee1d2300e023b924cfbe Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
-rw-r--r--doc/QtApplicationManagerDoc3
-rw-r--r--doc/applicationmanager-project.qdocconf4
-rw-r--r--doc/elements-common.qdoc3
-rw-r--r--src/intent-client-lib/intentclient.cpp51
-rw-r--r--src/intent-client-lib/intentclientrequest.cpp136
-rw-r--r--src/intent-client-lib/intenthandler.cpp56
-rw-r--r--src/intent-server-lib/intent.cpp56
-rw-r--r--src/intent-server-lib/intent.h1
-rw-r--r--src/intent-server-lib/intentserver.cpp80
-rw-r--r--src/manager-lib/intentaminterface.cpp2
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 &parameters)
{
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 &parameters)
{
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 &parameters) 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);