⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qdbusintegrator.cpp

📁 QT 开发环境里面一个很重要的文件
💻 CPP
📖 第 1 页 / 共 4 页
字号:
}static CallDeliveryEvent* prepareReply(QObject *object, int idx, const QList<int> &metaTypes,                                       const QDBusMessage &msg){    Q_ASSERT(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    CallDeliveryEvent *data = new CallDeliveryEvent;    data->object = object;    data->flags = 0;    data->message = msg;    data->metaTypes = metaTypes;    data->slotIdx = idx;    return data;}bool 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)    CallDeliveryEvent *call = prepareReply(hook.obj, hook.midx, hook.params, msg);    if (call) {        postCallDeliveryEvent(call);        return true;    }    return false;}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.    if (!object)        return false;    QList<int> metaTypes;    int idx;    {        const QMetaObject *mo = object->metaObject();        QByteArray memberName = msg.member().toUtf8();        // find a slot that matches according to the rules above        idx = ::findSlot(mo, memberName, flags, msg.signature(), metaTypes);        if (idx == -1) {            // ### this is where we want to add the connection as an arg too            // try with no parameters, but with a QDBusMessage            idx = ::findSlot(mo, memberName, flags, QString(), metaTypes);            if (metaTypes.count() != 2 || metaTypes.at(1) != QDBusMetaTypeId::message) {                return false;	  }        }    }    // found the slot to be called    // prepare for the call:    CallDeliveryEvent *call = new CallDeliveryEvent;    // parameters:    call->object = object;    call->flags = flags;    call->message = msg;    // save our state:    call->metaTypes = metaTypes;    call->slotIdx = idx;    if (QDBusMessagePrivate::isLocal(msg)) {        //qDebug() << "QDBusConnectionPrivate::activateCall" << msg.d_ptr->msg;        sendCallDeliveryEvent(call);    } else {        postCallDeliveryEvent(call);    }    // ready    return true;}void QDBusConnectionPrivate::sendCallDeliveryEvent(CallDeliveryEvent *data){    Q_ASSERT(data);    data->conn = this;#if USE_OUTSIDE_DISPATCH    callDeliveryMutex.lock();    callDeliveryState = data;#else    QCoreApplication::sendEvent(this, data);#endif}void QDBusConnectionPrivate::postCallDeliveryEvent(CallDeliveryEvent *data){    Q_ASSERT(data);    data->conn = this;#if USE_OUTSIDE_DISPATCH    callDeliveryMutex.lock();    callDeliveryState = data;#else    QCoreApplication::postEvent(this, data);#endif}CallDeliveryEvent *QDBusConnectionPrivate::postedCallDeliveryEvent(){    CallDeliveryEvent *e = callDeliveryState;    Q_ASSERT(e && e->conn == this);    // release it:    callDeliveryState = 0;    callDeliveryMutex.unlock();    return e;}void QDBusConnectionPrivate::deliverCall(const CallDeliveryEvent& data) const{    // resume state:    const QList<int>& metaTypes = data.metaTypes;    const QDBusMessage& msg = data.message;    QVarLengthArray<void *, 10> params;    params.reserve(metaTypes.count());    QVariantList auxParameters;    // let's create the parameter list    // first one is the return type -- add it below    params.append(0);    // add the input parameters    int i;    for (i = 1; i <= qMin(msg.arguments().count(), metaTypes.count() - 1); ++i) {        int id = metaTypes[i];        if (id == QDBusMetaTypeId::message)            break;        if (id == int(msg.arguments().at(i - 1).userType()))            // no conversion needed            params.append(const_cast<void *>(msg.arguments().at(i - 1).constData() ));        else if (msg.arguments().at(i - 1).userType() == qMetaTypeId<QDBusArgument>()) {            // convert to what the function expects            void *null = 0;            auxParameters.append(QVariant(id, null));            const QDBusArgument &in =                *reinterpret_cast<const QDBusArgument *>(msg.arguments().at(i - 1).constData());            QVariant &out = auxParameters[auxParameters.count() - 1];            if (!QDBusMetaType::demarshall(in, out.userType(), out.data()))                qFatal("Internal error: demarshalling function for type '%s' (%d) failed!",                       out.typeName(), out.userType());            params.append(const_cast<void *>(out.constData()) );        } else {            qFatal("Internal error: got invalid meta type %d when trying to convert to meta type %d",                   msg.arguments().at(i - 1).userType(), id);        }    }    bool takesMessage = false;    if (metaTypes.count() > i && metaTypes[i] == QDBusMetaTypeId::message) {        params.append(const_cast<void*>(static_cast<const void*>(&msg)));        takesMessage = true;        ++i;    }    // output arguments    QVariantList outputArgs;    void *null = 0;    if (metaTypes[0] != QMetaType::Void) {        QVariant arg(metaTypes[0], null);        outputArgs.append( arg );        params[0] = const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData());    }    for ( ; i < metaTypes.count(); ++i) {        QVariant arg(metaTypes[i], null);        outputArgs.append( arg );        params.append(const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData()));    }    // make call:    bool fail;    if (data.object.isNull()) {        fail = true;    } else {        QDBusConnectionPrivate::setSender(this);        fail = data.object->qt_metacall(QMetaObject::InvokeMetaMethod,                                        data.slotIdx, params.data()) >= 0;        QDBusConnectionPrivate::setSender(0);    }    // do we create a reply? Only if the caller is waiting for a reply and one hasn't been sent    // yet.    if (QDBusMessagePrivate::isLocal(msg) && !fail) {        // a little hack to enable local calls to return values        //qDebug() << "QDBusConnectionPrivate::deliverCall" << outputArgs;        QDBusMessagePrivate::setArguments(&msg, outputArgs);        QDBusMessagePrivate::setType(&msg, QDBusMessage::ReplyMessage);        return;    }    if (!msg.isReplyRequired() && !msg.isDelayedReply()) {        if (!fail) {            // normal reply            qDBusDebug() << "Automatically sending reply:" << outputArgs;            send(msg.createReply(outputArgs));        } else {            // generate internal error            qWarning("Internal error: Failed to deliver message");            send(QDBusMessage::createError(QDBusError(QDBusError::InternalError,                                           QLatin1String("Failed to deliver message"))));        }    }    return;}void QDBusConnectionPrivate::customEvent(QEvent *e){    // nothing else should be sending custom events at us    CallDeliveryEvent* call = static_cast<CallDeliveryEvent *>(e);    // self check:    Q_ASSERT(call->conn == this);    deliverCall(*call);}QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)    : QObject(p), ref(1), mode(InvalidMode), connection(0), server(0), busService(0){    extern bool qDBusInitThreads();    static const bool threads = qDBusInitThreads();    static const bool debugging = !qgetenv("QDBUS_DEBUG").isEmpty();    Q_UNUSED(threads);    ::isDebugging = debugging;    QDBusMetaTypeId::init();    dbus_error_init(&error);    rootNode.flags = 0;    connect(this, SIGNAL(serviceOwnerChanged(QString,QString,QString)),            this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));}QDBusConnectionPrivate::~QDBusConnectionPrivate(){    if (dbus_error_is_set(&error))        dbus_error_free(&error);    closeConnection();    rootNode.clear();        // free resources    qDeleteAll(cachedMetaObjects);}void QDBusConnectionPrivate::closeConnection(){    QWriteLocker locker(&lock);    ConnectionMode oldMode = mode;    mode = InvalidMode; // prevent reentrancy    if (oldMode == ServerMode) {        if (server) {            dbus_server_disconnect(server);            dbus_server_unref(server);            server = 0;        }    } else if (oldMode == ClientMode) {        if (connection) {            dbus_connection_close(connection);            // send the "close" message            while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS)                ;            dbus_connection_unref(connection);            connection = 0;        }    }}bool QDBusConnectionPrivate::handleError(){    lastError = QDBusError(&error);    if (dbus_error_is_set(&error))        dbus_error_free(&error);    return lastError.isValid();}void QDBusConnectionPrivate::bindToApplication(){    // Yay, now that we have an application we are in business    Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection",               "qDBusBindToApplication called without an application");    moveToThread(QCoreApplication::instance()->thread());    // Re-add all watchers    WatcherHash oldWatchers = watchers;    watchers.clear();    QHashIterator<int, QDBusConnectionPrivate::Watcher> it(oldWatchers);    while (it.hasNext()) {        it.next();        if (!it.value().read && !it.value().write) {            qDBusAddWatch(it.value().watch, this);        } else {            watchers.insertMulti(it.key(), it.value());        }    }    // Re-add all timeouts    while (!pendingTimeouts.isEmpty())       qDBusAddTimeout(pendingTimeouts.takeFirst(), this);}void QDBusConnectionPrivate::timerEvent(QTimerEvent *e){    DBusTimeout *timeout = timeouts.value(e->timerId(), 0);    dbus_timeout_handle(timeout);}void QDBusConnectionPrivate::doDispatch(){    if (mode == ClientMode)        while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);}void QDBusConnectionPrivate::socketRead(int fd){    QHashIterator<int, QDBusConnectionPrivate::Watcher> it(watchers);    while (it.hasNext()) {        it.next();        if (it.key() == fd && it.value().read && it.value().read->isEnabled()) {            if (!dbus_watch_handle(it.value().watch, DBUS_WATCH_READABLE))                qDebug("OUT OF MEM");        }    }    doDispatch();}void QDBusConnectionPrivate::socketWrite(int fd){    QHashIterator<int, QDBusConnectionPrivate::Watcher> it(watchers);    while (it.hasNext()) {        it.next();        if (it.key() == fd && it.value().write && it.value().write->isEnabled()) {            if (!dbus_watch_handle(it.value().watch, DBUS_WATCH_WRITABLE))                qDebug("OUT OF MEM");        }    }}void QDBusConnectionPrivate::objectDestroyed(QObject *obj){    QWriteLocker locker(&lock);    huntAndDestroy(obj, &rootNode);    SignalHookHash::iterator sit = signalHooks.begin();    while (sit != signalHooks.end()) {        if (static_cast<QObject *>(sit.value().obj) == obj)            sit = signalHooks.erase(sit);        else            ++sit;    }    obj->disconnect(this);}void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, int signalId,                                         const QVariantList &args){    int mciid = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);    Q_ASSERT(mciid != -1);    QMetaClassInfo mci = mo->classInfo(mciid);    Q_ASSERT(mci.value());    const char *interface = mci.value();    QMetaMethod mm = mo->method(signalId);    QByteArray memberName = mm.signature();    memberName.truncate(memberName.indexOf('('));    // check if it's scriptable    bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;    bool isAdaptor = false;    for ( ; mo; mo = mo->superClass())        if (mo == &QDBusAbstractAdaptor::staticMetaObject) {            isAdaptor = true;            break;        }    QReadLocker locker(&lock);

⌨️ 快捷键说明

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