diff options
author | Alan Alpert <alan.alpert@nokia.com> | 2012-04-26 19:32:48 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-19 06:39:41 +0200 |
commit | ffc209f6e365e7a32cb3c7b5d09f72c54f47d2a2 (patch) | |
tree | b57f9eac92bdf43bf3bba852bd0b52c495e495be /src/imports | |
parent | b04b5a3f5b7696c3d23cefaae23359fb9efcd315 (diff) |
Adds new asynchronous friendly types.
The old types will probably be deprecated at some point, but they're
still provided so that users have time to switch.
Change-Id: I0f3068e77d4252e777a2771950fc665f0d509bb7
Reviewed-by: Andrew Stanley-Jones <andrew.stanley-jones@nokia.com>
Diffstat (limited to 'src/imports')
-rw-r--r-- | src/imports/serviceframework/qdeclarativeservice.cpp | 726 | ||||
-rw-r--r-- | src/imports/serviceframework/qdeclarativeservice_p.h | 378 | ||||
-rw-r--r-- | src/imports/serviceframework/qdeclarativeserviceold.cpp | 636 | ||||
-rw-r--r-- | src/imports/serviceframework/qdeclarativeserviceold_p.h | 209 | ||||
-rw-r--r-- | src/imports/serviceframework/serviceframework.cpp | 6 | ||||
-rw-r--r-- | src/imports/serviceframework/serviceframework.pro | 4 |
6 files changed, 1435 insertions, 524 deletions
diff --git a/src/imports/serviceframework/qdeclarativeservice.cpp b/src/imports/serviceframework/qdeclarativeservice.cpp index 547b4b9e..bdecd1ce 100644 --- a/src/imports/serviceframework/qdeclarativeservice.cpp +++ b/src/imports/serviceframework/qdeclarativeservice.cpp @@ -44,592 +44,502 @@ #include <QQmlEngine> #include <QQmlInfo> +#include <qservicereply.h> + QT_BEGIN_NAMESPACE /*! - \qmlclass Service QDeclarativeService + \qmlclass ServiceLoader QDeclarativeService - \brief The Service element holds an instance of a service object. + \brief The ServiceLoader element holds an instance of a service object. \inherits QObject - + \inqmlmodule QtServiceFramework 5 \ingroup qml-serviceframework - The Service element is part of the Qt ServiceFramework API and - provides a client instance of the service object. This element is a simplified - reflection of the QServiceInterfaceDescriptor class that allows the specification of + The ServiceLoader element is part of the Qt ServiceFramework API and + provides a client instance of the service object. This element allows the specification of the Service::interfaceName to locate the default service implemented at this interface. + To request a service more specifically, you can filter available ServiceDescriptors with + the ServiceFilter element, and then request service objects based off them. + + Either way, the ServiceLoader element will provide you with the QtObject provided by that service + interface. You can then use its properties, signals, and slots as defined by its interface. + + Example: + \code + import QtQuick 2.0 + import QtServiceFramework 5.0 + + QtObject { + property alias serviceObject: service.serviceObject //In case you want to expose it upwards + ServiceLoader { + interfaceName: "com.qt.nokia.example.interface" + onStatusChanged: { + if (status == Service.Ready) + foo(serviceObject); //In case you want to do something with it as soon as it loads + else if (status == Service.Error) + errorHandling(errorString()); //In case you want to do error handling. + } + } + } + \endcode + \sa ServiceList */ -QDeclarativeService::QDeclarativeService() - : m_serviceInstance(0), m_componentComplete(false) +QDeclarativeServiceLoader::QDeclarativeServiceLoader() + : m_serviceDescriptor(0), m_status(Null), m_asynchronous(true), + m_serviceObject(0), m_componentComplete(false), m_serviceManager(0), + m_serviceReply(0) { - m_serviceManager = new QServiceManager(); } -QDeclarativeService::~QDeclarativeService() +QDeclarativeServiceLoader::~QDeclarativeServiceLoader() { - delete m_serviceInstance; + //Manager has qobject ownership + delete m_serviceObject;//QOBJECT parented? + delete m_serviceReply; } /*! - \qmlproperty bool Service::valid read-only + \qmlmethod string ServiceLoader::errorString() - This property holds whether a default service was found at the - interface name and corresponds to QServiceInterfaceDescriptor::isValid(). -*/ -bool QDeclarativeService::isValid() const -{ - return m_descriptor.isValid(); -} - -void QDeclarativeService::setInterfaceDesc(const QServiceInterfaceDescriptor &desc) -{ - if (desc == m_descriptor) - return; + This method returns a human readable description of the last error. - m_descriptor = desc; + If the status is not ServiceLoader.Error, errorString() will return an empty string. +*/ +/*! + \qmlproperty Status ServiceLoader::status + + This property contains the status of the service object. It will be one of the following: + + \list + \li ServiceLoader.Null - the service is inactive or no service has been set + \li ServiceLoader.Ready - the service has been loaded + \li ServiceLoader.Loading - the service is currently being loaded + \li ServiceLoader.Error - an error occurred while loading the service + \endlist + + If you want to do something immediately after the service loads, the recommended route is + to monitor this property. For example: + \code + ServiceLoader { + onStatusChanged: { + if (status == ServiceLoader.Ready) + doStuffWith(serviceObject) + else if (status == ServiceLoader.Error) + console.debug(errorString()) + } + } + \endcode - if (m_serviceInstance) - delete m_serviceInstance; - setServiceObject(0); -} +*/ +/*! + \qmlproperty bool ServiceLoader::asynchronous -QServiceInterfaceDescriptor QDeclarativeService::interfaceDesc() const -{ - return m_descriptor; -} + If asynchronous is false, then the element will block the main thread until a service object + is found or an error occurs. This will skip the Loading status. This is generally not + recommended, as blocking the main thread can lead to significant problems with user interface + responsiveness. + Default is true. +*/ /*! - \qmlproperty QString Service::interfaceName + \qmlproperty string ServiceLoader::interfaceName - This property holds the interface name of the service that - corresponds to QServiceInterfaceDescriptor::interfaceName(). + Set this to select a service based off of the interface name. The service name, + and service version, will be selected for you if a match is found. */ -void QDeclarativeService::setInterfaceName(const QString &interface) -{ - m_interface = interface; - updateDescriptor(); -} - -QString QDeclarativeService::interfaceName() const -{ - if (isValid()) - return m_descriptor.interfaceName(); - else - return "No Interface"; -} - /*! - \qmlproperty QString Service::serviceName + \qmlproperty ServiceDescriptor* ServiceLoader::serviceDescriptor + + Set this to select a specific service. ServiceDescriptors can be obtained + from the ServiceFilter element. - This property holds the service name of the service that - corresponds to QServiceInterfaceDescriptor::serviceName(). */ -QString QDeclarativeService::serviceName() const -{ - if (isValid()) - return m_descriptor.serviceName(); - else - return "No Service"; -} -void QDeclarativeService::setServiceName(const QString &service) -{ - m_service = service; -} /*! - \qmlproperty int Service::majorVersion + \qmlproperty QObject* ServiceLoader::serviceObject - This property holds the major version number of the service that - corresponds to QServiceInterfaceDescriptor::majorVersion(). + This property holds an instance of the service object which + can be used to make metaobject calls to the service. + + serviceObject is only valid when the status property is set to + ServiceLoader.Ready. Otherwise, it should be a null reference. */ -int QDeclarativeService::majorVersion() const +void QDeclarativeServiceLoader::componentComplete() { - if (isValid()) - return m_descriptor.majorVersion(); - else - return 0; + if (!m_interfaceName.isEmpty() || m_serviceDescriptor) + startLoading(); + m_componentComplete = true; } -void QDeclarativeService::setMajorVersion(int version) +void QDeclarativeServiceLoader::startLoading() { - m_major = version; - updateDescriptor(); -} + if (m_serviceReply) // Cancel pending requests + delete m_serviceReply; //Auto-disconnects signals -/*! - \qmlproperty int Service::minorVersion + if (m_serviceObject) { + m_serviceObject->deleteLater(); + m_serviceObject = 0; + emit serviceObjectChanged(0);// In sync only, you might get an extra signal + } - This property holds the minor version number of the service that - corresponds to QServiceInterfaceDescriptor::minorVersion(). -*/ -int QDeclarativeService::minorVersion() const -{ - if (isValid()) - return m_descriptor.minorVersion(); - else - return 0; + if (!m_serviceDescriptor && m_interfaceName.isEmpty()) { //Actually an 'unset' request + setStatus(Null); + return; + } + + if (!m_serviceManager) + m_serviceManager = new QServiceManager(this); + + if (m_asynchronous) { + if (m_serviceDescriptor) + m_serviceReply = m_serviceManager->loadInterfaceRequest(*m_serviceDescriptor); + else + m_serviceReply = m_serviceManager->loadInterfaceRequest(m_interfaceName); + connect(m_serviceReply, SIGNAL(finished()), + this, SLOT(finishLoading())); + setStatus(Loading); + } else { + finishLoading(); + } } -void QDeclarativeService::setMinorVersion(int version) +QString stringForError(QServiceManager::Error error)// ### Should we just expose the enum? Or merely pick better strings? { - m_minor = version; - updateDescriptor(); + switch (error) { + case QServiceManager::NoError: return QLatin1String("No error occurred."); + case QServiceManager::StorageAccessError: return QLatin1String("Storage access error."); + case QServiceManager::InvalidServiceLocation: return QLatin1String("Invalid service location."); + case QServiceManager::InvalidServiceXml: return QLatin1String("Invalid service XML."); + //case QService::InvalidInterfaceDescriptor: return QLatin1String("Invalid interface descriptor."); + case QServiceManager::PluginLoadingFailed: return QLatin1String("Error loading service plugin."); + case QServiceManager::ComponentNotFound: return QLatin1String("Service component not found."); + case QServiceManager::ServiceCapabilityDenied: return QLatin1String("You do not have permission to access this service capability."); + default: break; + } + return QLatin1String("Unknown error."); } -/*! - \qmlproperty QObject* Service::serviceObject - - This property holds an instance of the service object which - can be used to make metaobject calls to the service. This - corresponds to QServiceManager::loadInterface(). -*/ -QObject* QDeclarativeService::serviceObject() +void QDeclarativeServiceLoader::finishLoading() { - if (m_serviceInstance) { - return m_serviceInstance; + Q_ASSERT(m_serviceManager); + QServiceManager::Error error; + QObject* prevObject = m_serviceObject; + if (m_serviceReply) { + if (!m_serviceReply->isFinished()) + return; //TODO: Evaluate/handle this error condition + error = m_serviceReply->error(); + m_serviceObject = m_serviceReply->proxyObject(); + m_serviceReply->deleteLater(); + m_serviceReply = 0; + } else { + if (m_asynchronous) + qDebug() << "Uh oh..."; //TODO: Evaluate/handle this 'error' condition + if (m_serviceDescriptor) + m_serviceObject = m_serviceManager->loadInterface(*m_serviceDescriptor); + else + m_serviceObject = m_serviceManager->loadInterface(m_interfaceName); + error = m_serviceManager->error(); } - if (isValid()) { - QObject *object = m_serviceManager->loadInterface(m_descriptor); - setServiceObject(object); - if (!m_serviceInstance) { - emit error(QLatin1String("Failed to create object")); - return m_serviceInstance; - } - emit serviceObjectChanged(); - connect(m_serviceInstance, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), - this, SLOT(IPCFault(QService::UnrecoverableIPCError))); - m_error.clear(); - return m_serviceInstance; + if (error != QServiceManager::NoError) { + m_serviceObject = 0; + if (!m_asynchronous) + emit serviceObjectChanged(0);// In sync we didn't emit the intermediate state + m_errorString = stringForError(error); + setStatus(Error); } else { - return 0; + setStatus(Ready); + connect(m_serviceObject, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), + this, SLOT(IPCFault(QService::UnrecoverableIPCError))); } -} - -/*! - \qmlproperty QString Service::error - - This property holds the last error the was received, if any - */ + if (prevObject != m_serviceObject) + emit serviceObjectChanged(m_serviceObject); -QString QDeclarativeService::lastError() const -{ - return m_error; + delete m_serviceManager; + m_serviceManager = 0; } -void QDeclarativeService::IPCFault(QService::UnrecoverableIPCError errorValue) +void QDeclarativeServiceLoader::IPCFault(QService::UnrecoverableIPCError errorValue) { switch (errorValue) { default: case QService::ErrorUnknown: - m_error = QLatin1String("IPC Error: Unkown Error"); + m_errorString = QLatin1String("IPC Error: Unkown Error"); break; case QService::ErrorServiceNoLongerAvailable: - m_error = QLatin1String("IPC Error: Service no longer available"); + m_errorString = QLatin1String("IPC Error: Service no longer available"); break; case QService::ErrorOutofMemory: - m_error = QLatin1String("IPC Error: Out of memory"); + m_errorString = QLatin1String("IPC Error: Out of memory"); break; case QService::ErrorPermissionDenied: - m_error = QLatin1String("IPC Error: Permission Denied"); + m_errorString = QLatin1String("IPC Error: Permission Denied"); break; case QService::ErrorInvalidArguments: - m_error = QLatin1String("IPC Error: Invalid Arguments"); + m_errorString = QLatin1String("IPC Error: Invalid Arguments"); break; } - emit error(m_error); - m_serviceInstance->deleteLater(); - setServiceObject(0); + setStatus(Error); + m_serviceObject->deleteLater(); } -void QDeclarativeService::updateDescriptor() -{ - if (!m_componentComplete) - return; - - if (m_interface.isEmpty()) - return; - - QServiceInterfaceDescriptor new_desc; - - if (m_minor == 0 && m_major == 0 && m_service.isEmpty()){ - new_desc = m_serviceManager->interfaceDefault(m_interface); - } - else { - QServiceFilter filter; - if (!m_service.isEmpty()) - filter.setServiceName(m_service); - +/*! + \qmlclass ServiceDescriptor QDeclarativeServiceDescriptor - if (m_minor != 0 || m_major != 0) { - const QString version = QString::number(m_major) + "." + QString::number(m_minor); - filter.setInterface(m_interface, version); - } + \brief The ServiceDescriptor element holds a description of a service. + \inherits QObject - QList<QServiceInterfaceDescriptor> list = m_serviceManager->findInterfaces(filter); - if (!list.isEmpty()) - new_desc = list.takeFirst(); - } + \ingroup qml-serviceframework - if (new_desc != m_descriptor) { - m_descriptor = new_desc; - if (m_serviceInstance) - emit serviceObjectChanged(); - } + The ServiceDescriptor element is a simplified reflection of the ServiceDescriptor class, + and is used merely to contain data that can uniquely identify a service. - if (!isValid()) { - qWarning() << "WARNING: No service found for interface name: " << m_interface << m_service << m_major << m_minor; - } -} + It cannot be created manually, use a ServiceList to search for service descriptions. -void QDeclarativeService::setServiceObject(QObject *object) -{ - if (m_serviceInstance != object) { - m_serviceInstance = object; - emit serviceObjectChanged(); - } -} + \sa ServiceList +*/ +/*! + \qmlproperty QString ServiceDescriptor::serviceName -void QDeclarativeService::classBegin() -{ + This property holds the interface name of the service. +*/ +/*! + \qmlproperty QString ServiceDescriptor::interfaceName -} + This property holds the interface name of the service. +*/ -void QDeclarativeService::componentComplete() -{ - m_componentComplete = true; - updateDescriptor(); -} +/*! + \qmlproperty int ServiceDescriptor::majorVersion -bool QDeclarativeService::operator ==(const QServiceInterfaceDescriptor& other ) const -{ - if ( m_descriptor == other) - return true; + This property holds the major version number of the service. +*/ +/*! + \qmlproperty int ServiceDescriptor::minorVersion - return false; -} + This property holds the minor version number of the service. +*/ +//TODO: Fix doc or remove property +/*! + \qmlproperty bool ServiceDescriptor::valid + I have no clue what this property does, but it's probably important. +*/ /*! - \qmlclass ServiceList QDeclarativeServiceList + \qmlclass ServiceFilter QDeclarativeServiceFilter - \brief The ServiceList element holds a list of \l Service elements. + \brief The ServiceFilter element holds a list of \l ServiceDescriptor objects. \inherits QObject \ingroup qml-serviceframework - The ServiceList element is part of the Qt ServiceFramework API and - provides a list of \l Service elements at the interface ServiceList::interfaceName with - minimum version match ServiceList::minVersion properties. This list can be used to + The ServiceFilter element is part of the Qt ServiceFramework API and + provides a list of \l QServiceDesciptor objects at the interface ServiceFilter::interfaceName with + minimum version match ServiceFilter::minVersion properties. This list can be used to select the desired service and instantiate a service object for access via the QMetaObject. This element is a simplified reflection of the QServiceFilter class that provides a list - of simplified QServiceInterfaceDescriptors. Similarly, if the ServiceList::serviceName - and ServiceList::versionMatch are not provided they will respectively default to an empty + of ServiceDescriptors. Similarly, if the ServiceFilter::serviceName + and ServiceFilter::versionMatch are not provided they will respectively default to an empty string with a minimum verison match. - \sa Service + Example: + \code + Item { + ServiceFilter { + id: serviceFilter + interfaceName: "com.qt.nokia.example.interface" + } + ServiceLoader { + serviceDescriptor: serviceFilter.serviceDescriptions[0] //To get the first matching service + } + Repeater{ //To instantiate an object for all matching services. + model: serviceFilter.serviceDescriptions + Item { + ServiceLoader { + serviceDescriptor: modelData + } + } + } + } + \endcode + + \sa ServiceLoader ServiceDescriptor */ -QDeclarativeServiceList::QDeclarativeServiceList() - : m_service(QString()), - m_interface(), - m_major(1), - m_minor(1), - m_match(QDeclarativeServiceList::Minimum), +QDeclarativeServiceFilter::QDeclarativeServiceFilter(QObject* parent) + : QObject(parent), + m_majorVersion(1), // ### Is '1' the correct unset number? + m_minorVersion(0), + m_exactVersionMatching(false), + m_monitorServiceRegistrations(false), + m_serviceManager(0), m_componentComplete(false) { - serviceManager = new QServiceManager(this); } -QDeclarativeServiceList::~QDeclarativeServiceList() +QDeclarativeServiceFilter::~QDeclarativeServiceFilter() { - while (m_services.count()) - delete m_services.takeFirst(); } /*! - \qmlproperty QString ServiceList::serviceName + \qmlproperty QString ServiceFilter::serviceName This property holds the interface name of the services that corresponds to setting QServiceFilter::setService(). */ -void QDeclarativeServiceList::setServiceName(const QString &service) -{ - m_service = service; - updateFilterResults(); - if (m_componentComplete) - emit serviceNameChanged(); -} - -QString QDeclarativeServiceList::serviceName() const -{ - return m_service; -} - /*! - \qmlproperty QString ServiceList::interfaceName + \qmlproperty QString ServiceFilter::interfaceName This property holds the interface name of the services that corresponds to setting QServiceFilter::setInterface(). */ -void QDeclarativeServiceList::setInterfaceName(const QString &interface) -{ - m_interface = interface; - updateFilterResults(); - if (m_componentComplete) - emit interfaceNameChanged(); -} - -QString QDeclarativeServiceList::interfaceName() const -{ - return m_interface; -} /*! - \qmlproperty int ServiceList::majorVersion + \qmlproperty int ServiceFilter::majorVersion This property holds the major version number of the service filter that corresponds to QServiceFilter::majorVersion(). */ -void QDeclarativeServiceList::setMajorVersion(int major) -{ - m_major = major; - updateFilterResults(); - if (m_componentComplete) - emit majorVersionChanged(); -} - -int QDeclarativeServiceList::majorVersion() const -{ - return m_major; -} - /*! - \qmlproperty int ServiceList::minorVersion + \qmlproperty int ServiceFilter::minorVersion This property holds the minor version number of the service filter that corresponds to QServiceFilter::minorVersion(). */ -void QDeclarativeServiceList::setMinorVersion(int minor) -{ - m_minor = minor; - updateFilterResults(); - if (m_componentComplete) - emit minorVersionChanged(); -} - -int QDeclarativeServiceList::minorVersion() const -{ - return m_minor; -} /*! - \qmlproperty int ServiceList::monitorServiceRegistrations + \qmlproperty int ServiceFilter::monitorServiceRegistrations This property controls the behaviour of the list when new services are registered or deregistered. Setting this property to true means the list - will be automatically updated when a service is added or removed. Caution, - your service object will be deleted if the service is unregistered, even if - the service is still running. -*/ + will be automatically updated when a service is added or removed. -void QDeclarativeServiceList::setMonitorServiceRegistrations(bool updates) -{ - if (updates == false) { - disconnect(this, SLOT(servicesAddedRemoved())); - } - else { - connect(serviceManager, SIGNAL(serviceAdded(QString,QService::Scope)), - this, SLOT(servicesAddedRemoved())); - connect(serviceManager, SIGNAL(serviceRemoved(QString,QService::Scope)), - this, SLOT(servicesAddedRemoved())); - } - - if (m_dynamicUpdates != updates) - emit monitorServiceRegistrationsChanged(); - - m_dynamicUpdates = updates; -} - -void QDeclarativeServiceList::servicesAddedRemoved() -{ - // invoke in another event loop run - QMetaObject::invokeMethod(this, "updateServiceList", Qt::QueuedConnection); -} + Continuing to monitor the services can be expensive, so it is recommended + that you only enable this feature if you need it. -bool QDeclarativeServiceList::monitorServiceRegistrations() const -{ - return m_dynamicUpdates; -} + Caution, your service descriptor object will be deleted if the service + is unregistered, even if the service is still running. This is primarily + of note if you are using the serviceDescriptions list as a model with + Service element delegates. +*/ /*! - \qmlproperty enumeration ServiceList::versionMatch + \qmlproperty bool ServiceFilter::versionMatch This property holds the version match rule of the service filter that corresponds to QServiceFilter::versionMatchRule(). Within QML the values - ServiceList.Exact and ServiceList.Minimum correspond to + ServiceFilter.Exact and ServiceFilter.Minimum correspond to QServiceFilter::ExactVersionMatch and QServiceFilter::MinimumVersionMatch respectively. */ -void QDeclarativeServiceList::setVersionMatch(MatchRule match) -{ - m_match = match; - updateFilterResults(); - if (m_componentComplete) - emit versionMatchChanged(); -} -QDeclarativeServiceList::MatchRule QDeclarativeServiceList::versionMatch() const +void QDeclarativeServiceFilter::setMonitorServiceRegistrations(bool updates) { - return m_match; -} - - -void QDeclarativeServiceList::updateServiceList() -{ - if (!m_componentComplete) + if (m_monitorServiceRegistrations == updates) return; - const QString version = QString::number(m_major) + "." + QString::number(m_minor); - - QServiceFilter filter; - - if (!m_service.isEmpty()) - filter.setServiceName(m_service); - - if (m_match == QDeclarativeServiceList::Exact) - filter.setInterface(m_interface, version, QServiceFilter::ExactVersionMatch); - else if (!m_interface.isEmpty()) - filter.setInterface(m_interface, version); - - const QList<QServiceInterfaceDescriptor> newlist = serviceManager->findInterfaces(filter); - - QSet<QServiceInterfaceDescriptor> currentServices = QSet<QServiceInterfaceDescriptor>::fromList(m_currentList); - QSet<QServiceInterfaceDescriptor> newServices = QSet<QServiceInterfaceDescriptor>::fromList(newlist); - - if (currentServices == newServices) { - return; + if (updates == false) { + disconnect(this, SLOT(servicesAddedRemoved())); + if (m_serviceManager) + delete m_serviceManager; + m_serviceManager = 0; + } else { + if (!m_serviceManager) + m_serviceManager = new QServiceManager(this); + connect(m_serviceManager, SIGNAL(serviceAdded(QString,QService::Scope)), + this, SLOT(servicesAddedRemoved())); + connect(m_serviceManager, SIGNAL(serviceRemoved(QString,QService::Scope)), + this, SLOT(servicesAddedRemoved())); } - const QSet<QServiceInterfaceDescriptor> addServices = newServices.subtract(currentServices); - const QSet<QServiceInterfaceDescriptor> delServices = currentServices.subtract( - QSet<QServiceInterfaceDescriptor>::fromList(newlist)); - - foreach (const QServiceInterfaceDescriptor &desc, delServices) { - foreach (QDeclarativeService *service, m_services) { - if (*service == desc) { - m_services.removeOne(service); - delete service; - } - } - m_currentList.removeOne(desc); - } + emit monitorServiceRegistrationsChanged(updates); + m_monitorServiceRegistrations = updates; +} - foreach (const QServiceInterfaceDescriptor &desc, addServices) { - QDeclarativeService *service = new QDeclarativeService(); - service->setInterfaceDesc(desc); - m_services.append(service); - m_currentList.append(desc); - } +void QDeclarativeServiceFilter::servicesAddedRemoved() +{ + // invoke in another event loop run ### Why? + QMetaObject::invokeMethod(this, "updateServiceList", Qt::QueuedConnection); +} - emit resultsChanged(); +QList<QDeclarativeServiceDescriptor> makeDeclarative(QList<QServiceInterfaceDescriptor> in) +{ + QList<QDeclarativeServiceDescriptor> out; + foreach (const QServiceInterfaceDescriptor &d, in) + out << QDeclarativeServiceDescriptor(d); + return out; } -void QDeclarativeServiceList::updateFilterResults() +void QDeclarativeServiceFilter::updateServiceList() { if (!m_componentComplete) return; - const QString version = QString::number(m_major) + "." + QString::number(m_minor); + if (!m_serviceManager) + m_serviceManager = new QServiceManager(this); + const QString version = QString::number(m_majorVersion) + "." + QString::number(m_minorVersion); QServiceFilter filter; - if (!m_service.isEmpty()) - filter.setServiceName(m_service); + if (!m_serviceName.isEmpty()) + filter.setServiceName(m_serviceName); - if (m_match == QDeclarativeServiceList::Exact) - filter.setInterface(m_interface, version, QServiceFilter::ExactVersionMatch); - else if (!m_interface.isEmpty()) - filter.setInterface(m_interface, version); + if (!m_interfaceName.isEmpty()) + filter.setInterface(m_interfaceName, version, m_exactVersionMatching ? + QServiceFilter::ExactVersionMatch : QServiceFilter::MinimumVersionMatch); - QList<QServiceInterfaceDescriptor> list = serviceManager->findInterfaces(filter); + QList<QDeclarativeServiceDescriptor> list = makeDeclarative(m_serviceManager->findInterfaces(filter)); - if (list == m_currentList) { - return; + if (list != m_services) { + m_services = list; + emit serviceDescriptionsChanged(); } - m_currentList = list; - - while (m_services.count()) //for now we refresh the entire list - delete m_services.takeFirst(); - - for (int i = 0; i < list.size(); i++) { - QDeclarativeService *service = new QDeclarativeService(); - service->setInterfaceDesc(list.at(i)); - m_services.append(service); + if (!m_monitorServiceRegistrations) { + delete m_serviceManager; + m_serviceManager = 0; } - emit resultsChanged(); } /*! - \qmlproperty QQmlListProperty ServiceList::services + \qmlproperty QQmlListProperty ServiceFilter::serviceDescriptions - This property holds the list of \l Service elements that match - the Service::interfaceName and minimum Service::versionNumber properties. + This property holds the list of \l ServiceDescriptor objects that match + the ServiceFilter::interfaceName and minimum ServiceFilter::versionNumber properties. */ -QQmlListProperty<QDeclarativeService> QDeclarativeServiceList::services() -{ - return QQmlListProperty<QDeclarativeService>(this, - 0, - s_append, - s_count, - s_at, - s_clear); -} - -void QDeclarativeServiceList::classBegin() -{ -} -void QDeclarativeServiceList::componentComplete() +void QDeclarativeServiceFilter::componentComplete() { - if (!m_componentComplete) { - m_componentComplete = true; - updateFilterResults(); - } -} - -void QDeclarativeServiceList::listUpdated() -{ - if (m_componentComplete) - emit resultsChanged(); + m_componentComplete = true; + updateServiceList(); } -void QDeclarativeServiceList::s_append(QQmlListProperty<QDeclarativeService> *prop, QDeclarativeService *service) +void QDeclarativeServiceFilter::s_append(QQmlListProperty<QDeclarativeServiceDescriptor> *prop, QDeclarativeServiceDescriptor *service) { - QDeclarativeServiceList* list = static_cast<QDeclarativeServiceList*>(prop->object); - list->m_services.append(service); - list->listUpdated(); + QDeclarativeServiceFilter* list = static_cast<QDeclarativeServiceFilter*>(prop->object); + list->m_services.append(*service);//### This does not maintain the reference + list->serviceDescriptionsChanged(); } -int QDeclarativeServiceList::s_count(QQmlListProperty<QDeclarativeService> *prop) +int QDeclarativeServiceFilter::s_count(QQmlListProperty<QDeclarativeServiceDescriptor> *prop) { - return static_cast<QDeclarativeServiceList*>(prop->object)->m_services.count(); + return static_cast<QDeclarativeServiceFilter*>(prop->object)->m_services.count(); } -QDeclarativeService* QDeclarativeServiceList::s_at(QQmlListProperty<QDeclarativeService> *prop, int index) +QDeclarativeServiceDescriptor* QDeclarativeServiceFilter::s_at(QQmlListProperty<QDeclarativeServiceDescriptor> *prop, int index) { - return static_cast<QDeclarativeServiceList*>(prop->object)->m_services[index]; + return &(static_cast<QDeclarativeServiceFilter*>(prop->object)->m_services[index]); } -void QDeclarativeServiceList::s_clear(QQmlListProperty<QDeclarativeService> *prop) +void QDeclarativeServiceFilter::s_clear(QQmlListProperty<QDeclarativeServiceDescriptor> *prop) { - QDeclarativeServiceList* list = static_cast<QDeclarativeServiceList*>(prop->object); - qDeleteAll(list->m_services); + QDeclarativeServiceFilter* list = static_cast<QDeclarativeServiceFilter*>(prop->object); list->m_services.clear(); - list->listUpdated(); + list->serviceDescriptionsChanged(); } #include "moc_qdeclarativeservice_p.cpp" diff --git a/src/imports/serviceframework/qdeclarativeservice_p.h b/src/imports/serviceframework/qdeclarativeservice_p.h index 396fb8d7..e2e0756d 100644 --- a/src/imports/serviceframework/qdeclarativeservice_p.h +++ b/src/imports/serviceframework/qdeclarativeservice_p.h @@ -39,9 +39,8 @@ ** ***************************************************************************/ -#ifndef QDECLARATIVESERVICE_H -#define QDECLARATIVESERVICE_H - +#ifndef QDECLARATIVESERVICE_P_H +#define QDECLARATIVESERVICE_P_H #include <QtCore> #include <qserviceinterfacedescriptor.h> #include <qservicemanager.h> @@ -50,160 +49,309 @@ QT_BEGIN_NAMESPACE -class QDeclarativeService : public QObject, public QQmlParserStatus { +class QDeclarativeServiceDescriptor : public QObject, public QServiceInterfaceDescriptor { + Q_OBJECT + Q_PROPERTY(QString serviceName READ serviceName CONSTANT) + Q_PROPERTY(QString interfaceName READ interfaceName CONSTANT) + Q_PROPERTY(int majorVersion READ majorVersion CONSTANT) + Q_PROPERTY(int minorVersion READ minorVersion CONSTANT) + Q_PROPERTY(bool valid READ isValid CONSTANT) + +public: + QDeclarativeServiceDescriptor(QObject* parent = 0) : QObject(parent) {} + QDeclarativeServiceDescriptor(const QDeclarativeServiceDescriptor& other) + : QObject(0), QServiceInterfaceDescriptor(other) {} + QDeclarativeServiceDescriptor(const QServiceInterfaceDescriptor& other) + : QObject(0), QServiceInterfaceDescriptor(other) {} + bool operator==(const QServiceInterfaceDescriptor& other) const + { return QServiceInterfaceDescriptor::operator==(other); } + QDeclarativeServiceDescriptor& operator=(const QServiceInterfaceDescriptor& other) + { + QServiceInterfaceDescriptor::operator=(other); + return *this; + } + QDeclarativeServiceDescriptor& operator=(const QDeclarativeServiceDescriptor& other) + { + QServiceInterfaceDescriptor::operator=(other); + return *this; + } +}; + +class QDeclarativeServiceLoader : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName NOTIFY interfaceNameChanged) - Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY serviceNameChanged) - Q_PROPERTY(int majorVersion READ majorVersion WRITE setMajorVersion NOTIFY majorVersionChanged) - Q_PROPERTY(int minorVersion READ minorVersion WRITE setMinorVersion NOTIFY minorVersionChanged) - Q_PROPERTY(bool valid READ isValid NOTIFY validChanged) + // ### Rename descriptor? + Q_PROPERTY(QDeclarativeServiceDescriptor* serviceDescriptor READ serviceDescriptor WRITE setServiceDescriptor NOTIFY serviceDescriptorChanged RESET resetServiceDescriptor) //Takes precedence over interfaceName if set + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) + // ### Rename object? Q_PROPERTY(QObject* serviceObject READ serviceObject NOTIFY serviceObjectChanged) - Q_PROPERTY(QString error READ lastError NOTIFY error) + Q_ENUMS(Status) public: - QDeclarativeService(); - ~QDeclarativeService(); - - void setInterfaceDesc(const QServiceInterfaceDescriptor& desc); - QServiceInterfaceDescriptor interfaceDesc() const; - - void setInterfaceName(const QString& interface); - QString interfaceName() const; - QString serviceName() const; - void setServiceName(const QString &service); - int majorVersion() const; - void setMajorVersion(int version); - int minorVersion() const; - void setMinorVersion(int version); - QString lastError() const; - - bool isValid() const; - QObject* serviceObject(); - - //Derived from QQmlParserStatus - virtual void classBegin(); - virtual void componentComplete(); + enum Status { + Null = 0, + Ready, + Loading, + Error + }; - bool operator== ( const QServiceInterfaceDescriptor& other ) const; + QDeclarativeServiceLoader(); + ~QDeclarativeServiceLoader(); + + Q_INVOKABLE QString errorString() const + { + if (m_status == Error) + return m_errorString; + else + return ""; + } + + QString interfaceName() const + { + return m_interfaceName; + } + + QDeclarativeServiceDescriptor* serviceDescriptor() const + { + return m_serviceDescriptor; + } + + void resetServiceDescriptor() + { + setServiceDescriptor(0); + } + + Status status() const + { + return m_status; + } + + bool asynchronous() const + { + return m_asynchronous; + } + + QObject* serviceObject() const + { + return m_serviceObject; + } + +public slots: + void setInterfaceName(QString arg) + { + if (m_interfaceName != arg) { + m_interfaceName = arg; + emit interfaceNameChanged(arg); + if (!m_serviceDescriptor && m_componentComplete) + startLoading(); + } + } + + void setServiceDescriptor(QDeclarativeServiceDescriptor* arg) + { + if (m_serviceDescriptor != arg) { + m_serviceDescriptor = arg; + emit serviceDescriptorChanged(arg); + if (m_componentComplete) + startLoading(); + } + } + + void setAsynchronous(bool arg) + { + if (m_asynchronous != arg) { + m_asynchronous = arg; + emit asynchronousChanged(arg); + } + } -Q_SIGNALS: - void validChanged(); - void serviceObjectChanged(); - void interfaceNameChanged(); - void serviceNameChanged(); - void majorVersionChanged(); - void minorVersionChanged(); +private Q_SLOTS: + void setStatus(Status arg) + { + if (m_status != arg) { + m_status = arg; + emit statusChanged(arg); + } + } + +protected: + virtual void classBegin() {} + virtual void componentComplete(); - void error(const QString &errorString); +signals: + void interfaceNameChanged(QString arg); -private Q_SLOTS: - void IPCFault(QService::UnrecoverableIPCError); + void serviceDescriptorChanged(QServiceInterfaceDescriptor* arg); -private: - void updateDescriptor(); - void setServiceObject(QObject *object); + void statusChanged(Status arg); - QPointer<QObject> m_serviceInstance; - QServiceManager* m_serviceManager; + void asynchronousChanged(bool arg); - QServiceInterfaceDescriptor m_descriptor; + void serviceObjectChanged(QObject* arg); - int m_minor; - int m_major; - QString m_service; - QString m_interface; +private slots: + void startLoading(); + void finishLoading(); + void IPCFault(QService::UnrecoverableIPCError); - QString m_error; +private: + QString m_interfaceName; + QDeclarativeServiceDescriptor* m_serviceDescriptor; + Status m_status; + bool m_asynchronous; + QObject* m_serviceObject; + QString m_errorString; bool m_componentComplete; + QServiceManager* m_serviceManager; + QServiceReply* m_serviceReply; }; - -class QDeclarativeServiceList : public QObject, public QQmlParserStatus { +class QDeclarativeServiceFilter : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY serviceNameChanged) Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName NOTIFY interfaceNameChanged) Q_PROPERTY(int majorVersion READ majorVersion WRITE setMajorVersion NOTIFY majorVersionChanged) Q_PROPERTY(int minorVersion READ minorVersion WRITE setMinorVersion NOTIFY minorVersionChanged) + Q_PROPERTY(bool exactVersionMatching READ exactVersionMatching WRITE setExactVersionMatching NOTIFY exactVersionMatchingChanged) + // ### Rename monitorRegistrations ? Q_PROPERTY(bool monitorServiceRegistrations READ monitorServiceRegistrations WRITE setMonitorServiceRegistrations NOTIFY monitorServiceRegistrationsChanged) - Q_PROPERTY(QQmlListProperty<QDeclarativeService> services READ services NOTIFY resultsChanged) - - Q_PROPERTY(MatchRule versionMatch READ versionMatch WRITE setVersionMatch NOTIFY versionMatchChanged) - Q_ENUMS(MatchRule) - + // ### Rename services ? + Q_PROPERTY(QQmlListProperty<QDeclarativeServiceDescriptor> serviceDescriptions READ serviceDescriptions NOTIFY serviceDescriptionsChanged) public: - enum MatchRule { - Minimum = 0, - Exact - }; - - QDeclarativeServiceList(); - ~QDeclarativeServiceList(); + QDeclarativeServiceFilter(QObject* parent = 0); + ~QDeclarativeServiceFilter(); + QString serviceName() const + { + return m_serviceName; + } + + QString interfaceName() const + { + return m_interfaceName; + } + + int majorVersion() const + { + return m_majorVersion; + } + + int minorVersion() const + { + return m_minorVersion; + } + + bool exactVersionMatching() const + { + return m_exactVersionMatching; + } + + bool monitorServiceRegistrations() const + { + return m_monitorServiceRegistrations; + } + + QQmlListProperty<QDeclarativeServiceDescriptor> serviceDescriptions() + { + return QQmlListProperty<QDeclarativeServiceDescriptor> (this, 0, s_append, s_count, s_at, s_clear); + } + +public slots: + void setServiceName(QString arg) + { + if (m_serviceName != arg) { + m_serviceName = arg; + emit serviceNameChanged(arg); + updateServiceList(); + } + } + + void setInterfaceName(QString arg) + { + if (m_interfaceName != arg) { + m_interfaceName = arg; + emit interfaceNameChanged(arg); + updateServiceList(); + } + } + + void setMajorVersion(int arg) + { + if (m_majorVersion != arg) { + m_majorVersion = arg; + emit majorVersionChanged(arg); + updateServiceList(); + } + } + + void setMinorVersion(int arg) + { + if (m_minorVersion != arg) { + m_minorVersion = arg; + emit minorVersionChanged(arg); + updateServiceList(); + } + } + + void setExactVersionMatching(bool arg) + { + if (m_exactVersionMatching != arg) { + m_exactVersionMatching = arg; + emit exactVersionMatchingChanged(arg); + updateServiceList(); + } + } - QQmlListProperty<QDeclarativeService> services(); - - void setServiceName(const QString& service); - QString serviceName() const; + void setMonitorServiceRegistrations(bool updates); - void setInterfaceName(const QString& interface); - QString interfaceName() const; +protected: + virtual void classBegin() {} + virtual void componentComplete(); +signals: + void serviceNameChanged(QString arg); - void setMinorVersion(int minor); - int minorVersion() const; + void interfaceNameChanged(QString arg); - void setMajorVersion(int major); - int majorVersion() const; + void majorVersionChanged(int arg); - void setMonitorServiceRegistrations(bool updates); - bool monitorServiceRegistrations() const; + void minorVersionChanged(int arg); - void setVersionMatch(QDeclarativeServiceList::MatchRule match); - QDeclarativeServiceList::MatchRule versionMatch() const; + void exactVersionMatchingChanged(bool arg); - void listUpdated(); + void monitorServiceRegistrationsChanged(bool arg); - //Derived from QQmlParserStatus - virtual void classBegin(); - virtual void componentComplete(); + void serviceDescriptionsChanged(); -Q_SIGNALS: - void resultsChanged(); - void servicesChanged(const QQmlListProperty<QDeclarativeService>&); - void serviceNameChanged(); - void interfaceNameChanged(); - void minorVersionChanged(); - void majorVersionChanged(); - void versionMatchChanged(); - void monitorServiceRegistrationsChanged(); - -protected Q_SLOTS: - void servicesAddedRemoved(); - void updateFilterResults(); +private slots: void updateServiceList(); - + void servicesAddedRemoved(); private: - QList<QDeclarativeService *> m_services; - QList<QServiceInterfaceDescriptor> m_currentList; - QServiceManager* serviceManager; - QString m_service; - QString m_interface; - int m_major; - int m_minor; - QDeclarativeServiceList::MatchRule m_match; + QString m_serviceName; + QString m_interfaceName; + int m_majorVersion; + int m_minorVersion; + bool m_exactVersionMatching; + bool m_monitorServiceRegistrations; + QQmlListProperty<QDeclarativeServiceDescriptor*> m_serviceDescriptions; + QList<QDeclarativeServiceDescriptor> m_services; + + QServiceManager* m_serviceManager; bool m_componentComplete; - bool m_dynamicUpdates; - static void s_append(QQmlListProperty<QDeclarativeService> *prop, QDeclarativeService *service); - static int s_count(QQmlListProperty<QDeclarativeService> *prop); - static QDeclarativeService* s_at(QQmlListProperty<QDeclarativeService> *prop, int index); - static void s_clear(QQmlListProperty<QDeclarativeService> *prop); + static void s_append(QQmlListProperty<QDeclarativeServiceDescriptor> *prop, QDeclarativeServiceDescriptor *service); + static int s_count(QQmlListProperty<QDeclarativeServiceDescriptor> *prop); + static QDeclarativeServiceDescriptor* s_at(QQmlListProperty<QDeclarativeServiceDescriptor> *prop, int index); + static void s_clear(QQmlListProperty<QDeclarativeServiceDescriptor> *prop); }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeService); -QML_DECLARE_TYPE(QDeclarativeServiceList); +QML_DECLARE_TYPE(QDeclarativeServiceLoader); +QML_DECLARE_TYPE(QDeclarativeServiceDescriptor); +QML_DECLARE_TYPE(QDeclarativeServiceFilter); + -#endif +#endif // QDECLARATIVESERVICE_P_H diff --git a/src/imports/serviceframework/qdeclarativeserviceold.cpp b/src/imports/serviceframework/qdeclarativeserviceold.cpp new file mode 100644 index 00000000..d36477ea --- /dev/null +++ b/src/imports/serviceframework/qdeclarativeserviceold.cpp @@ -0,0 +1,636 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeserviceold_p.h" + +#include <QQmlEngine> +#include <QQmlInfo> + +QT_BEGIN_NAMESPACE + +/*! + \qmlclass Service QDeclarativeService + + \brief The Service element holds an instance of a service object. + \inherits QObject + + \ingroup qml-serviceframework + + The Service element is part of the Qt ServiceFramework API and + provides a client instance of the service object. This element is a simplified + reflection of the QServiceInterfaceDescriptor class that allows the specification of + the Service::interfaceName to locate the default service implemented at this interface. + + \sa ServiceList +*/ +QDeclarativeService::QDeclarativeService() + : m_serviceInstance(0), m_componentComplete(false) +{ + m_serviceManager = new QServiceManager(); +} + +QDeclarativeService::~QDeclarativeService() +{ + delete m_serviceInstance; +} + +/*! + \qmlproperty bool Service::valid read-only + + This property holds whether a default service was found at the + interface name and corresponds to QServiceInterfaceDescriptor::isValid(). +*/ +bool QDeclarativeService::isValid() const +{ + return m_descriptor.isValid(); +} + +void QDeclarativeService::setInterfaceDesc(const QServiceInterfaceDescriptor &desc) +{ + if (desc == m_descriptor) + return; + + m_descriptor = desc; + + if (m_serviceInstance) + delete m_serviceInstance; + setServiceObject(0); +} + +QServiceInterfaceDescriptor QDeclarativeService::interfaceDesc() const +{ + return m_descriptor; +} + +/*! + \qmlproperty QString Service::interfaceName + + This property holds the interface name of the service that + corresponds to QServiceInterfaceDescriptor::interfaceName(). +*/ +void QDeclarativeService::setInterfaceName(const QString &interface) +{ + m_interface = interface; + updateDescriptor(); +} + +QString QDeclarativeService::interfaceName() const +{ + if (isValid()) + return m_descriptor.interfaceName(); + else + return "No Interface"; +} + +/*! + \qmlproperty QString Service::serviceName + + This property holds the service name of the service that + corresponds to QServiceInterfaceDescriptor::serviceName(). +*/ +QString QDeclarativeService::serviceName() const +{ + if (isValid()) + return m_descriptor.serviceName(); + else + return "No Service"; +} + +void QDeclarativeService::setServiceName(const QString &service) +{ + m_service = service; +} + +/*! + \qmlproperty int Service::majorVersion + + This property holds the major version number of the service that + corresponds to QServiceInterfaceDescriptor::majorVersion(). +*/ +int QDeclarativeService::majorVersion() const +{ + if (isValid()) + return m_descriptor.majorVersion(); + else + return 0; +} + +void QDeclarativeService::setMajorVersion(int version) +{ + m_major = version; + updateDescriptor(); +} + +/*! + \qmlproperty int Service::minorVersion + + This property holds the minor version number of the service that + corresponds to QServiceInterfaceDescriptor::minorVersion(). +*/ +int QDeclarativeService::minorVersion() const +{ + if (isValid()) + return m_descriptor.minorVersion(); + else + return 0; +} + +void QDeclarativeService::setMinorVersion(int version) +{ + m_minor = version; + updateDescriptor(); +} + +/*! + \qmlproperty QObject* Service::serviceObject + + This property holds an instance of the service object which + can be used to make metaobject calls to the service. This + corresponds to QServiceManager::loadInterface(). +*/ +QObject* QDeclarativeService::serviceObject() +{ + if (m_serviceInstance) { + return m_serviceInstance; + } + + if (isValid()) { + QObject *object = m_serviceManager->loadInterface(m_descriptor); + setServiceObject(object); + if (!m_serviceInstance) { + emit error(QLatin1String("Failed to create object")); + return m_serviceInstance; + } + emit serviceObjectChanged(); + connect(m_serviceInstance, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), + this, SLOT(IPCFault(QService::UnrecoverableIPCError))); + m_error.clear(); + return m_serviceInstance; + } else { + return 0; + } +} + +/*! + \qmlproperty QString Service::error + + This property holds the last error the was received, if any + + */ + +QString QDeclarativeService::lastError() const +{ + return m_error; +} + +void QDeclarativeService::IPCFault(QService::UnrecoverableIPCError errorValue) +{ + switch (errorValue) { + default: + case QService::ErrorUnknown: + m_error = QLatin1String("IPC Error: Unkown Error"); + break; + case QService::ErrorServiceNoLongerAvailable: + m_error = QLatin1String("IPC Error: Service no longer available"); + break; + case QService::ErrorOutofMemory: + m_error = QLatin1String("IPC Error: Out of memory"); + break; + case QService::ErrorPermissionDenied: + m_error = QLatin1String("IPC Error: Permission Denied"); + break; + case QService::ErrorInvalidArguments: + m_error = QLatin1String("IPC Error: Invalid Arguments"); + break; + } + emit error(m_error); + m_serviceInstance->deleteLater(); + setServiceObject(0); +} + +void QDeclarativeService::updateDescriptor() +{ + if (!m_componentComplete) + return; + + if (m_interface.isEmpty()) + return; + + QServiceInterfaceDescriptor new_desc; + + if (m_minor == 0 && m_major == 0 && m_service.isEmpty()){ + new_desc = m_serviceManager->interfaceDefault(m_interface); + } + else { + QServiceFilter filter; + if (!m_service.isEmpty()) + filter.setServiceName(m_service); + + + if (m_minor != 0 || m_major != 0) { + const QString version = QString::number(m_major) + "." + QString::number(m_minor); + filter.setInterface(m_interface, version); + } + + QList<QServiceInterfaceDescriptor> list = m_serviceManager->findInterfaces(filter); + if (!list.isEmpty()) + new_desc = list.takeFirst(); + } + + if (new_desc != m_descriptor) { + m_descriptor = new_desc; + if (m_serviceInstance) + emit serviceObjectChanged(); + } + + if (!isValid()) { + qWarning() << "WARNING: No service found for interface name: " << m_interface << m_service << m_major << m_minor; + } +} + +void QDeclarativeService::setServiceObject(QObject *object) +{ + if (m_serviceInstance != object) { + m_serviceInstance = object; + emit serviceObjectChanged(); + } +} + +void QDeclarativeService::classBegin() +{ + +} + +void QDeclarativeService::componentComplete() +{ + m_componentComplete = true; + updateDescriptor(); +} + +bool QDeclarativeService::operator ==(const QServiceInterfaceDescriptor& other ) const +{ + if ( m_descriptor == other) + return true; + + return false; +} + +/*! + \qmlclass ServiceList QDeclarativeServiceList + + \brief The ServiceList element holds a list of \l Service elements. + \inherits QObject + + \ingroup qml-serviceframework + + The ServiceList element is part of the Qt ServiceFramework API and + provides a list of \l Service elements at the interface ServiceList::interfaceName with + minimum version match ServiceList::minVersion properties. This list can be used to + select the desired service and instantiate a service object for access via the QMetaObject. + + This element is a simplified reflection of the QServiceFilter class that provides a list + of simplified QServiceInterfaceDescriptors. Similarly, if the ServiceList::serviceName + and ServiceList::versionMatch are not provided they will respectively default to an empty + string with a minimum verison match. + + \sa Service +*/ +QDeclarativeServiceList::QDeclarativeServiceList() + : m_service(QString()), + m_interface(), + m_major(1), + m_minor(1), + m_match(QDeclarativeServiceList::Minimum), + m_componentComplete(false) +{ + serviceManager = new QServiceManager(this); +} + +QDeclarativeServiceList::~QDeclarativeServiceList() +{ + while (m_services.count()) + delete m_services.takeFirst(); +} +/*! + \qmlproperty QString ServiceList::serviceName + + This property holds the interface name of the services that + corresponds to setting QServiceFilter::setService(). +*/ +void QDeclarativeServiceList::setServiceName(const QString &service) +{ + m_service = service; + updateFilterResults(); + if (m_componentComplete) + emit serviceNameChanged(); +} + +QString QDeclarativeServiceList::serviceName() const +{ + return m_service; +} + +/*! + \qmlproperty QString ServiceList::interfaceName + + This property holds the interface name of the services that + corresponds to setting QServiceFilter::setInterface(). +*/ +void QDeclarativeServiceList::setInterfaceName(const QString &interface) +{ + m_interface = interface; + updateFilterResults(); + if (m_componentComplete) + emit interfaceNameChanged(); +} + +QString QDeclarativeServiceList::interfaceName() const +{ + return m_interface; +} + +/*! + \qmlproperty int ServiceList::majorVersion + + This property holds the major version number of the service filter that + corresponds to QServiceFilter::majorVersion(). +*/ +void QDeclarativeServiceList::setMajorVersion(int major) +{ + m_major = major; + updateFilterResults(); + if (m_componentComplete) + emit majorVersionChanged(); +} + +int QDeclarativeServiceList::majorVersion() const +{ + return m_major; +} + +/*! + \qmlproperty int ServiceList::minorVersion + + This property holds the minor version number of the service filter that + corresponds to QServiceFilter::minorVersion(). +*/ +void QDeclarativeServiceList::setMinorVersion(int minor) +{ + m_minor = minor; + updateFilterResults(); + if (m_componentComplete) + emit minorVersionChanged(); +} + +int QDeclarativeServiceList::minorVersion() const +{ + return m_minor; +} + +/*! + \qmlproperty int ServiceList::monitorServiceRegistrations + + This property controls the behaviour of the list when new services are + registered or deregistered. Setting this property to true means the list + will be automatically updated when a service is added or removed. Caution, + your service object will be deleted if the service is unregistered, even if + the service is still running. +*/ + +void QDeclarativeServiceList::setMonitorServiceRegistrations(bool updates) +{ + if (updates == false) { + disconnect(this, SLOT(servicesAddedRemoved())); + } + else { + connect(serviceManager, SIGNAL(serviceAdded(QString,QService::Scope)), + this, SLOT(servicesAddedRemoved())); + connect(serviceManager, SIGNAL(serviceRemoved(QString,QService::Scope)), + this, SLOT(servicesAddedRemoved())); + } + + if (m_dynamicUpdates != updates) + emit monitorServiceRegistrationsChanged(); + + m_dynamicUpdates = updates; +} + +void QDeclarativeServiceList::servicesAddedRemoved() +{ + // invoke in another event loop run + QMetaObject::invokeMethod(this, "updateServiceList", Qt::QueuedConnection); +} + +bool QDeclarativeServiceList::monitorServiceRegistrations() const +{ + return m_dynamicUpdates; +} + +/*! + \qmlproperty enumeration ServiceList::versionMatch + + This property holds the version match rule of the service filter that + corresponds to QServiceFilter::versionMatchRule(). Within QML the values + ServiceList.Exact and ServiceList.Minimum correspond to + QServiceFilter::ExactVersionMatch and QServiceFilter::MinimumVersionMatch + respectively. +*/ +void QDeclarativeServiceList::setVersionMatch(MatchRule match) +{ + m_match = match; + updateFilterResults(); + if (m_componentComplete) + emit versionMatchChanged(); +} + +QDeclarativeServiceList::MatchRule QDeclarativeServiceList::versionMatch() const +{ + return m_match; +} + + +void QDeclarativeServiceList::updateServiceList() +{ + if (!m_componentComplete) + return; + + const QString version = QString::number(m_major) + "." + QString::number(m_minor); + + QServiceFilter filter; + + if (!m_service.isEmpty()) + filter.setServiceName(m_service); + + if (m_match == QDeclarativeServiceList::Exact) + filter.setInterface(m_interface, version, QServiceFilter::ExactVersionMatch); + else if (!m_interface.isEmpty()) + filter.setInterface(m_interface, version); + + const QList<QServiceInterfaceDescriptor> newlist = serviceManager->findInterfaces(filter); + + QSet<QServiceInterfaceDescriptor> currentServices = QSet<QServiceInterfaceDescriptor>::fromList(m_currentList); + QSet<QServiceInterfaceDescriptor> newServices = QSet<QServiceInterfaceDescriptor>::fromList(newlist); + + if (currentServices == newServices) { + return; + } + + const QSet<QServiceInterfaceDescriptor> addServices = newServices.subtract(currentServices); + const QSet<QServiceInterfaceDescriptor> delServices = currentServices.subtract( + QSet<QServiceInterfaceDescriptor>::fromList(newlist)); + + foreach (const QServiceInterfaceDescriptor &desc, delServices) { + foreach (QDeclarativeService *service, m_services) { + if (*service == desc) { + m_services.removeOne(service); + delete service; + } + } + m_currentList.removeOne(desc); + } + + foreach (const QServiceInterfaceDescriptor &desc, addServices) { + QDeclarativeService *service = new QDeclarativeService(); + service->setInterfaceDesc(desc); + m_services.append(service); + m_currentList.append(desc); + } + + emit resultsChanged(); +} + +void QDeclarativeServiceList::updateFilterResults() +{ + if (!m_componentComplete) + return; + + const QString version = QString::number(m_major) + "." + QString::number(m_minor); + + QServiceFilter filter; + + if (!m_service.isEmpty()) + filter.setServiceName(m_service); + + if (m_match == QDeclarativeServiceList::Exact) + filter.setInterface(m_interface, version, QServiceFilter::ExactVersionMatch); + else if (!m_interface.isEmpty()) + filter.setInterface(m_interface, version); + + QList<QServiceInterfaceDescriptor> list = serviceManager->findInterfaces(filter); + + if (list == m_currentList) { + return; + } + + m_currentList = list; + + while (m_services.count()) //for now we refresh the entire list + delete m_services.takeFirst(); + + for (int i = 0; i < list.size(); i++) { + QDeclarativeService *service = new QDeclarativeService(); + service->setInterfaceDesc(list.at(i)); + m_services.append(service); + } + + emit resultsChanged(); +} + +/*! + \qmlproperty QQmlListProperty ServiceList::services + + This property holds the list of \l Service elements that match + the Service::interfaceName and minimum Service::versionNumber properties. +*/ +QQmlListProperty<QDeclarativeService> QDeclarativeServiceList::services() +{ + return QQmlListProperty<QDeclarativeService>(this, + 0, + s_append, + s_count, + s_at, + s_clear); +} + +void QDeclarativeServiceList::classBegin() +{ +} + +void QDeclarativeServiceList::componentComplete() +{ + if (!m_componentComplete) { + m_componentComplete = true; + updateFilterResults(); + } +} + +void QDeclarativeServiceList::listUpdated() +{ + if (m_componentComplete) + emit resultsChanged(); +} + +void QDeclarativeServiceList::s_append(QQmlListProperty<QDeclarativeService> *prop, QDeclarativeService *service) +{ + QDeclarativeServiceList* list = static_cast<QDeclarativeServiceList*>(prop->object); + list->m_services.append(service); + list->listUpdated(); +} +int QDeclarativeServiceList::s_count(QQmlListProperty<QDeclarativeService> *prop) +{ + return static_cast<QDeclarativeServiceList*>(prop->object)->m_services.count(); +} + +QDeclarativeService* QDeclarativeServiceList::s_at(QQmlListProperty<QDeclarativeService> *prop, int index) +{ + return static_cast<QDeclarativeServiceList*>(prop->object)->m_services[index]; +} + +void QDeclarativeServiceList::s_clear(QQmlListProperty<QDeclarativeService> *prop) +{ + QDeclarativeServiceList* list = static_cast<QDeclarativeServiceList*>(prop->object); + qDeleteAll(list->m_services); + list->m_services.clear(); + list->listUpdated(); +} +#include "moc_qdeclarativeserviceold_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/serviceframework/qdeclarativeserviceold_p.h b/src/imports/serviceframework/qdeclarativeserviceold_p.h new file mode 100644 index 00000000..ee214e31 --- /dev/null +++ b/src/imports/serviceframework/qdeclarativeserviceold_p.h @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +***************************************************************************/ + +#ifndef QDECLARATIVESERVICE_H +#define QDECLARATIVESERVICE_H + +#include <QtCore> +#include <qserviceinterfacedescriptor.h> +#include <qservicemanager.h> +#include <qqml.h> +#include <qqmllist.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeService : public QObject, public QQmlParserStatus { + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName NOTIFY interfaceNameChanged) + Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY serviceNameChanged) + Q_PROPERTY(int majorVersion READ majorVersion WRITE setMajorVersion NOTIFY majorVersionChanged) + Q_PROPERTY(int minorVersion READ minorVersion WRITE setMinorVersion NOTIFY minorVersionChanged) + Q_PROPERTY(bool valid READ isValid NOTIFY validChanged) + Q_PROPERTY(QObject* serviceObject READ serviceObject NOTIFY serviceObjectChanged) + Q_PROPERTY(QString error READ lastError NOTIFY error) + +public: + QDeclarativeService(); + ~QDeclarativeService(); + + void setInterfaceDesc(const QServiceInterfaceDescriptor& desc); + QServiceInterfaceDescriptor interfaceDesc() const; + + void setInterfaceName(const QString& interface); + QString interfaceName() const; + QString serviceName() const; + void setServiceName(const QString &service); + int majorVersion() const; + void setMajorVersion(int version); + int minorVersion() const; + void setMinorVersion(int version); + QString lastError() const; + + bool isValid() const; + QObject* serviceObject(); + + //Derived from QDeclarativeParserStatus + virtual void classBegin(); + virtual void componentComplete(); + + bool operator== ( const QServiceInterfaceDescriptor& other ) const; + +Q_SIGNALS: + void validChanged(); + void serviceObjectChanged(); + void interfaceNameChanged(); + void serviceNameChanged(); + void majorVersionChanged(); + void minorVersionChanged(); + + void error(const QString &errorString); + +private slots: + void IPCFault(QService::UnrecoverableIPCError); + +private: + void updateDescriptor(); + void setServiceObject(QObject *object); + + QPointer<QObject> m_serviceInstance; + QServiceManager* m_serviceManager; + + QServiceInterfaceDescriptor m_descriptor; + + int m_minor; + int m_major; + QString m_service; + QString m_interface; + + QString m_error; + + bool m_componentComplete; +}; + + +class QDeclarativeServiceList : public QObject, public QQmlParserStatus { + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY serviceNameChanged) + Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName NOTIFY interfaceNameChanged) + Q_PROPERTY(int majorVersion READ majorVersion WRITE setMajorVersion NOTIFY majorVersionChanged) + Q_PROPERTY(int minorVersion READ minorVersion WRITE setMinorVersion NOTIFY minorVersionChanged) + Q_PROPERTY(bool monitorServiceRegistrations READ monitorServiceRegistrations WRITE setMonitorServiceRegistrations NOTIFY monitorServiceRegistrationsChanged) + Q_PROPERTY(QQmlListProperty<QDeclarativeService> services READ services NOTIFY resultsChanged) + + Q_PROPERTY(MatchRule versionMatch READ versionMatch WRITE setVersionMatch NOTIFY versionMatchChanged) + Q_ENUMS(MatchRule) + +public: + enum MatchRule { + Minimum = 0, + Exact + }; + + QDeclarativeServiceList(); + ~QDeclarativeServiceList(); + + QQmlListProperty<QDeclarativeService> services(); + + void setServiceName(const QString& service); + QString serviceName() const; + + void setInterfaceName(const QString& interface); + QString interfaceName() const; + + void setMinorVersion(int minor); + int minorVersion() const; + + void setMajorVersion(int major); + int majorVersion() const; + + void setMonitorServiceRegistrations(bool updates); + bool monitorServiceRegistrations() const; + + void setVersionMatch(QDeclarativeServiceList::MatchRule match); + QDeclarativeServiceList::MatchRule versionMatch() const; + + void listUpdated(); + + //Derived from QDeclarativeParserStatus + virtual void classBegin(); + virtual void componentComplete(); + +Q_SIGNALS: + void resultsChanged(); + void servicesChanged(const QQmlListProperty<QDeclarativeService>&); + void serviceNameChanged(); + void interfaceNameChanged(); + void minorVersionChanged(); + void majorVersionChanged(); + void versionMatchChanged(); + void monitorServiceRegistrationsChanged(); + +protected slots: + void servicesAddedRemoved(); + void updateFilterResults(); + void updateServiceList(); + +private: + QList<QDeclarativeService *> m_services; + QList<QServiceInterfaceDescriptor> m_currentList; + QServiceManager* serviceManager; + QString m_service; + QString m_interface; + int m_major; + int m_minor; + QDeclarativeServiceList::MatchRule m_match; + bool m_componentComplete; + bool m_dynamicUpdates; + + static void s_append(QQmlListProperty<QDeclarativeService> *prop, QDeclarativeService *service); + static int s_count(QQmlListProperty<QDeclarativeService> *prop); + static QDeclarativeService* s_at(QQmlListProperty<QDeclarativeService> *prop, int index); + static void s_clear(QQmlListProperty<QDeclarativeService> *prop); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeService); +QML_DECLARE_TYPE(QDeclarativeServiceList); + +#endif diff --git a/src/imports/serviceframework/serviceframework.cpp b/src/imports/serviceframework/serviceframework.cpp index 200a48e5..578944e0 100644 --- a/src/imports/serviceframework/serviceframework.cpp +++ b/src/imports/serviceframework/serviceframework.cpp @@ -43,6 +43,7 @@ #include <QtQml/qqml.h> #include "qdeclarativeservice_p.h" +#include "qdeclarativeserviceold_p.h" QT_BEGIN_NAMESPACE @@ -61,6 +62,11 @@ public: // @uri QtServiceFramework 5.0 + qmlRegisterType<QDeclarativeServiceLoader>(uri, 5, 0, "ServiceLoader"); + qmlRegisterUncreatableType<QDeclarativeServiceDescriptor>(uri, 5, 0, "ServiceDescriptor", "ServiceDescriptor elements must be generated by a ServiceFilter."); + qmlRegisterType<QDeclarativeServiceFilter>(uri, 5, 0, "ServiceFilter"); + + // Old types, scheduled for eventual deprecation qmlRegisterType<QDeclarativeService>(uri, 5, 0, "Service"); qmlRegisterType<QDeclarativeServiceList>(uri, 5, 0, "ServiceList"); } diff --git a/src/imports/serviceframework/serviceframework.pro b/src/imports/serviceframework/serviceframework.pro index 469d3963..09079a23 100644 --- a/src/imports/serviceframework/serviceframework.pro +++ b/src/imports/serviceframework/serviceframework.pro @@ -13,9 +13,11 @@ INSTALLS += qmldir target QT += qml serviceframework -HEADERS += qdeclarativeservice_p.h +HEADERS += qdeclarativeservice_p.h \ + qdeclarativeserviceold_p.h SOURCES += qdeclarativeservice.cpp \ + qdeclarativeserviceold.cpp \ serviceframework.cpp jsondb|contains(QT_CONFIG, jsondb): { |