📄 qdbusintegrator.cpp
字号:
QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), QLatin1String(interface), QLatin1String(memberName)); message.setArguments(args); DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); if (!msg) { qWarning("QDBusConnection: Could not emit signal %s.%s", interface, memberName.constData()); return; } //qDBusDebug() << "Emitting signal" << message; //qDBusDebug() << "for paths:"; dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything huntAndEmit(connection, msg, obj, &rootNode, isScriptable, isAdaptor); dbus_message_unref(msg);}void QDBusConnectionPrivate::_q_serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner){ Q_UNUSED(oldOwner); if (isServiceRegisteredByThread(oldOwner)) unregisterService(name); if (isServiceRegisteredByThread(newOwner)) registerService(name); QMutableHashIterator<QString, SignalHook> it(signalHooks); it.toFront(); while (it.hasNext()) if (it.next().value().service == name) it.value().owner = newOwner;}int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName, QList<int> ¶ms){ int midx = obj->metaObject()->indexOfMethod(normalizedName); if (midx == -1) return -1; int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params); if ( inputCount == -1 || inputCount + 1 != params.count() ) return -1; // failed to parse or invalid arguments or output arguments return midx;}bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, const QString &service, const QString &owner, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *signal, int minMIdx, bool buildSignature){ QByteArray normalizedName = signal + 1; hook.midx = findSlot(receiver, signal + 1, hook.params); if (hook.midx == -1) { normalizedName = QMetaObject::normalizedSignature(signal + 1); hook.midx = findSlot(receiver, normalizedName, hook.params); } if (hook.midx < minMIdx) { if (hook.midx == -1) ;//qWarning("No such slot '%s' while connecting D-Bus", normalizedName.constData()); return false; } hook.service = service; hook.owner = owner; // we don't care if the service has an owner yet hook.path = path; hook.obj = receiver; // build the D-Bus signal name and signature // This should not happen for QDBusConnection::connect, use buildSignature here, since // QDBusConnection::connect passes false and everything else uses true QString mname = name; if (buildSignature && mname.isNull()) { normalizedName.truncate(normalizedName.indexOf('(')); mname = QString::fromUtf8(normalizedName); } key = mname; key.reserve(interface.length() + 1 + mname.length()); key += QLatin1Char(':'); key += interface; if (buildSignature) { hook.signature.clear(); for (int i = 1; i < hook.params.count(); ++i) if (hook.params.at(i) != QDBusMetaTypeId::message) hook.signature += QLatin1String( QDBusMetaType::typeToSignature( hook.params.at(i) ) ); } return true; // connect to this signal}bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode *node, const QDBusMessage &msg){ // object may be null if (msg.interface().isEmpty() || msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) { if (msg.member() == QLatin1String("Introspect") && msg.signature().isEmpty()) { //qDebug() << "QDBusConnectionPrivate::activateInternalFilters introspect" << msg.d_ptr->msg; QDBusMessage reply = msg.createReply(qDBusIntrospectObject(node)); if (QDBusMessagePrivate::isLocal(msg)) { QDBusMessagePrivate::setType(&msg, reply.type()); QDBusMessagePrivate::setArguments(&msg, QVariantList() << qDBusIntrospectObject(node)); } else { send(reply); } } if (msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) return true; } if (node->obj && (msg.interface().isEmpty() || msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES))) { //qDebug() << "QDBusConnectionPrivate::activateInternalFilters properties" << msg.d_ptr->msg; if (msg.member() == QLatin1String("Get") && msg.signature() == QLatin1String("ss")) { QDBusMessage reply = qDBusPropertyGet(node, msg); if (QDBusMessagePrivate::isLocal(msg)) { QDBusMessagePrivate::setType(&msg, reply.type()); QDBusMessagePrivate::setArguments(&msg, reply.arguments()); } else { send(reply); } } else if (msg.member() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv")) { QDBusMessage reply = qDBusPropertySet(node, msg); if (QDBusMessagePrivate::isLocal(msg)) { QDBusMessagePrivate::setType(&msg, reply.type()); QDBusMessagePrivate::setArguments(&msg, reply.arguments()); } else { send(reply); } } if (msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES)) return true; } return false;}bool QDBusConnectionPrivate::activateObject(const ObjectTreeNode *node, const QDBusMessage &msg){ // This is called by QDBusConnectionPrivate::handleObjectCall to place a call to a slot // on the object. // // The call is routed through the adaptor sub-objects if we have any // object may be null QDBusAdaptorConnector *connector; if (node->flags & QDBusConnection::ExportAdaptors && (connector = qDBusFindAdaptorConnector(node->obj))) { int newflags = node->flags | QDBusConnection::ExportNonScriptableSlots; if (msg.interface().isEmpty()) { // place the call in all interfaces // let the first one that handles it to work QDBusAdaptorConnector::AdaptorMap::ConstIterator it = connector->adaptors.constBegin(); QDBusAdaptorConnector::AdaptorMap::ConstIterator end = connector->adaptors.constEnd(); for ( ; it != end; ++it) if (activateCall(it->adaptor, newflags, msg)) return true; } else { // check if we have an interface matching the name that was asked: QDBusAdaptorConnector::AdaptorMap::ConstIterator it; it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(), msg.interface()); if (it != connector->adaptors.constEnd() && msg.interface() == QLatin1String(it->interface)) if (activateCall(it->adaptor, newflags, msg)) return true; } } // no adaptors matched or were exported // try our standard filters if (activateInternalFilters(node, msg)) return true; // try the object itself: if (node->flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots) && activateCall(node->obj, node->flags, msg)) { return true; }#if 0 // nothing matched qDebug("Call failed: no match for %s%s%s at %s", qPrintable(msg.interface()), msg.interface().isEmpty() ? "" : ".", qPrintable(msg.signature()), qPrintable(msg.path()));#endif return false;}template<typename Func>static bool applyForObject(QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath, Func& functor){ // walk the object tree QStringList path = fullpath.split(QLatin1Char('/')); if (path.last().isEmpty()) path.removeLast(); // happens if path is "/" int i = 1; QDBusConnectionPrivate::ObjectTreeNode *node = root; // try our own tree first while (node && !(node->flags & QDBusConnection::ExportChildObjects) ) { if (i == path.count()) { // found our object functor(node); return true; } QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::ConstIterator it = qLowerBound(node->children.constBegin(), node->children.constEnd(), path.at(i)); if (it != node->children.constEnd() && it->name == path.at(i)) // match node = it->node; else node = 0; ++i; } // any object in the tree can tell us to switch to its own object tree: if (node && node->flags & QDBusConnection::ExportChildObjects) { QObject *obj = node->obj; while (obj) { if (i == path.count()) { // we're at the correct level QDBusConnectionPrivate::ObjectTreeNode fakenode(*node); fakenode.obj = obj; functor(&fakenode); return true; } const QObjectList children = obj->children(); // find a child with the proper name QObject *next = 0; QObjectList::ConstIterator it = children.constBegin(); QObjectList::ConstIterator end = children.constEnd(); for ( ; it != end; ++it) if ((*it)->objectName() == path.at(i)) { next = *it; break; } if (!next) break; ++i; obj = next; } } // object not found return false;}#if 0struct qdbus_callObject{ QDBusConnectionPrivate *self; const QDBusMessage &msg; bool returnVal; inline qdbus_callObject(QDBusConnectionPrivate *s, const QDBusMessage &m) : self(s), msg(m), returnVal(false) { } inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node) { }};bool QDBusConnectionPrivate::doDirectObjectCall(const QDBusMessage &msg){ QReadLocker locker(&lock); qdbus_callObject call(this, msg); if (applyForObject(&rootNode, msg.path(), call)) return call.returnVal; // qDebug("Call failed: no object found at %s", qPrintable(msg.path())); return false;}#endifstruct qdbus_activateObject{ QDBusConnectionPrivate *self; const QDBusMessage &msg; bool returnVal; inline qdbus_activateObject(QDBusConnectionPrivate *s, const QDBusMessage &m) : self(s), msg(m), returnVal(false) { } inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node) { returnVal = self->activateObject(node, msg); }};bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg){ QReadLocker locker(&lock); qdbus_activateObject apply(this, msg); if (applyForObject(&rootNode, msg.path(), apply)) return apply.returnVal; // qDebug("Call failed: no object found at %s", qPrintable(msg.path())); return false;}bool QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage& msg){ bool result = false; SignalHookHash::const_iterator it = signalHooks.find(key); SignalHookHash::const_iterator end = signalHooks.constEnd(); //qDebug("looking for: %s", path.toLocal8Bit().constData()); //qDBusDebug() << signalHooks.keys(); for ( ; it != end && it.key() == key; ++it) { const SignalHook &hook = it.value(); if (!hook.owner.isEmpty() && hook.owner != msg.service()) continue; if (!hook.path.isEmpty() && hook.path != msg.path()) continue; if (!hook.signature.isEmpty() && hook.signature != msg.signature()) continue; if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty()) continue; // yes, |= result |= activateSignal(hook, msg); } return result;}bool QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg){ // We call handlesignal(QString, QDBusMessage) three times: // one with member:interface // one with member: // one with :interface // This allows us to match signals with wildcards on member or interface // (but not both) QString key = msg.member(); key.reserve(key.length() + 1 + msg.interface().length()); key += QLatin1Char(':'); key += msg.interface(); QReadLocker locker(&lock); bool result = handleSignal(key, msg); // one try key.truncate(msg.member().length() + 1); // keep the ':' result |= handleSignal(key, msg); // second try key = QLatin1Char(':'); key += msg.interface(); result |= handleSignal(key, msg); // third try return result;}static dbus_int32_t server_slot = -1;void QDBusConnectionPrivate::setServer(DBusServer *s){ if (!server) { handleError(); return; } server = s; mode = ServerMode; dbus_server_allocate_data_slot(&server_slot); if (server_slot < 0) return; dbus_server_set_watch_functions(server, qDBusAddWatch, qDBusRemoveWatch, qDBusToggleWatch, this, 0); // ### check return type? dbus_server_set_timeout_functions(server, qDBusAddTimeout, qDBusRemoveTimeout, qDBusToggleTimeout, this, 0); dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0); dbus_server_set_data(server, server_slot, this, 0);}void QDBusConnectionPrivate::setConnection(DBusConnection *dbc){ if (!dbc) { handleError(); return; } connection = dbc; mode = ClientMode; dbus_connection_set_exit_on_disconnect(connection, false); dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch, qDBusToggleWatch, this, 0); dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout, qDBusToggleTimeout, this, 0);// dbus_bus_add_match(connection, "type='signal',interface='com.trolltech.dbus.Signal'", &error);// dbus_bus_add_match(connection, "type='signal'", &error); dbus_bus_add_match(connection, "type='signal'", &error); if (handleError()) { closeConnection(); return; } const char *service = dbus_bus_get_unique_name(connection); if (service) { QVarLengthArray<char, 56> filter; filter.append("destination='", 13); filter.append(service, qstrlen(service)); filter.append("\'\0", 2); dbus_bus_add_match(connection, filter.constData(), &error); if (handleError()) { closeConnection(); return; } } else { qWarning("QDBusConnectionPrivate::SetConnection: Unable to get base service");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -