diff options
author | Alex <qt-info@nokia.com> | 2010-02-24 16:58:30 +1000 |
---|---|---|
committer | Alex <qt-info@nokia.com> | 2010-02-24 16:58:30 +1000 |
commit | b4609876948239178167966de7c611088e4610a7 (patch) | |
tree | dfb5ba6e3a5e63040e729c67e185d36708375664 | |
parent | ab1f9e2f6fc6f4438a01c752b0d21e3c6b4d0d9d (diff) |
add first part of remote property invocation
mostly example and client side handling only
-rw-r--r-- | examples/sfwipcclient/main.cpp | 15 | ||||
-rw-r--r-- | examples/sfwipcservice/main.cpp | 56 | ||||
-rw-r--r-- | src/serviceframework/ipc/objectendpoint.cpp | 88 | ||||
-rw-r--r-- | src/serviceframework/ipc/objectendpoint_p.h | 5 | ||||
-rw-r--r-- | src/serviceframework/ipc/proxyobject.cpp | 44 | ||||
-rw-r--r-- | src/serviceframework/ipc/qservicepackage.cpp | 6 | ||||
-rw-r--r-- | src/serviceframework/ipc/qservicepackage_p.h | 6 |
7 files changed, 199 insertions, 21 deletions
diff --git a/examples/sfwipcclient/main.cpp b/examples/sfwipcclient/main.cpp index 7a2032aa27..1d002bab58 100644 --- a/examples/sfwipcclient/main.cpp +++ b/examples/sfwipcclient/main.cpp @@ -48,9 +48,18 @@ public slots: type = "method"; break; } qDebug() << " " << i << "." << method.signature() << type; - + } + qDebug() << "Properties:" << mo->propertyCount()- mo->propertyOffset() << "(" << mo->propertyCount() << ")"; + for(int i=0; i< mo->propertyCount(); i++) { + QMetaProperty property = mo->property(i); + QString info = "Readable: %1 Resettable: %2 Writeable: %3 Designable: %4 Scriptable: %5 User: %6 Stored: %7 Constant: %8 Final: %9 HasNotify: %10"; + info = info.arg(property.isReadable()).arg(property.isResettable()).arg(property.isWritable()); + info = info.arg(property.isDesignable()).arg(property.isScriptable()).arg(property.isUser()); + info = info.arg(property.isStored()).arg(property.isConstant()).arg(property.isFinal()).arg(property.hasNotifySignal()); + qDebug() << " " << i << "." << property.name() << "Type:" << property.typeName() << info; } + QTimer::singleShot(1000, this, SLOT(useService())); } @@ -138,6 +147,10 @@ public slots: qDebug() << "Triggering signal on client side"; emit clientsignal(); + qDebug() << "^^^^^^^^^^^^^^^^^^^^^^"; + qDebug() << "Property value:" << service->property("value"); + service->setProperty("value", "new value"); + QTimer::singleShot(5000, this, SLOT(killService())); } diff --git a/examples/sfwipcservice/main.cpp b/examples/sfwipcservice/main.cpp index 877062ca91..738cb97f91 100644 --- a/examples/sfwipcservice/main.cpp +++ b/examples/sfwipcservice/main.cpp @@ -16,6 +16,7 @@ class TestService : public QObject { Q_OBJECT Q_SERVICE(TestService, "com.nokia.qt.interface", "3.4") + Q_PROPERTY(QString value READ value WRITE setValue RESET resetValue NOTIFY valueChanged SCRIPTABLE true DESIGNABLE true STORED true); public: TestService(QObject* parent = 0) @@ -23,6 +24,28 @@ public: { } + QString value() + { + qDebug() << "Reading property"; + return m_value; + } + + void setValue(const QString& value) + { + qDebug() << "Writing property"; + m_value = value; + emit valueChanged(m_value); + } + + void resetValue() + { + qDebug() << "Resetting value"; + m_value = "<empty>"; + emit valueChanged(m_value); + } + + + Q_INVOKABLE QString testFunctionWithReturnValue(int input) { qDebug() << "TestService::testFunctionWithReturnValue(" << input << ")"; @@ -49,6 +72,7 @@ public: Q_SIGNALS: void signalWithIntParam(int); void signalWithVariousParam(QVariant,QString,QServiceFilter); + void valueChanged(QString); public slots: Q_INVOKABLE void triggerSignalWithIntParam() @@ -98,14 +122,40 @@ public slots: { qDebug() << "TestService::testSlotWithUnknownArg(const QServiceInterfaceDescriptor& d)"; } +private: + QString m_value; }; class TestService2 : public QObject { Q_OBJECT Q_SERVICE(TestService2, "com.nokia.qt.interface", "3.5") + + Q_PROPERTY(QString value READ value WRITE setValue RESET resetValue NOTIFY valueChanged SCRIPTABLE true DESIGNABLE true STORED true); public: + QString value() + { + qDebug() << "Reading property"; + return m_value; + } + + void setValue(const QString& value) + { + qDebug() << "Writing property"; + m_value = value; + emit valueChanged(m_value); + } + + void resetValue() + { + qDebug() << "Resetting value"; + m_value = "<empty>"; + emit valueChanged(m_value); + } + + + /*Q_INVOKABLE*/ TestService2(QObject* parent = 0) : QObject(parent) { @@ -137,6 +187,7 @@ public: Q_SIGNALS: void signalWithIntParam(int); void signalWithVariousParam(QVariant,QString,QServiceFilter); + void valueChanged(QString); public slots: @@ -187,9 +238,8 @@ public slots: { qDebug() << "TestService2::testSlotWithUnknownArg(const QServiceInterfaceDescriptor& d)"; } -Q_SIGNALS: - //void signalWithIntParam1(int); - //void signalWithIntParam4(int); +private: + QString m_value; }; void unregisterExampleService() diff --git a/src/serviceframework/ipc/objectendpoint.cpp b/src/serviceframework/ipc/objectendpoint.cpp index 677ece52e1..40b4c2bf95 100644 --- a/src/serviceframework/ipc/objectendpoint.cpp +++ b/src/serviceframework/ipc/objectendpoint.cpp @@ -82,7 +82,7 @@ public: protected: void activated( const QList<QVariant>& args ) { - qDebug() << signal() << "emitted."; + //qDebug() << signal() << "emitted."; endPoint->invokeRemote(metaIndex, args, QMetaType::Void); } private: @@ -116,7 +116,6 @@ public: if (method.methodType() == QMetaMethod::Signal) { QByteArray signal = method.signature(); //add '2' for signal - see QSIGNAL_CODE - qDebug() << "creating interceptor"; ServiceSignalIntercepter* intercept = new ServiceSignalIntercepter(service, "2"+signal, parent ); intercept->setMetaIndex(i); @@ -159,6 +158,7 @@ public: //TODO list: /* - Why do we need typeIdent and serviceInstanceId on service side. The instance id should be sufficient. + - Consider merging invokeRemoteProperty() and invokeRemote() */ @@ -245,20 +245,40 @@ void ObjectEndPoint::newPackageReady() case QServicePackage::ObjectCreation: objectRequest(p); break; - case QServicePackage::SignalEmission: case QServicePackage::MethodCall: methodCall(p); break; + case QServicePackage::PropertyCall: + qDebug() << "Property calls not implemented"; + //propertyCall(p); + break; default: qWarning() << "Unknown package type received."; } } } +void ObjectEndPoint::propertyCall(const QServicePackage& /*p*/) +{ + /*if(p.d->responseType == QServicePackage::NotAResponse) { + QByteArray data = p.d->payload.toByteArray(); + QDataStream stream(&data, QIODevice::ReadOnly); + int metaIndex = -1; + QVariantList args; + stream >> metaIndex; + stream >> args; + + QMetaMethod method = service->metaObject()->method(metaIndex); + const bool isSignal = (method.methodType() == QMetaMethod::Signal); + const int returnType = QMetaType::type(method.typeName()); + } else { + }*/ +} + void ObjectEndPoint::objectRequest(const QServicePackage& p) { if (p.d->responseType != QServicePackage::NotAResponse ) { - qDebug() << p; + //qDebug() << p; Response* response = openRequests()->value(p.d->messageId); if (p.d->responseType == QServicePackage::Failed) { response->result = 0; @@ -277,7 +297,7 @@ void ObjectEndPoint::objectRequest(const QServicePackage& p) QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished())); } else { - qDebug() << p; + //qDebug() << p; QServicePackage response = p.createResponse(); InstanceManager* m = InstanceManager::instance(); @@ -316,7 +336,7 @@ void ObjectEndPoint::objectRequest(const QServicePackage& p) void ObjectEndPoint::methodCall(const QServicePackage& p) { if (p.d->responseType == QServicePackage::NotAResponse ) { - qDebug() << p; + //qDebug() << p; QByteArray data = p.d->payload.toByteArray(); QDataStream stream(&data, QIODevice::ReadOnly); int metaIndex = -1; @@ -410,7 +430,7 @@ void ObjectEndPoint::methodCall(const QServicePackage& p) if (!result) qWarning( "%s::%s cannot be called.", service->metaObject()->className(), method.signature()); } else { - qDebug() << p; + //qDebug() << p; Response* response = openRequests()->value(p.d->messageId); if (p.d->responseType == QServicePackage::Failed) { response->result = 0; @@ -429,8 +449,60 @@ void ObjectEndPoint::methodCall(const QServicePackage& p) /*! Will block if return value expected + Handles property calls +*/ +QVariant ObjectEndPoint::invokeRemoteProperty(int metaIndex, const QVariant& arg, int /*returnType*/, QMetaObject::Call c ) +{ + QServicePackage p; + p.d = new QServicePackagePrivate(); + p.d->packageType = QServicePackage::PropertyCall; + p.d->messageId = QUuid::createUuid(); + + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly|QIODevice::Append); + stream << metaIndex << arg; + p.d->payload = data; + + if (c == QMetaObject::ReadProperty) { + //create response and block for answer + Response* response = new Response(); + openRequests()->insert(p.d->messageId, response); + + dispatch->writePackage(p); + waitForResponse(p.d->messageId); + + QVariant result; + QVariant* resultPointer; + if (response->isFinished) { + if (response->result == 0) { + qWarning() << "Request for remote service failed"; + } else { + resultPointer = reinterpret_cast<QVariant* >(response->result); + result = (*resultPointer); + } + } else { + qDebug() << "response passed but not finished"; + } + + openRequests()->take(p.d->messageId); + delete resultPointer; + delete response; + + return result; + + + } else { + dispatch->writePackage(p); + } + + return QVariant(); +} + +/*! + Will block if return value expected + Handles signal/slots */ -QVariant ObjectEndPoint::invokeRemote(int metaIndex, QVariantList args, int returnType) +QVariant ObjectEndPoint::invokeRemote(int metaIndex, const QVariantList& args, int returnType) { QServicePackage p; p.d = new QServicePackagePrivate(); diff --git a/src/serviceframework/ipc/objectendpoint_p.h b/src/serviceframework/ipc/objectendpoint_p.h index 7d58fb7e0e..e9589d4667 100644 --- a/src/serviceframework/ipc/objectendpoint_p.h +++ b/src/serviceframework/ipc/objectendpoint_p.h @@ -66,8 +66,11 @@ public: void objectRequest(const QServicePackage& p); void methodCall(const QServicePackage& p); + void propertyCall(const QServicePackage& p); + + QVariant invokeRemote(int metaIndex, const QVariantList& args, int returnType); + QVariant invokeRemoteProperty(int metaIndex, const QVariant& arg, int returnType, QMetaObject::Call c); - QVariant invokeRemote(int metaIndex, QVariantList args, int returnType); Q_SIGNALS: void pendingRequestFinished(); diff --git a/src/serviceframework/ipc/proxyobject.cpp b/src/serviceframework/ipc/proxyobject.cpp index 1b1394aeab..8aa26e8916 100644 --- a/src/serviceframework/ipc/proxyobject.cpp +++ b/src/serviceframework/ipc/proxyobject.cpp @@ -150,9 +150,49 @@ int QServiceProxy::qt_metacall(QMetaObject::Call c, int id, void **a) if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result; } } - - id-=mcount; + } else if ( c == QMetaObject::ReadProperty + || c == QMetaObject::WriteProperty + || c == QMetaObject::ResetProperty ) { + const int pCount = d->meta->propertyCount() - d->meta->propertyOffset(); + const int metaIndex = id + d->meta->propertyOffset(); + + QMetaProperty property = d->meta->property(metaIndex); + if (property.isValid()) { + int pType = property.type(); + if (pType == QVariant::UserType) + pType = QMetaType::type(property.typeName()); + + QVariant arg; + if ( c == QMetaObject::WriteProperty ) { + if (pType == QVariant::Invalid && QByteArray(property.typeName()) == "QVariant") + arg = *reinterpret_cast<const QVariant(*)>(a[0]); + else if (pType == 0) { + qWarning("%s: property %s has unkown type", property.name(), property.typeName()); + return id; + } else { + arg = QVariant(pType, a[0]); + } + } + + QVariant result; + if (QMetaObject::ReadProperty) + QVariant result = d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c); + else + d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c); + + if (pType != 0) { + QByteArray buffer; + QDataStream stream(&buffer, QIODevice::ReadWrite); + QMetaType::save(stream, pType, result.constData()); + stream.device()->seek(0); + QMetaType::load(stream, pType, a[0]); + } else { + if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result; + } + + } + id-=pCount; } else { //TODO qWarning() << "MetaCall type" << c << "not yet handled"; diff --git a/src/serviceframework/ipc/qservicepackage.cpp b/src/serviceframework/ipc/qservicepackage.cpp index 45f67a159e..fd9faea037 100644 --- a/src/serviceframework/ipc/qservicepackage.cpp +++ b/src/serviceframework/ipc/qservicepackage.cpp @@ -148,15 +148,15 @@ QDebug operator<<(QDebug dbg, const QServicePackage& p) if (p.isValid()) { QString type; switch(p.d->packageType) { - case QServicePackage::SignalEmission: - type = QString("SignalEmission"); - break; case QServicePackage::ObjectCreation: type = QString("ObjectCreation"); break; case QServicePackage::MethodCall: type = QString("MethodCall"); break; + case QServicePackage::PropertyCall: + type = QString("PropertyCall"); + break; default: break; } diff --git a/src/serviceframework/ipc/qservicepackage_p.h b/src/serviceframework/ipc/qservicepackage_p.h index 9a9165528c..bfc2b1bf41 100644 --- a/src/serviceframework/ipc/qservicepackage_p.h +++ b/src/serviceframework/ipc/qservicepackage_p.h @@ -66,9 +66,9 @@ public: ~QServicePackage(); enum Type { - SignalEmission = 0, - ObjectCreation, - MethodCall + ObjectCreation = 0, + MethodCall, + PropertyCall }; enum ResponseType { |