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