qdbusintegrator.cpp
来自「奇趣公司比较新的qt/emd版本」· C++ 代码 · 共 1,726 行 · 第 1/5 页
CPP
1,726 行
return result.toLatin1();}static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath, int &usedLength, QDBusConnectionPrivate::ObjectTreeNode &result){ int start = 0; int length = fullpath.length(); if (fullpath.at(0) == QLatin1Char('/')) start = 1; // walk the object tree const QDBusConnectionPrivate::ObjectTreeNode *node = root; while (start < length && node && !(node->flags & QDBusConnection::ExportChildObjects)) { int end = fullpath.indexOf(QLatin1Char('/'), start); end = (end == -1 ? length : end); QStringRef pathComponent(&fullpath, start, end - start); QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponent); if (it != node->children.constEnd() && it->name == pathComponent) // match node = it; else node = 0; start = end + 1; } // found our object usedLength = (start > length ? length : start); if (node) { if (node->obj || !node->children.isEmpty()) result = *node; else // there really is no object here // we're just looking at an unused space in the QVector node = 0; } return node;}static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath, int start){ int length = fullpath.length(); // any object in the tree can tell us to switch to its own object tree: const QDBusConnectionPrivate::ObjectTreeNode *node = root; if (node && node->flags & QDBusConnection::ExportChildObjects) { QObject *obj = node->obj; while (obj) { if (start >= length) // we're at the correct level return obj; int pos = fullpath.indexOf(QLatin1Char('/'), start); pos = (pos == -1 ? length : pos); QStringRef pathComponent(&fullpath, start, pos - start); 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() == pathComponent) { next = *it; break; } if (!next) break; obj = next; start = pos + 1; } } // object not found return 0;}extern QDBUS_EXPORT void qDBusAddSpyHook(QDBusSpyHook);void qDBusAddSpyHook(QDBusSpyHook hook){ qDBusSpyHookList()->append(hook);}extern "C" {static DBusHandlerResultqDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data){ Q_ASSERT(data); Q_UNUSED(connection); QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); if (d->mode == QDBusConnectionPrivate::InvalidMode) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message); qDBusDebug() << QThread::currentThread() << "got message:" << amsg; return d->handleMessage(amsg) ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;}}bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg){ const QDBusSpyHookList *list = qDBusSpyHookList(); for (int i = 0; i < list->size(); ++i) { qDBusDebug() << "calling the message spy hook"; (*(*list)[i])(amsg); } switch (amsg.type()) { case QDBusMessage::SignalMessage: handleSignal(amsg); return true; break; case QDBusMessage::MethodCallMessage: handleObjectCall(amsg); return true; case QDBusMessage::ReplyMessage: // This is most likely an ACK generated by RemoveMatch message if (amsg.service() == QLatin1String("org.freedesktop.DBus")) return true; qWarning("QDBusConnection received a message of type %d that it shouldn't have", amsg.type()); return false; case QDBusMessage::ErrorMessage: qWarning("QDBusConnection received a message of type %d that it shouldn't have", amsg.type()); return false; // we shouldn't have got them here case QDBusMessage::InvalidMessage: Q_ASSERT_X(false, "QDBusConnection", "Invalid message found when processing"); break; } return false;}static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNode &haystack){ QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = haystack.children.begin(); QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator end = haystack.children.end(); for ( ; it != end; ++it) huntAndDestroy(needle, *it); if (needle == haystack.obj) { haystack.obj = 0; haystack.flags = 0; }}static void huntAndEmit(DBusConnection *connection, DBusMessage *msg, QObject *needle, const QDBusConnectionPrivate::ObjectTreeNode &haystack, bool isScriptable, bool isAdaptor, const QString &path = QString()){ QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = haystack.children.constBegin(); QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator end = haystack.children.constEnd(); for ( ; it != end; ++it) huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1String("/") + it->name); if (needle == haystack.obj) { // is this a signal we should relay? if (isAdaptor && (haystack.flags & QDBusConnection::ExportAdaptors) == 0) return; // no: it comes from an adaptor and we're not exporting adaptors else if (!isAdaptor) { int mask = isScriptable ? QDBusConnection::ExportScriptableSignals : QDBusConnection::ExportNonScriptableSignals; if ((haystack.flags & mask) == 0) return; // signal was not exported } QByteArray p = path.toLatin1(); if (p.isEmpty()) p = "/"; qDBusDebug() << QThread::currentThread() << "emitting signal at" << p; DBusMessage *msg2 = dbus_message_copy(msg); dbus_message_set_path(msg2, p); dbus_connection_send(connection, msg2, 0); dbus_message_unref(msg2); }}static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags, const QString &signature_, QList<int>& metaTypes){ QByteArray msgSignature = signature_.toLatin1(); for (int idx = mo->methodCount() - 1 ; idx >= QObject::staticMetaObject.methodCount(); --idx) { QMetaMethod mm = mo->method(idx); // check access: if (mm.access() != QMetaMethod::Public) continue; // check type: // unnecessary, since signals are never public: //if (mm.methodType() != QMetaMethod::Slot) // continue; // check name: QByteArray slotname = mm.signature(); int paren = slotname.indexOf('('); if (paren != name.length() || !slotname.startsWith(name)) continue; int returnType = qDBusNameToTypeId(mm.typeName()); bool isAsync = qDBusCheckAsyncTag(mm.tag()); bool isScriptable = mm.attributes() & QMetaMethod::Scriptable; // consistency check: if (isAsync && returnType != QMetaType::Void) continue; int inputCount = qDBusParametersForMethod(mm, metaTypes); if (inputCount == -1) continue; // problem parsing metaTypes[0] = returnType; bool hasMessage = false; if (inputCount > 0 && metaTypes.at(inputCount) == QDBusMetaTypeId::message) { // "no input parameters" is allowed as long as the message meta type is there hasMessage = true; --inputCount; } // try to match the parameters int i; QByteArray reconstructedSignature; for (i = 1; i <= inputCount; ++i) { const char *typeSignature = QDBusMetaType::typeToSignature( metaTypes.at(i) ); if (!typeSignature) break; // invalid reconstructedSignature += typeSignature; if (!msgSignature.startsWith(reconstructedSignature)) break; } if (reconstructedSignature != msgSignature) continue; // we didn't match them all if (hasMessage) ++i; // make sure that the output parameters have signatures too if (returnType != 0 && QDBusMetaType::typeToSignature(returnType) == 0) continue; bool ok = true; for (int j = i; ok && j < metaTypes.count(); ++j) if (QDBusMetaType::typeToSignature(metaTypes.at(i)) == 0) ok = false; if (!ok) continue; // consistency check: if (isAsync && metaTypes.count() > i + 1) continue; if (isScriptable && (flags & QDBusConnection::ExportScriptableSlots) == 0) continue; // not exported if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableSlots) == 0) continue; // not exported // if we got here, this slot matched return idx; } // no slot matched return -1;}QDBusCallDeliveryEvent* QDBusConnectionPrivate::prepareReply(QObject *object, int idx, const QList<int> &metaTypes, const QDBusMessage &msg){ Q_ASSERT(object); Q_UNUSED(object); int n = metaTypes.count() - 1; if (metaTypes[n] == QDBusMetaTypeId::message) --n; // check that types match for (int i = 0; i < n; ++i) if (metaTypes.at(i + 1) != msg.arguments().at(i).userType() && msg.arguments().at(i).userType() != qMetaTypeId<QDBusArgument>()) return 0; // no match // we can deliver // prepare for the call return new QDBusCallDeliveryEvent(QDBusConnection(this), idx, this, msg, metaTypes);}void QDBusConnectionPrivate::activateSignal(const QDBusConnectionPrivate::SignalHook& hook, const QDBusMessage &msg){ // This is called by QDBusConnectionPrivate::handleSignal to deliver a signal // that was received from D-Bus // // Signals are delivered to slots if the parameters match // Slots can have less parameters than there are on the message // Slots can optionally have one final parameter that is a QDBusMessage // Slots receive read-only copies of the message (i.e., pass by value or by const-ref) QDBusCallDeliveryEvent *call = prepareReply(hook.obj, hook.midx, hook.params, msg); if (call) postEventToThread(ActivateSignalAction, hook.obj, call);}bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBusMessage &msg){ // This is called by QDBusConnectionPrivate::handleObjectCall to place a call // to a slot on the object. // // The call is delivered to the first slot that matches the following conditions: // - has the same name as the message's target member // - ALL of the message's types are found in slot's parameter list // - optionally has one more parameter of type QDBusMessage // If none match, then the slot of the same name as the message target and with // the first type of QDBusMessage is delivered. // // The D-Bus specification requires that all MethodCall messages be replied to, unless the // caller specifically waived this requirement. This means that we inspect if the user slot // generated a reply and, if it didn't, we will. Obviously, if the user slot doesn't take a // QDBusMessage parameter, it cannot generate a reply. // // When a return message is generated, the slot's return type, if any, will be placed // in the message's first position. If there are non-const reference parameters to the // slot, they must appear at the end and will be placed in the subsequent message // positions. static const char cachePropertyName[] = "_qdbus_slotCache"; if (!object) return false;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?