diff -r 885c2596c964 -r 5d007b20cfd0 qthighway/xqservice/src/xqaiwrequest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qthighway/xqservice/src/xqaiwrequest.cpp Tue Aug 31 16:02:37 2010 +0300 @@ -0,0 +1,657 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, version 2.1 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, +* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/". +* +* Description: +* +*/ + +#include +#include + +#include "xqservicelog.h" +#include "xqaiwservicedriver.h" +#include "xqaiwfiledriver.h" +#include "xqaiwuridriver.h" +#include "xqaiwrequest.h" + +/*! + \class XQAiwRequest + \inpublicgroup QtBaseModule + + \ingroup ipc + \brief Encapsulates the core functionality of the interworking requests + + The XQAiwRequest class encapsulates the core functionality of the interworking requests and hides the implementation details. + This object is created by the XQApplicationManager::create factory method. + + This class is a part of API to be used by the applications instead of using XQServiceRequest directly. + + The Application Manager API offers centric place for applications UIs to handle application to application interworking use cases, like: + - Synchronous out-of-process service call from client to service provider, where service provider needs to complete the request before + control comes back to requesting client. + - Asynchronous out-of-process service call from client to service provider, where Service provider completes the request whenever suitable. + The control returns back requesting as soon the service provider has received the asynchronous call (can be applied to notifications as well). + - Embedded out-of-process service call. In this case window groups are chained and "Back" returns to client window. + - Any named Qt type in the Qt meta-object system can be used as a service call parameter or return value. Also own, custom meta-types are supported. + - Launched service provider application (.exe) if not already running when client makes service call to it. + - List and discover services dynamically. + - Apply UI related options upon service launch, like "launch as embedded", "launch to foreground" and "launch to backround". + - Opening files to be viewed by a file viewing interface. + - Opening URI to be viewed by a URI viewing interface. Includes also launching activity URIs (appto) as fire-and-forget manner. + - Miscellanous AIW support, like get service stasus or get DRM attributes. + + See the "examples/appmgrclient" included in the QtHighway release for usage examples. + + Example usage: \n + The usage pattern for all the XQAiwRequest variants implemented as service providers , interface, QUrl, QFile, is similar both embedded + and non-embedded usage. + \code + // Recommended way is to add XQApplicationManager as member variable to class + // Later on when caching of services + // You can use the class also as local variable. + class Client + { + + public: + // Service access + bool accessService(void); + + private slots: + void handleOk(const QVariant &result); + void handleError(int errorCode, const QString& errorMessage); + private: + XQApplicationManager mAiwMgr; + }; + + + // In client.cpp + bool Client::accessService(void) + { + QString parameter1("+3581234567890"); + int parameter2 = 3; + + bool embedded=true; // or false + + XQAiwRequest *request; + // Create request by interface name, the very first service implementation + // applied. + request = mAiwMgr.create("Interface", "functionName2(QString, int)", embedded); + + // If dedicated service is wanted, apply this + // request = mAiwMgr.create("Service", "Interface", + // "functionName2(QString, int)", embedded); + + if (request == NULL) + { + // Service not found + return false; + } + + // Connect result handling signal + connect(request, SIGNAL(requestOk(const QVariant&)), this, SLOT(handleOk(const QVariant&))); + // Connect error handling signal or apply lastError function instead. + connect(request, SIGNAL(requestError(int,const QString&)), this, SLOT(handleError(int,const QString&))); + + // Set function parameters + QList args; + args << parameter1; + args << parameter2; + request->setArguments(args); + + // In this example, request embedded launch (window groups chained) + request->setEmbedded(true); + + // Send the request + bool res = request.send(); + if (!res) + { + // Request failed. + return false; + } + + // If making multiple requests to same service, you can save the request as member variable + // In this example all done. + delete request; + return true; + } + + void Client::handleOk(const QVariant& result) + { + // Handle result here or just save them. + // Result could be a service specific error code also. + // + } + + void Client::handleError(int errorCode, const QString& errorMessage) + { + // Handle error + } + \endcode + + \sa XQApplicationManager +*/ + +/*! + Constructs interworking request to service application by the given interface \a descriptor + which points to the dedicated implementation. The service application is not started during + creation of the request. + \param descriptor Points to the dedicated service implementation. Obtained via the XQApplicationManager::list function. + \param operation Service function to be called, equals \a message parameter in XQServiceRequest. + \param embedded True if window groups should be chained, false otherwise + \return Constructed interworking request to service application object. +*/ +XQAiwRequest::XQAiwRequest(const XQAiwInterfaceDescriptor& descriptor, const QString &operation, bool embedded) + : QObject(), + currentRequest(NULL), + errorMsg(), + errorCode(0), + completeSignalConnected(false), + errorSignalConnected(false) +{ + + XQSERVICE_DEBUG_PRINT("XQAiwRequest::XQAiwRequest: %s %s,%d,%x", + qPrintable(descriptor.interfaceName()), + qPrintable(operation), + embedded, + descriptor.property(XQAiwInterfaceDescriptor::ImplementationId).toInt()); + + // Initialize service request + // The XQServiceRequest should actually accept service descriptor as input.... + currentRequest = new XQAiwServiceDriver(descriptor, operation); + if (currentRequest) + { + currentRequest->setEmbedded(embedded); + } +} + +/*! + Constructs interworking request to service application by the given uri and the interface \a descriptor + which points to the dedicated implementation. The service application is not started during + creation of the request. + \param uri Uri for the given interworking request to service application. + \param descriptor Points to the dedicated service implementation. Obtained via the XQApplicationManager::list function. + \param operation Service function to be called, equals \a message parameter in XQServiceRequest. + \return Constructed interworking request to service application object. +*/ +XQAiwRequest::XQAiwRequest( + const QUrl &uri, const XQAiwInterfaceDescriptor& descriptor, const QString &operation) + : QObject(), + currentRequest(NULL), + errorMsg(), + errorCode(0), + completeSignalConnected(false), + errorSignalConnected(false) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::XQAiwRequest (uri): %s %s,%x", + qPrintable(descriptor.interfaceName()), + qPrintable(operation), + descriptor.property(XQAiwInterfaceDescriptor::ImplementationId).toInt()); + + if (XQAiwUriDriver::hasCustomHandler(uri)) + { + // Custom handling goes via URI driver + currentRequest = new XQAiwUriDriver(uri, descriptor, operation); + } + else + { + // Otherwise, apply service based URI access + currentRequest = new XQAiwServiceDriver(descriptor, operation); + } + +} + + +/*! + Constructs interworking request to service application by the file and the interface \a descriptor + which points to the dedicated implementation. The service application is not started during + creation of the request. + \param file File for the given interworking request to service application. + \param descriptor Points to the dedicated service implementation. Obtained via the XQApplicationManager::list function. + \param operation Service function to be called, equals \a message parameter in XQServiceRequest. + \return Constructed interworking request to service application object. +*/ +XQAiwRequest::XQAiwRequest( + const QFile &file, const XQAiwInterfaceDescriptor& descriptor, const QString &operation) + : QObject(), + currentRequest(NULL), + errorMsg(), + errorCode(0), + completeSignalConnected(false), + errorSignalConnected(false) +{ + + XQSERVICE_DEBUG_PRINT("XQAiwRequest::XQAiwRequest (file): %s %x", + qPrintable(file.fileName()), + descriptor.property(XQAiwInterfaceDescriptor::ImplementationId).toInt()); + + // Initialize file service request + if (!descriptor.interfaceName().isEmpty()) + { + // Apply normal service request + XQSERVICE_DEBUG_PRINT("Apply service driver"); + currentRequest = new XQAiwServiceDriver(descriptor, operation); + } + else + { + // The is no service provider for the file. + // So as backup plan, apply file driver to handle non-service file launches + XQSERVICE_DEBUG_PRINT("Apply file driver"); + currentRequest = new XQAiwFileDriver(file, descriptor, operation); + } + +} + +/*! + Constructs interworking request to service application by the sharable file and the interface \a descriptor + which points to the dedicated implementation. The service application is not started during + creation of the request. + \param file Sharable file for the given interworking request to service application. + \param descriptor Points to the dedicated service implementation. Obtained via the XQApplicationManager::list function. + \param operation Service function to be called, equals \a message parameter in XQServiceRequest. + \return Constructed interworking request to service application object. +*/ +XQAiwRequest::XQAiwRequest( + const XQSharableFile &file, const XQAiwInterfaceDescriptor& descriptor, const QString &operation) + : QObject(), + currentRequest(NULL), + errorMsg(), + errorCode(0), + completeSignalConnected(false), + errorSignalConnected(false) +{ + + XQSERVICE_DEBUG_PRINT("XQAiwRequest::XQAiwRequest (file handle): %x", + descriptor.property(XQAiwInterfaceDescriptor::ImplementationId).toInt()); + + // Initialize file service request + if (!descriptor.interfaceName().isEmpty()) + { + // Apply normal service request + XQSERVICE_DEBUG_PRINT("Apply service driver"); + currentRequest = new XQAiwServiceDriver(descriptor, operation); + } + else + { + // The is no service provider for the file. + // So as backup plan, apply file driver to handle non-service file launches + XQSERVICE_DEBUG_PRINT("Apply file driver"); + currentRequest = new XQAiwFileDriver(file, descriptor, operation); + } + +} + + +XQAiwRequest::~XQAiwRequest() +{ + XQSERVICE_DEBUG_PRINT("~XQAiwRequest::XQAiwRequest"); + + // Disconnect signals + if (completeSignalConnected) + { + disconnect(currentRequest, SIGNAL(requestOk(const QVariant&)), this, SLOT(handleAsyncResponse(const QVariant&))); + } + if (errorSignalConnected) + { + disconnect(currentRequest, SIGNAL(requestError(int,const QString&)), this, SLOT(handleAsyncError(int))); + } + + delete currentRequest; // Destructor cancels the async request + + for (int i=0; icreateAction(); + if (action) + { + if (!connect(action, SIGNAL(triggered(bool)), this, SLOT(sendFromAction(bool)))) { + XQSERVICE_CRITICAL_PRINT("Failed to connect QAction triggered signal to XQAiwRequest."); + } + actionList.append(action); + return action; + } + + return NULL; +} + +/*! + Set arguments for the request. This shall be called before sending + add the action to wanted UI widget. For the attached action, the + triggered() signal emitted by the request is the last chance to + add aguments. + \param arguments List of arguments that will be transferred to service provider function + to be called +*/ +void XQAiwRequest::setArguments(const QList &arguments) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::setArguments"); + currentRequest->setArguments(arguments); +} + + +/*! + Returns the last error code occured. + IPC errors: + - ENoError = 0 + - EConnectionError = -5000, (Server might be busy) + - EConnectionClosed = -4999, + - EServerNotFound = -4998, + - EIPCError = -4997, + - EUnknownError = -4996, + - ERequestPending = -4995, (already pending request exists) + - EMessageNotFound = -4994, + - EArgumentError = -4993 + \return Error code as integer value. + \sa xqserviceglobal.h for error codes + +*/ +int XQAiwRequest::lastError() const +{ + int err = currentRequest->lastError(); + XQSERVICE_DEBUG_PRINT("XQAiwRequest::lastError %d", err); + return err; +} + +/*! + Returns the last error as text for debugging purposes. + The content and details of the text may vary over API + development time evolution. + \return Error code as QString value. +*/ +const QString& XQAiwRequest::lastErrorMessage() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::lastErrorMessage"); + return currentRequest->lastErrorMessage(); +} + + +/*! + Returns the implementation descriptor of a service attached to request. + Caller can check meta-data information of the request. + \return Implementation descriptor attached to the request. +*/ +const XQAiwInterfaceDescriptor &XQAiwRequest::descriptor() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::descriptor"); + return currentRequest->descriptor(); +} + +/*! + Starts the service application if necessary and sends request on-ward. + The results are delivered via requestOk() and requestError() signals. + If the request is synchronous, the client application is blocked until + service provider completes the request. + \return True on success, false otherwise +*/ +bool XQAiwRequest::send() +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::send"); + + // do request + if (sendExecute()) + { + if (currentRequest->isSynchronous()) + { + XQSERVICE_DEBUG_PRINT("XQAiwRequest::emit requestOk"); + emit requestOk(result); + result.clear(); + } + return true; + } else + { + XQSERVICE_DEBUG_PRINT("XQAiwRequest::emit requestError"); + emit requestError(lastError(), lastErrorMessage()); + return false; + } +} + + +/*! + Convinience method for sending a synchronous request on-ward. + The returnValue delivered via the output parameter. + \return True on success, false otherwise +*/ +bool XQAiwRequest::send(QVariant &returnValue) +{ + + XQSERVICE_DEBUG_PRINT("XQAiwRequest::send(retValue)"); + + // do request + if (sendExecute()) + { + if (currentRequest->isSynchronous()) + { + XQSERVICE_DEBUG_PRINT("XQAiwRequest::set retValue "); + // Do not emit requestOk as return value delivered directly + returnValue = result; // Copy return value + result.clear(); + } + return true; + } else + { + XQSERVICE_DEBUG_PRINT("XQAiwRequest::emit requestError"); + emit requestError(lastError(), lastErrorMessage()); + return false; + } + +} + +/*! + Request service application to be launched in embedded mode. + \param embedded If set to true, service application will be launched + in embedded mode +*/ +void XQAiwRequest::setEmbedded(bool embedded) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::setEmbedded=%d",embedded); + currentRequest->setEmbedded(embedded); +} + +/*! + Get the value of embedded option of the request. + \return True if request is set to launch service application in embedded + mode, false otherwise +*/ +bool XQAiwRequest::isEmbedded() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::isEmbedded"); + return currentRequest->isEmbedded(); +} + +/*! + Sets service operation. The XQApplicationManager::create() functions for + files and URLs set the default operation, but it can be overriden using + this function. + \param operation Operation to be set to the request. +*/ +void XQAiwRequest::setOperation(const QString &operation) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::setOperation"); + currentRequest->setOperation(operation); +} + +/*! + Returns operation attached to the request. + \return Operation attached to the request +*/ +const QString &XQAiwRequest::operation() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::operation"); + return currentRequest->operation(); +} + +/*! + Sets request as synchronous or asynchronous, based on the \a synchronous value. + \param synchronous If set to true, request will be synchronous. + If set to false, request will be asynchronous +*/ +void XQAiwRequest::setSynchronous(bool synchronous) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::setSynchronous=%d", synchronous); + currentRequest->setSynchronous(synchronous); +} + +/*! + Returns the value of the synchronous option. + \return True if request is synchronous, false otherwise +*/ +bool XQAiwRequest::isSynchronous() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::isSynchronous"); + return currentRequest->isSynchronous(); +} + +/*! + Requests service application to be launched to background initially, + or if already running, to go to background. + \param background If set to true, service application will be launched + to background +*/ +void XQAiwRequest::setBackground(bool background ) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::setbackground=%d", background); + currentRequest->setBackground(background); +} + +/*! + Returns the value of the background option. + \return True if request is set to launch service + application to background +*/ +bool XQAiwRequest::isBackground() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::isBackground"); + return currentRequest->isBackground(); +} + +/*! + Used to set additional UI behavior type options to the request. + Embedded and background options are handled by their own functions. + This function should not be used to implement additional data + parameters for operations! + \param info UI bahavior type option to be set to the request. +*/ +void XQAiwRequest::setInfo(const XQRequestInfo &info) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::setInfo"); + return currentRequest->setInfo(info); +} + +/*! + Returns additional options attached to the request. + \return Additional options attached to the request. +*/ +XQRequestInfo XQAiwRequest::info() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::info"); + return currentRequest->info(); +} + + + +const QVariant &XQAiwRequest::results() const +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::results"); + return result; +} + + +void XQAiwRequest::sendFromAction(bool checked) +{ + Q_UNUSED(checked); + + XQSERVICE_DEBUG_PRINT("XQAiwRequest::sendFromAction"); + + emit triggered(); // Last chance to setup request parameters + + // do request + if (sendExecute()) + { + if (isSynchronous()) + { + emit requestOk(result); + result.clear(); + } + } else + { + emit requestError(lastError(), lastErrorMessage()); + } +} + +bool XQAiwRequest::sendExecute() +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::sendExecute>>>"); + + QStringList list; + bool res = true; + if (!isSynchronous() && !completeSignalConnected) + { + // Set async request signals once + XQSERVICE_DEBUG_PRINT("request::async send"); + connect(currentRequest, SIGNAL(requestOk(const QVariant&)), this, SLOT(handleAsyncResponse(const QVariant&))); + completeSignalConnected = true; + } + if (!errorSignalConnected) + { + // Connect always error signal once + connect(currentRequest, SIGNAL(requestError(int,const QString&)), this, SLOT(handleAsyncError(int))); + errorSignalConnected = true; + } + + XQSERVICE_DEBUG_PRINT("request::send>>>"); + res = currentRequest->send(result); // Result is valid for sync request only + XQSERVICE_DEBUG_PRINT("request::send: %d<<<", res); + + errorCode = currentRequest->lastError(); // ask always + if (errorCode || !res) + { + res = false; + } + + XQSERVICE_DEBUG_PRINT("XQAiwRequest::sendExecute: %d<<<", res); + + return res; + +} + + + +void XQAiwRequest::handleAsyncResponse(const QVariant& value) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::handleAsyncResponse"); + emit requestOk(value); +} + +void XQAiwRequest::handleAsyncError(int err) +{ + XQSERVICE_DEBUG_PRINT("XQAiwRequest::handleAsyncError"); + errorCode = err; + emit requestError(lastError(), lastErrorMessage()); +}