From 838a740ea6f25108b2bca922a1f1ea9d90b64ec2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 2 May 2006 14:00:27 +0000 Subject: * qt/dbusidl2cpp.cpp: There's no callAsync. Use the correct call (r535506) * qt/dbusidl2cpp.cpp: * qt/qdbusabstractadaptor.cpp: * qt/qdbusabstractadaptor.h: Make QDBusAdaptorConnector be a sibling of the QDBusAbstractAdaptor objects instead of the parent. (r535848) * qt/dbusidl2cpp.cpp: * qt/qdbusabstractinterface.cpp: * qt/qdbusabstractinterface.h: * qt/qdbusabstractinterface_p.h: * qt/qdbusinterface.cpp: Make properties in interfaces actually work. The code that was generated would not compile, due to moc calls to functions that did not exist. They now shall. (r536571) --- qt/dbusidl2cpp.cpp | 112 +++++++++++++++++++++++++++--------------- qt/qdbusabstractadaptor.cpp | 40 +++++++-------- qt/qdbusabstractadaptor.h | 2 +- qt/qdbusabstractinterface.cpp | 88 +++++++++++++++++++++++++++++++++ qt/qdbusabstractinterface.h | 2 + qt/qdbusabstractinterface_p.h | 6 ++- qt/qdbusinterface.cpp | 70 +++++--------------------- 7 files changed, 199 insertions(+), 121 deletions(-) (limited to 'qt') diff --git a/qt/dbusidl2cpp.cpp b/qt/dbusidl2cpp.cpp index eb1a1b1e..8097a075 100644 --- a/qt/dbusidl2cpp.cpp +++ b/qt/dbusidl2cpp.cpp @@ -37,7 +37,7 @@ #include "qdbusintrospection_p.h" #define PROGRAMNAME "dbusidl2cpp" -#define PROGRAMVERSION "0.3" +#define PROGRAMVERSION "0.4" #define PROGRAMCOPYRIGHT "Copyright (C) 2006 Trolltech AS. All rights reserved." #define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" @@ -344,6 +344,26 @@ static void writeArgList(QTextStream &ts, const QStringList &argNames, } } +static QString propertyGetter(const QDBusIntrospection::Property &property) +{ + QString getter = property.annotations.value("com.trolltech.QtDBus.propertyGetter"); + if (getter.isEmpty()) { + getter = property.name; + getter[0] = getter[0].toLower(); + } + return getter; +} + +static QString propertySetter(const QDBusIntrospection::Property &property) +{ + QString setter = property.annotations.value("com.trolltech.QtDBus.propertySetter"); + if (setter.isEmpty()) { + setter = "set" + property.name; + setter[3] = setter[3].toUpper(); + } + return setter; +} + static QString stringify(const QString &data) { QString retval; @@ -425,31 +445,6 @@ static void writeProxy(const char *proxyFile, const QDBusIntrospection::Interfac << "{" << endl << " Q_OBJECT" << endl; - // properties: - foreach (const QDBusIntrospection::Property &property, interface->properties) { - QByteArray type = qtTypeName(property.type); - QString templateType = templateArg(type); - QString constRefType = constRefArg(type); - QString getter = property.name; - QString setter = "set" + property.name; - getter[0] = getter[0].toLower(); - setter[3] = setter[3].toUpper(); - - hs << " Q_PROPERTY(" << type << " " << property.name; - - // getter: - if (property.access != QDBusIntrospection::Property::Write) - // it's readble - hs << " READ" << getter; - - // setter - if (property.access != QDBusIntrospection::Property::Read) - // it's writeable - hs << " WRITE" << setter; - - hs << ")" << endl; - } - // the interface name hs << "public:" << endl << " static inline const char *staticInterfaceName()" << endl @@ -472,9 +467,50 @@ static void writeProxy(const char *proxyFile, const QDBusIntrospection::Interfac << "}" << endl << endl; + // properties: + foreach (const QDBusIntrospection::Property &property, interface->properties) { + QByteArray type = qtTypeName(property.type); + QString templateType = templateArg(type); + QString constRefType = constRefArg(type); + QString getter = propertyGetter(property); + QString setter = propertySetter(property); + + hs << " Q_PROPERTY(" << type << " " << property.name; + + // getter: + if (property.access != QDBusIntrospection::Property::Write) + // it's readble + hs << " READ " << getter; + + // setter + if (property.access != QDBusIntrospection::Property::Read) + // it's writeable + hs << " WRITE " << setter; + + hs << ")" << endl; + + // getter: + if (property.access != QDBusIntrospection::Property::Write) { + hs << " inline " << type << " " << getter << "() const" << endl; + if (type != "QVariant") + hs << " { return qvariant_cast< " << type << " >(internalPropGet(\"" + << property.name << "\")); }" << endl; + else + hs << " { return internalPropGet(\"" << property.name << "\"); }" << endl; + } + + // setter: + if (property.access != QDBusIntrospection::Property::Read) { + hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl + << " { internalPropSet(\"" << property.name + << "\", qVariantFromValue(value)); }" << endl; + } + + hs << endl; + } // methods: - hs << "public slots: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << endl; foreach (const QDBusIntrospection::Method &method, interface->methods) { bool isAsync = method.annotations.value(ANNOTATION_NO_WAIT) == "true"; if (isAsync && !method.outputArgs.isEmpty()) { @@ -544,7 +580,7 @@ static void writeProxy(const char *proxyFile, const QDBusIntrospection::Interfac << endl; } - hs << "signals: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << endl; foreach (const QDBusIntrospection::Signal &signal, interface->signals_) { hs << " "; if (signal.annotations.value("org.freedesktop.DBus.Deprecated") == "true") @@ -720,12 +756,10 @@ static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Inte foreach (const QDBusIntrospection::Property &property, interface->properties) { QByteArray type = qtTypeName(property.type); QString constRefType = constRefArg(type); - QString getter = property.name; - QString setter = "set" + property.name; - getter[0] = getter[0].toLower(); - setter[3] = setter[3].toUpper(); + QString getter = propertyGetter(property); + QString setter = propertySetter(property); - hs << " Q_PROPERTY(" << type << " " << property.name; + hs << " Q_PROPERTY(" << type << " " << property.name; if (property.access != QDBusIntrospection::Property::Write) hs << " READ " << getter; if (property.access != QDBusIntrospection::Property::Read) @@ -739,7 +773,7 @@ static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Inte << className << "::" << getter << "() const" << endl << "{" << endl << " // get the value of property " << property.name << endl - << " return qvariant_cast< " << type <<" >(object()->property(\"" << getter << "\"));" << endl + << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl << "}" << endl << endl; } @@ -750,7 +784,7 @@ static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Inte cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl << "{" << endl << " // set the value of property " << property.name << endl - << " object()->setProperty(\"" << getter << "\", value);" << endl + << " parent()->setProperty(\"" << property.name << "\", value);" << endl << "}" << endl << endl; } @@ -758,7 +792,7 @@ static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Inte hs << endl; } - hs << "public slots: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << endl; foreach (const QDBusIntrospection::Method &method, interface->methods) { bool isAsync = method.annotations.value(ANNOTATION_NO_WAIT) == "true"; if (isAsync && !method.outputArgs.isEmpty()) { @@ -805,7 +839,7 @@ static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Inte // make the call if (method.inputArgs.count() <= 10 && method.outputArgs.count() <= 1) { // we can use QMetaObject::invokeMethod - static const char invoke[] = " QMetaObject::invokeMethod(object(), \""; + static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; cs << invoke << name << "\""; if (!method.outputArgs.isEmpty()) @@ -830,7 +864,7 @@ static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Inte << " //"; if (!method.outputArgs.isEmpty()) cs << argNames.at(method.inputArgs.count()) << " = "; - cs << "static_cast(object())->" << name << "("; + cs << "static_cast(parent())->" << name << "("; int argPos = 0; bool first = true; @@ -851,7 +885,7 @@ static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Inte << endl; } - hs << "signals: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << endl; foreach (const QDBusIntrospection::Signal &signal, interface->signals_) { hs << " "; if (signal.annotations.value("org.freedesktop.DBus.Deprecated") == "true") diff --git a/qt/qdbusabstractadaptor.cpp b/qt/qdbusabstractadaptor.cpp index e2ab0964..2794293d 100644 --- a/qt/qdbusabstractadaptor.cpp +++ b/qt/qdbusabstractadaptor.cpp @@ -51,12 +51,7 @@ Q_GLOBAL_STATIC(QDBusAdaptorInit, qAdaptorInit) QDBusAdaptorConnector *qDBusFindAdaptorConnector(QObject *obj) { - qAdaptorInit(); - -#if 0 - if (caller->metaObject() == QDBusAdaptorConnector::staticMetaObject) - return 0; // it's a QDBusAdaptorConnector -#endif + (void)qAdaptorInit(); if (!obj) return 0; @@ -66,9 +61,14 @@ QDBusAdaptorConnector *qDBusFindAdaptorConnector(QObject *obj) return connector; } +QDBusAdaptorConnector *qDBusFindAdaptorConnector(QDBusAbstractAdaptor *adaptor) +{ + return qDBusFindAdaptorConnector(adaptor->parent()); +} + QDBusAdaptorConnector *qDBusCreateAdaptorConnector(QObject *obj) { - qAdaptorInit(); + (void)qAdaptorInit(); QDBusAdaptorConnector *connector = qDBusFindAdaptorConnector(obj); if (connector) @@ -122,15 +122,11 @@ void QDBusAbstractAdaptorPrivate::saveIntrospectionXml(QDBusAbstractAdaptor *ada /*! Constructs a QDBusAbstractAdaptor with \a parent as the object we refer to. - - \warning Use object() to retrieve the object passed as \a parent to this constructor. The real - parent object (as retrieved by QObject::parent()) may be something else. */ QDBusAbstractAdaptor::QDBusAbstractAdaptor(QObject* parent) - : d(new QDBusAbstractAdaptorPrivate) + : QObject(parent), d(new QDBusAbstractAdaptorPrivate) { QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(parent); - setParent(connector); connector->waitingForPolish = true; QTimer::singleShot(0, connector, SLOT(polish())); @@ -153,7 +149,7 @@ QDBusAbstractAdaptor::~QDBusAbstractAdaptor() */ QObject* QDBusAbstractAdaptor::object() const { - return parent()->parent(); + return parent(); } /*! @@ -167,7 +163,7 @@ QObject* QDBusAbstractAdaptor::object() const void QDBusAbstractAdaptor::setAutoRelaySignals(bool enable) { const QMetaObject *us = metaObject(); - const QMetaObject *them = object()->metaObject(); + const QMetaObject *them = parent()->metaObject(); for (int idx = staticMetaObject.methodCount(); idx < us->methodCount(); ++idx) { QMetaMethod mm = us->method(idx); @@ -179,9 +175,9 @@ void QDBusAbstractAdaptor::setAutoRelaySignals(bool enable) if (them->indexOfSignal(sig) == -1) continue; sig.prepend(QSIGNAL_CODE + '0'); - object()->disconnect(sig, this, sig); + parent()->disconnect(sig, this, sig); if (enable) - connect(object(), sig, sig); + connect(parent(), sig, sig); } } @@ -274,7 +270,7 @@ void QDBusAdaptorConnector::relay(QObject *sender) qWarning("Inconsistency detected: QDBusAdaptorConnector::relay got called with unexpected sender object!"); } else { QMetaMethod mm = senderMetaObject->method(lastSignalIdx); - QObject *object = static_cast(sender)->object(); + QObject *object = static_cast(sender)->parent(); // break down the parameter list QList types; @@ -316,8 +312,9 @@ void QDBusAdaptorConnector::relay(QObject *sender) void QDBusAdaptorConnector::signalBeginCallback(QObject *caller, int method_index, void **argv) { - QDBusAdaptorConnector *data = qobject_cast(caller->parent()); - if (data) { + QDBusAbstractAdaptor *adaptor = qobject_cast(caller); + if (adaptor) { + QDBusAdaptorConnector *data = qDBusFindAdaptorConnector(adaptor); data->lastSignalIdx = method_index; data->argv = argv; data->senderMetaObject = caller->metaObject(); @@ -327,8 +324,9 @@ void QDBusAdaptorConnector::signalBeginCallback(QObject *caller, int method_inde void QDBusAdaptorConnector::signalEndCallback(QObject *caller, int) { - QDBusAdaptorConnector *data = qobject_cast(caller->parent()); - if (data) { + QDBusAbstractAdaptor *adaptor = qobject_cast(caller); + if (adaptor) { + QDBusAdaptorConnector *data = qDBusFindAdaptorConnector(adaptor); data->lastSignalIdx = 0; data->argv = 0; data->senderMetaObject = 0; diff --git a/qt/qdbusabstractadaptor.h b/qt/qdbusabstractadaptor.h index cc85a891..16fbf5d9 100644 --- a/qt/qdbusabstractadaptor.h +++ b/qt/qdbusabstractadaptor.h @@ -37,7 +37,7 @@ protected: public: ~QDBusAbstractAdaptor(); - QObject *object() const; + Q_DECL_DEPRECATED QObject *object() const; protected: void setAutoRelaySignals(bool enable); diff --git a/qt/qdbusabstractinterface.cpp b/qt/qdbusabstractinterface.cpp index eec373a3..7c09b510 100644 --- a/qt/qdbusabstractinterface.cpp +++ b/qt/qdbusabstractinterface.cpp @@ -28,6 +28,60 @@ #include "qdbusmetaobject_p.h" #include "qdbusconnection_p.h" +QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const +{ + // try to read this property + QDBusMessage msg = QDBusMessage::methodCall(service, path, DBUS_INTERFACE_PROPERTIES, + QLatin1String("Get")); + msg << interface << QString::fromUtf8(mp.name()); + QDBusMessage reply = connp->sendWithReply(msg, QDBusConnection::NoUseEventLoop); + + if (reply.type() == QDBusMessage::ReplyMessage && reply.count() == 1 && + reply.signature() == QLatin1String("v")) { + QVariant value = QDBusTypeHelper::fromVariant(reply.at(0)); + + // make sure the type is right + if (qstrcmp(mp.typeName(), value.typeName()) == 0) { + if (mp.type() == QVariant::LastType) + // QVariant is special in this context + return QDBusTypeHelper::fromVariant(value); + + return value; + } + } + + // there was an error... + if (reply.type() == QDBusMessage::ErrorMessage) + lastError = reply; + else if (reply.signature() != QLatin1String("v")) { + QString errmsg = QLatin1String("Invalid signature `%1' in return from call to " + DBUS_INTERFACE_PROPERTIES); + lastError = QDBusError(QDBusError::InvalidSignature, errmsg.arg(reply.signature())); + } else { + QString errmsg = QLatin1String("Unexpected type `%1' when retrieving property " + "`%2 %3.%4'"); + lastError = QDBusError(QDBusError::InvalidSignature, + errmsg.arg(QLatin1String(reply.at(0).typeName()), + QLatin1String(mp.typeName()), + interface, QString::fromUtf8(mp.name()))); + } + + return QVariant(); +} + +void QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) +{ + // send the value + QDBusMessage msg = QDBusMessage::methodCall(service, path, DBUS_INTERFACE_PROPERTIES, + QLatin1String("Set")); + msg.setSignature(QLatin1String("ssv")); + msg << interface << QString::fromUtf8(mp.name()) << value; + QDBusMessage reply = connp->sendWithReply(msg, QDBusConnection::NoUseEventLoop); + + if (reply.type() != QDBusMessage::ReplyMessage) + lastError = reply; +} + /*! \class QDBusAbstractInterface \brief Base class for all D-Bus interfaces in the QtDBus binding, allowing access to remote interfaces. @@ -246,6 +300,40 @@ void QDBusAbstractInterface::disconnectNotify(const char *signal) d->connp->disconnectRelay(d->service, d->path, d->interface, this, signal); } +/*! + \internal + Get the value of the property \a propname. +*/ +QVariant QDBusAbstractInterface::internalPropGet(const char *propname) const +{ + // assume this property exists and is readable + // we're only called from generated code anyways + + int idx = metaObject()->indexOfProperty(propname); + if (idx != -1) + return d_func()->property(metaObject()->property(idx)); + qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname); + return QVariant(); // error +} + +/*! + \internal + Set the value of the property \a propname to \a value. +*/ +void QDBusAbstractInterface::internalPropSet(const char *propname, const QVariant &value) +{ + Q_D(QDBusAbstractInterface); + + // assume this property exists and is writeable + // we're only called from generated code anyways + + int idx = metaObject()->indexOfProperty(propname); + if (idx != -1) + d->setProperty(metaObject()->property(idx), value); + else + qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname); +} + /*! \overload \fn QDBusMessage QDBusAbstractInterface::call(const QString &method) diff --git a/qt/qdbusabstractinterface.h b/qt/qdbusabstractinterface.h index 23f928a2..1ad1a532 100644 --- a/qt/qdbusabstractinterface.h +++ b/qt/qdbusabstractinterface.h @@ -242,6 +242,8 @@ protected: QDBusAbstractInterface(QDBusAbstractInterfacePrivate *); void connectNotify(const char *signal); void disconnectNotify(const char *signal); + QVariant internalPropGet(const char *propname) const; + void internalPropSet(const char *propname, const QVariant &value); private: friend class QDBusInterface; diff --git a/qt/qdbusabstractinterface_p.h b/qt/qdbusabstractinterface_p.h index 8f4d8dc3..43807071 100644 --- a/qt/qdbusabstractinterface_p.h +++ b/qt/qdbusabstractinterface_p.h @@ -54,7 +54,7 @@ public: QString service; QString path; QString interface; - QDBusError lastError; + mutable QDBusError lastError; bool isValid; inline QDBusAbstractInterfacePrivate(const QDBusConnection& con, QDBusConnectionPrivate *conp, @@ -62,6 +62,10 @@ public: : conn(con), connp(conp), service(serv), path(p), interface(iface), isValid(true) { } virtual ~QDBusAbstractInterfacePrivate() { } + + // these functions do not check if the property is valid + QVariant property(const QMetaProperty &mp) const; + void setProperty(const QMetaProperty &mp, const QVariant &value); }; diff --git a/qt/qdbusinterface.cpp b/qt/qdbusinterface.cpp index 48b1011c..0afa452b 100644 --- a/qt/qdbusinterface.cpp +++ b/qt/qdbusinterface.cpp @@ -180,72 +180,24 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv) if (!mp.isReadable()) return -1; // don't read - // try to read this property - QDBusMessage msg = QDBusMessage::methodCall(service, path, DBUS_INTERFACE_PROPERTIES, - QLatin1String("Get")); - msg << interface << QString::fromUtf8(mp.name()); - - QPointer qq = q; - QDBusMessage reply = connp->sendWithReply(msg, QDBusConnection::UseEventLoop); - - // access to "this" or to "q" below this point must check for "qq" - // we may have been deleted! - - if (reply.type() == QDBusMessage::ReplyMessage && reply.count() == 1 && - reply.signature() == QLatin1String("v")) { - QVariant value = QDBusTypeHelper::fromVariant(reply.at(0)); - - // make sure the type is right - if (strcmp(mp.typeName(), value.typeName()) == 0) { - if (mp.type() == QVariant::LastType) - // QVariant is special in this context - *reinterpret_cast(argv[0]) = value; - else - QDBusMetaObject::assign(argv[0], value); - return -1; - } - } - - // got an error - if (qq.isNull()) - return -1; // bail out + QVariant value = property(mp); + if (value.type() == QVariant::Invalid) + // an error occurred -- property already set lastError + return -1; + else if (mp.type() == QVariant::LastType) + // QVariant is special in this context + *reinterpret_cast(argv[0]) = value; + else + QDBusMetaObject::assign(argv[0], value); - if (reply.type() == QDBusMessage::ErrorMessage) - lastError = reply; - else if (reply.signature() != QLatin1String("v")) { - QString errmsg = QLatin1String("Invalid signature `%1' in return from call to " - DBUS_INTERFACE_PROPERTIES); - lastError = QDBusError(QDBusError::InvalidSignature, errmsg.arg(reply.signature())); - } else { - QString errmsg = QLatin1String("Unexpected type `%1' when retrieving property " - "`%2 %3.%4'"); - lastError = QDBusError(QDBusError::InvalidSignature, - errmsg.arg(QLatin1String(reply.at(0).typeName()), - QLatin1String(mp.typeName()), - interface, QString::fromUtf8(mp.name()))); - } - return -1; + return -1; // handled } else if (c == QMetaObject::WriteProperty) { // QMetaProperty::write has already checked that we're writable // it has also checked that the type is right QVariant value(metaObject->propertyMetaType(id), argv[0]); QMetaProperty mp = metaObject->property(id + metaObject->propertyOffset()); - // send the value - QDBusMessage msg = QDBusMessage::methodCall(service, path, DBUS_INTERFACE_PROPERTIES, - QLatin1String("Set")); - msg.setSignature(QLatin1String("ssv")); - msg << interface << QString::fromUtf8(mp.name()) << value; - - QPointer qq = q; - QDBusMessage reply = connp->sendWithReply(msg, QDBusConnection::UseEventLoop); - - // access to "this" or to "q" below this point must check for "qq" - // we may have been deleted! - - if (!qq.isNull() && reply.type() != QDBusMessage::ReplyMessage) - lastError = reply; - + setProperty(mp, value); return -1; } return id; -- cgit