+2006-05-02 Thiago Macieira <thiago.macieira@trolltech.com>
+
+ * 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)
+
2006-04-30 Thiago Macieira <thiago.macieira@trolltech.com>
* Makefile.am:
#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"
}
}
+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;
<< "{" << 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
<< "}" << 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()) {
<< 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")
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)
<< 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;
}
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;
}
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()) {
// 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())
<< " //";
if (!method.outputArgs.isEmpty())
cs << argNames.at(method.inputArgs.count()) << " = ";
- cs << "static_cast<YourObjectType *>(object())->" << name << "(";
+ cs << "static_cast<YourObjectType *>(parent())->" << name << "(";
int argPos = 0;
bool first = true;
<< 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")
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;
return connector;
}
+QDBusAdaptorConnector *qDBusFindAdaptorConnector(QDBusAbstractAdaptor *adaptor)
+{
+ return qDBusFindAdaptorConnector(adaptor->parent());
+}
+
QDBusAdaptorConnector *qDBusCreateAdaptorConnector(QObject *obj)
{
- qAdaptorInit();
+ (void)qAdaptorInit();
QDBusAdaptorConnector *connector = qDBusFindAdaptorConnector(obj);
if (connector)
/*!
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()));
*/
QObject* QDBusAbstractAdaptor::object() const
{
- return parent()->parent();
+ return parent();
}
/*!
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);
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);
}
}
qWarning("Inconsistency detected: QDBusAdaptorConnector::relay got called with unexpected sender object!");
} else {
QMetaMethod mm = senderMetaObject->method(lastSignalIdx);
- QObject *object = static_cast<QDBusAbstractAdaptor *>(sender)->object();
+ QObject *object = static_cast<QDBusAbstractAdaptor *>(sender)->parent();
// break down the parameter list
QList<int> types;
void QDBusAdaptorConnector::signalBeginCallback(QObject *caller, int method_index, void **argv)
{
- QDBusAdaptorConnector *data = qobject_cast<QDBusAdaptorConnector *>(caller->parent());
- if (data) {
+ QDBusAbstractAdaptor *adaptor = qobject_cast<QDBusAbstractAdaptor *>(caller);
+ if (adaptor) {
+ QDBusAdaptorConnector *data = qDBusFindAdaptorConnector(adaptor);
data->lastSignalIdx = method_index;
data->argv = argv;
data->senderMetaObject = caller->metaObject();
void QDBusAdaptorConnector::signalEndCallback(QObject *caller, int)
{
- QDBusAdaptorConnector *data = qobject_cast<QDBusAdaptorConnector *>(caller->parent());
- if (data) {
+ QDBusAbstractAdaptor *adaptor = qobject_cast<QDBusAbstractAdaptor *>(caller);
+ if (adaptor) {
+ QDBusAdaptorConnector *data = qDBusFindAdaptorConnector(adaptor);
data->lastSignalIdx = 0;
data->argv = 0;
data->senderMetaObject = 0;
public:
~QDBusAbstractAdaptor();
- QObject *object() const;
+ Q_DECL_DEPRECATED QObject *object() const;
protected:
void setAutoRelaySignals(bool enable);
#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<QVariant>::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<QVariant>::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.
}
/*!
+ \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)
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;
QString service;
QString path;
QString interface;
- QDBusError lastError;
+ mutable QDBusError lastError;
bool isValid;
inline QDBusAbstractInterfacePrivate(const QDBusConnection& con, QDBusConnectionPrivate *conp,
: 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);
};
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<QDBusAbstractInterface> 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<QVariant>::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<QVariant *>(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<QVariant *>(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<QDBusAbstractInterface> 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;