qdbusintegrator.cpp

来自「奇趣公司比较新的qt/emd版本」· C++ 代码 · 共 1,726 行 · 第 1/5 页

CPP
1,726
字号
    handled = true;    return -1;}void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage& msg){    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;        activateSignal(hook, msg);    }}void 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();    QDBusReadLocker locker(HandleSignalAction, this);    handleSignal(key, msg);                  // one try    key.truncate(msg.member().length() + 1); // keep the ':'    handleSignal(key, msg);                  // second try    key = QLatin1Char(':');    key += msg.interface();    handleSignal(key, msg);                  // third try}static dbus_int32_t server_slot = -1;void QDBusConnectionPrivate::setServer(DBusServer *s, const QDBusErrorInternal &error){    if (!s) {        handleError(error);        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, const QDBusErrorInternal &error){    if (!dbc) {        handleError(error);        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);    // Initialize the match rules    // We want all messages that have us as destination    // signals don't have destinations, but connectSignal() takes care of them    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);        QDBusErrorInternal error;        dbus_bus_add_match(connection, filter.constData(), error);        if (handleError(error)) {            closeConnection();            return;        }        baseService = QString::fromUtf8(service);    } else {        qWarning("QDBusConnectionPrivate::SetConnection: Unable to get base service");    }    dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0);    //qDebug("base service: %s", service);    // schedule a dispatch:    QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);}extern "C"{static void qDBusResultReceived(DBusPendingCall *pending, void *user_data){    QDBusConnectionPrivate::messageResultReceived(pending, user_data);}}void QDBusConnectionPrivate::messageResultReceived(DBusPendingCall *pending, void *user_data){    QDBusPendingCall *call = reinterpret_cast<QDBusPendingCall *>(user_data);    QDBusConnectionPrivate *connection = const_cast<QDBusConnectionPrivate *>(call->connection);    Q_ASSERT(call->pending == pending);    if (!call->receiver.isNull() && call->methodIdx != -1) {        DBusMessage *reply = dbus_pending_call_steal_reply(pending);        // Deliver the return values of a remote function call.        //        // There is only one connection and it is specified by idx        // The slot must have the same parameter types that the message does        // The slot may have less parameters than the message        // The slot may optionally have one final parameter that is QDBusMessage        // The slot receives read-only copies of the message (i.e., pass by value or by const-ref)        QDBusMessage msg = QDBusMessagePrivate::fromDBusMessage(reply);        qDBusDebug() << QThread::currentThread() << "got message reply (async):" << msg;        if (msg.type() == QDBusMessage::ErrorMessage) {            // got an error, emit it            emit QDBusErrorHelper(call->receiver, call->errorMethod)                .pendingCallError(QDBusError(msg), call->message);            emit connection->callWithCallbackFailed(QDBusError(msg), call->message);        } else {            QDBusCallDeliveryEvent *e = connection->prepareReply(call->receiver, call->methodIdx,                                                                 call->metaTypes, msg);            if (e)                connection->postEventToThread(MessageResultReceivedAction, call->receiver, e);            else                qDBusDebug() << "Deliver failed!";        }    }    dbus_pending_call_unref(pending);    delete call;}int QDBusConnectionPrivate::send(const QDBusMessage& message){    if (QDBusMessagePrivate::isLocal(message))        return -1;              // don't send; the reply will be retrieved by the caller                                // through the d_ptr->localReply link    DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);    if (!msg) {        if (message.type() == QDBusMessage::MethodCallMessage)            qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",                     qPrintable(message.service()), qPrintable(message.path()),                     qPrintable(message.interface()), qPrintable(message.member()));        else if (message.type() == QDBusMessage::SignalMessage)            qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\"",                     qPrintable(message.path()), qPrintable(message.interface()),                     qPrintable(message.member()));        else            qWarning("QDBusConnection: error: could not send %s message to service \"%s\"",                     message.type() == QDBusMessage::ReplyMessage ? "reply" :                     message.type() == QDBusMessage::ErrorMessage ? "error" :                     "invalid", qPrintable(message.service()));        return 0;    }    dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything    qDBusDebug() << QThread::currentThread() << "sending message (no reply):" << message;    checkThread();    bool isOk = dbus_connection_send(connection, msg, 0);    int serial = 0;    if (isOk)        serial = dbus_message_get_serial(msg);    dbus_message_unref(msg);    return serial;}QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,                                                   int sendMode, int timeout){    checkThread();    if ((sendMode == QDBus::BlockWithGui || sendMode == QDBus::Block)         && isServiceRegisteredByThread(message.service()))        // special case for synchronous local calls        return sendWithReplyLocal(message);    if (!QCoreApplication::instance() || sendMode == QDBus::Block) {        DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);        if (!msg) {            qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",                     qPrintable(message.service()), qPrintable(message.path()),                     qPrintable(message.interface()), qPrintable(message.member()));            return QDBusMessage();        }        qDBusDebug() << QThread::currentThread() << "sending message (blocking):" << message;        QDBusErrorInternal error;        DBusMessage *reply = dbus_connection_send_with_reply_and_block(connection, msg, timeout, error);        dbus_message_unref(msg);        if (!!error) {            QDBusError qe = error;            lastError = qe;            return QDBusMessage::createError(qe);        }        QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply);        dbus_message_unref(reply);        qDBusDebug() << QThread::currentThread() << "got message reply (blocking):" << amsg;        if (dbus_connection_get_dispatch_status(connection) == DBUS_DISPATCH_DATA_REMAINS)            QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);        return amsg;    } else { // use the event loop        QDBusReplyWaiter waiter;        if (sendWithReplyAsync(message, &waiter, SLOT(reply(QDBusMessage)),                               SLOT(error(QDBusMessage)), timeout) > 0) {            // enter the event loop and wait for a reply            waiter.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);            lastError = waiter.replyMsg; // set or clear error            return waiter.replyMsg;        }        return QDBusMessage();    }}QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &message){    qDBusDebug() << QThread::currentThread() << "sending message via local-loop:" << message;    QDBusMessage localCallMsg = QDBusMessagePrivate::makeLocal(*this, message);    bool handled = handleMessage(localCallMsg);    if (!handled) {        QString interface = message.interface();        if (interface.isEmpty())            interface = QLatin1String("<no-interface>");        return QDBusMessage::createError(QDBusError::InternalError,                                         QString::fromLatin1("Internal error trying to call %1.%2 at %3 (signature '%4'")                                         .arg(interface, message.member(),                                              message.path(), message.signature()));    }    // if the message was handled, there might be a reply    QDBusMessage localReplyMsg = QDBusMessagePrivate::makeLocalReply(*this, localCallMsg);    if (localReplyMsg.type() == QDBusMessage::InvalidMessage) {        qWarning("QDBusConnection: cannot call local method '%s' at object %s (with signature '%s') "                 "on blocking mode", qPrintable(message.member()), qPrintable(message.path()),                 qPrintable(message.signature()));        return QDBusMessage::createError(            QDBusError(QDBusError::InternalError,                       QLatin1String("local-loop message cannot have delayed replies")));    }    // there is a reply    qDBusDebug() << QThread::currentThread() << "got message via local-loop:" << localReplyMsg;    return localReplyMsg;}int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,                                               const char *returnMethod, const char *errorMethod,                                               int timeout){    if (!receiver || !returnMethod || !*returnMethod) {        // would not be able to deliver a reply        qWarning("QDBusConnection::sendWithReplyAsync: error: cannot deliver a reply to %s::%s (%s)",                 receiver ? receiver->metaObject()->className() : "(null)",                 returnMethod ? returnMethod + 1 : "(null)",                 receiver ? qPrintable(receiver->objectName()) : "no name");        return send(message);    }    int slotIdx = -1;    QList<int> metaTypes;    slotIdx = findSlot(receiver, returnMethod + 1, metaTypes);    if (slotIdx == -1) {        QByteArray normalizedName = QMetaObject::normalizedSignature(returnMethod + 1);        slotIdx = findSlot(receiver, normalizedName, metaTypes);    }    if (slotIdx == -1) {        // would not be able to deliver a reply        qWarning("QDBusConnection::sendWithReplyAsync: error: cannot deliver a reply to %s::%s (%s)",                 receiver->metaObject()->className(),                 returnMethod + 1, qPrintable(receiver->objectName()));        return send(message);    }    DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);    if (!msg) {        qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",                 qPrintable(message.service()), qPrintable(message.path()),                 qPrintable(message.interface()), qPrintable(message.member()));        return 0;    }    checkThread();    qDBusDebug() << QThread::currentThread() << "sending message (async):" << message;    DBusPendingCall *pending = 0;    QDBusDispatchLocker locker(SendWithReplyAsyncAction, this);    if (dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {        int serial = dbus_message_get_serial(msg);        dbus_message_unref(msg);        QDBusPendingCall *pcall = new QDBusPendingCall;        pcall->receiver = receiver;        pcall->metaTypes = metaTypes;        pcall->methodIdx = slotIdx;        pcall->connection = this;        pcall->pending = pending;        pcall->errorMethod = errorMethod;        pcall->message = message;        dbus_pending_call_set_notif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?