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 + -
显示快捷键?