summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex <qt-info@nokia.com>2010-02-24 16:58:30 +1000
committerAlex <qt-info@nokia.com>2010-02-24 16:58:30 +1000
commitb4609876948239178167966de7c611088e4610a7 (patch)
treedfb5ba6e3a5e63040e729c67e185d36708375664
parentab1f9e2f6fc6f4438a01c752b0d21e3c6b4d0d9d (diff)
add first part of remote property invocation
mostly example and client side handling only
-rw-r--r--examples/sfwipcclient/main.cpp15
-rw-r--r--examples/sfwipcservice/main.cpp56
-rw-r--r--src/serviceframework/ipc/objectendpoint.cpp88
-rw-r--r--src/serviceframework/ipc/objectendpoint_p.h5
-rw-r--r--src/serviceframework/ipc/proxyobject.cpp44
-rw-r--r--src/serviceframework/ipc/qservicepackage.cpp6
-rw-r--r--src/serviceframework/ipc/qservicepackage_p.h6
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 {