Service Browser ExampleThis example demonstrates how Service Framework can register and search for services and interfaces. This example shows how to use the Service Framework to:
The application window is split into three panes. The top-left pane shows all the services that are registered within the Service Framework. The bottom-left pane shows the interfaces implemented by the service selected in the top-left pane. Each entry in this list shows:
The right-hand pane shows the attributes of an interface implementation that are invokable through the Qt meta-object system. Such attributes include signals, slots, properties and methods marked with the Q_INVOKABLE macro. If the "Selected implementation" radio button is checked, this view shows the attributes of the selected implementation in the bottom-left pane; otherwise, it shows the attributes of the default implementation for the interface of the selected implementation. ServiceBrowser Class DefinitionThe ServiceBrowser class inherits from QWidget. It has several slots for reloading the lists in the three information panes, and for changing the default implementation for an interface. class ServiceBrowser : public QWidget { Q_OBJECT public: ServiceBrowser(QWidget *parent = 0, Qt::WindowFlags flags = 0); ~ServiceBrowser(); private slots: void currentInterfaceImplChanged(QListWidgetItem *current, QListWidgetItem *previous); void reloadServicesList(); void reloadInterfaceImplementationsList(); void reloadAttributesList(); void setDefaultInterfaceImplementation(); void handleImplementationReply(); private: ... }; ServiceBrowser Class ImplementationServiceBrowser::ServiceBrowser(QWidget *parent, Qt::WindowFlags flags) : QWidget(parent, flags) { serviceManager = new QServiceManager(this); systemManager = new QServiceManager(QService::SystemScope); registerExampleServices(); initWidgets(); reloadServicesList(); setWindowTitle(tr("Services Browser")); } The constructor registers the projects in the examples/ directory. It also calls reloadServicesList() to show these two newly registered services in the top-left pane. void ServiceBrowser::reloadServicesList() { servicesListWidget->clear(); QSet<QString> services; QList<QServiceInterfaceDescriptor> descriptors = serviceManager->findInterfaces(); for (int i=0; i<descriptors.count(); i++) { QString service = descriptors[i].serviceName(); if (descriptors[i].scope() == QService::SystemScope) service += tr(" (system)"); services << service; } When the services list in the top-left pane needs to be refreshed, we call QServiceManager::findServices() to get a QStringList of all services that are currently registered with the service framework. void ServiceBrowser::reloadInterfaceImplementationsList() { ... ... QList<QServiceInterfaceDescriptor> descriptors = manager->findInterfaces(serviceName); attributesListWidget->clear(); interfacesListWidget->clear(); for (int i=0; i<descriptors.count(); i++) { if (descriptors[i].scope() != manager->scope() && !serviceName.isEmpty()) continue; QString text = QString("%1 %2.%3") .arg(descriptors[i].interfaceName()) .arg(descriptors[i].majorVersion()) .arg(descriptors[i].minorVersion()); QServiceInterfaceDescriptor defaultInterfaceImpl = manager->interfaceDefault(descriptors[i].interfaceName()); if (serviceName.isEmpty()) { text += " (" + descriptors[i].serviceName() + ")"; if (descriptors[i].scope() == QService::SystemScope) { text += tr(" (system"); defaultInterfaceImpl = systemManager->interfaceDefault(descriptors[i].interfaceName()); if (descriptors[i] == defaultInterfaceImpl) text += tr(" default)"); else text += ")"; defaultInterfaceImpl = QServiceInterfaceDescriptor(); } ... } To create the list of interface implementations in the bottom-left pane, we call QServiceManager::findInterfaces() to get a list of QServiceInterfaceDescriptor objects. If a particular service has been selected in the top-left pane, we call QServiceManager::findInterfaces() with the name of that service as the argument, so that it will only return the interface implementations provided by that service. Otherwise, it is called with no argument to retrieve a list of all implementations provided by all registered services. The example maps each entry in the interface implementations list to its corresponding QServiceInterfaceDescriptor object using the QListWidgetItem::setData() method. Note how we also call QServiceManager::defaultServiceInterface() to determine whether an interface implementation is the default for that interface. void ServiceBrowser::reloadAttributesList() { QListWidgetItem *item = interfacesListWidget->currentItem(); if (!item) return; QServiceInterfaceDescriptor selectedImpl = item->data(Qt::UserRole).value<QServiceInterfaceDescriptor>(); QServiceReply *reply = 0; if (selectedImplRadioButton->isChecked()) reply = serviceManager->loadInterfaceRequest(selectedImpl); else reply = serviceManager->loadInterfaceRequest(selectedImpl.interfaceName()); connect(reply, SIGNAL(finished()), this, SLOT(handleImplementationReply())); } void ServiceBrowser::handleImplementationReply() { QServiceReply *reply = static_cast< QServiceReply * >(sender()); QObject *implementationRef = reply->proxyObject(); ... The reloadAttributesList() method creates the list in the right-hand pane that shows the attributes of an interface implementation that can be invoked through the Qt meta-object system. QServiceManager::loadInterface() is called to get an instance of the identified interface implementation. This method finds the corresponding service plugin and returns the QObject instance provided by the service plugin's QServicePluginInterface::createInstance() method. ... const QMetaObject *metaObject = implementationRef->metaObject(); attributesGroup->setTitle(tr("Invokable attributes for %1 class") .arg(QString(metaObject->className()))); for (int i=0; i<metaObject->methodCount(); i++) { QMetaMethod method = metaObject->method(i); attributesListWidget->addItem("[METHOD] " + QString(method.methodSignature())); } for (int i=0; i<metaObject->propertyCount(); i++) { QMetaProperty property = metaObject->property(i); attributesListWidget->addItem("[PROPERTY] " + QString(property.name())); } } Call QObject::metaObject() on the implementation instance to get a QMetaObject instance that reveals the dynamically invokable attributes for the instance. These attributes include properties, signals, slots, and methods marked with the Q_INVOKABLE macro. Call QMetaObject::method() to get information about a signal, slot or invokable method, and QMetaObject::property() to access a property of the instance. When you know the name of the method you wish to invoke, call QMetaObject::invoke() or QMetaMethod::invoke() to invoke it dynamically. Similarly, QMetaProperty::read() and QMetaProperty::write() can be used to read and modify the value of a property. Files: |