Logo Search packages:      
Sourcecode: qt4-x11 version File versions

bool QMetaObject::invokeMethod ( QObject obj,
const char *  member,
Qt::ConnectionType  type,
QGenericReturnArgument  ret,
QGenericArgument  val0 = QGenericArgument(0),
QGenericArgument  val1 = QGenericArgument(),
QGenericArgument  val2 = QGenericArgument(),
QGenericArgument  val3 = QGenericArgument(),
QGenericArgument  val4 = QGenericArgument(),
QGenericArgument  val5 = QGenericArgument(),
QGenericArgument  val6 = QGenericArgument(),
QGenericArgument  val7 = QGenericArgument(),
QGenericArgument  val8 = QGenericArgument(),
QGenericArgument  val9 = QGenericArgument() 
) [static]

Invokes the member (a signal or a slot name) on the object obj. Returns true if the member could be invoked. Returns false if there is no such member or the parameters did not match.

The invocation can be either synchronous or asynchronous, depending on type:

If type is Qt::DirectConnection, the member will be invoked immediately.

If type is Qt::QueuedConnection, a QEvent will be sent and the member is invoked as soon as the application enters the main event loop.

If type is Qt::AutoConnection, the member is invoked synchronously if obj lives in the same thread as the caller; otherwise it will invoke the member asynchronously.

The return value of the member function call is placed in ret. If the invocation is asynchronous, the return value cannot be evaluated. You can pass up to ten arguments (val0, val1, val2, val3, val4, val5, val6, val7, val8, and val9) to the member function.

QGenericArgument and QGenericReturnArgument are internal helper classes. Because signals and slots can be dynamically invoked, you must enclose the arguments using the Q_ARG() and Q_RETURN_ARG() macros. Q_ARG() takes a type name and a const reference of that type; Q_RETURN_ARG() takes a type name and a non-const reference.

To asynchronously invoke the {QPushButton::animateClick()}{animateClick()} slot on a QPushButton:

        QMetaObject::invokeMethod(pushButton, "animateClick",
                                  Qt::QueuedConnection);

With asynchronous method invocations, the parameters must be of types that are known to Qt's meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes. If you try to use a queued connection and get the error message

        QMetaObject::invokeMethod: Unable to handle unregistered datatype 'MyType'

call qRegisterMetaType() to register the data type before you call invokeMethod().

To synchronously invoke the compute(QString, int, double) slot on some arbitrary object obj retrieve its return value:

        QString retVal;
        QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
                                  Q_RETURN_ARG(QString, retVal),
                                  Q_ARG(QString, "sqrt"),
                                  Q_ARG(int, 42),
                                  Q_ARG(double, 9.7));

If the "compute" slot does not take exactly one QString, one int and one double in the specified order, the call will fail.

See also:
Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType()

Definition at line 893 of file qmetaobject.cpp.

References QByteArray::append(), QByteArray::constData(), QMetaType::construct(), QThread::currentThread(), QGenericArgument::data(), QByteArray::length(), QGenericArgument::name(), normalizedSignature(), QCoreApplication::postEvent(), QByteArray::reserve(), QObject::thread(), QByteArray::truncate(), and QMetaType::type().

Referenced by QLayout::addChildWidget(), QAbstractSocket::connectToHost(), QAbstractSocket::disconnectFromHost(), QWorkspace::event(), QObject::event(), QSocketNotifier::event(), QItemDelegate::eventFilter(), QDesktopServices::openUrl(), QDBusAbstractAdaptor::QDBusAbstractAdaptor(), QTest::qExec(), QTest::qInvokeTestMethod(), QAbstractScrollArea::setViewport(), QStyle::standardIcon(), QTreeView::updateGeometries(), QTableView::updateGeometries(), and QBuffer::writeData().

{
    if (!obj)
        return false;

    QVarLengthArray<char, 512> sig;
    int len = qstrlen(member);
    if (len <= 0)
        return false;
    sig.append(member, len);
    sig.append('(');

    enum { ParamCount = 11 };
    const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
                               val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
                               val9.name()};

    int i;
    for (i = 1; i < ParamCount; ++i) {
        len = qstrlen(typeNames[i]);
        if (len <= 0)
            break;
        sig.append(typeNames[i], len);
        sig.append(',');
    }
    if (i == 1)
        sig.append(')'); // no parameters
    else
        sig[sig.size() - 1] = ')';
    sig.append('\0');

    int idx = obj->metaObject()->indexOfMethod(sig.constData());
    if (idx < 0) {
        QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
        idx = obj->metaObject()->indexOfMethod(norm.constData());
    }
    if (idx < 0)
        return false;

    // check return type
    if (ret.data()) {
        const char *retType = obj->metaObject()->method(idx).typeName();
        if (qstrcmp(ret.name(), retType) != 0) {
            // normalize the return value as well
            // the trick here is to make a function signature out of the return type
            // so that we can call normalizedSignature() and avoid duplicating code
            QByteArray unnormalized;
            int len = qstrlen(ret.name());

            unnormalized.reserve(len + 3);
            unnormalized = "_(";        // the function is called "_"
            unnormalized.append(ret.name());
            unnormalized.append(')');

            QByteArray normalized = QMetaObject::normalizedSignature(unnormalized.constData());
            normalized.truncate(normalized.length() - 1); // drop the ending ')'

            if (qstrcmp(normalized.constData() + 2, retType) != 0)
                return false;
        }
    }
    void *param[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
                     val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
    if (type == Qt::AutoConnection) {
        type = QThread::currentThread() == obj->thread()
               ? Qt::DirectConnection
               : Qt::QueuedConnection;
    }

    if (type != Qt::QueuedConnection) {
        return obj->qt_metacall(QMetaObject::InvokeMetaMethod, idx, param) < 0;
    } else {
        if (ret.data()) {
            qWarning("QMetaObject::invokeMethod: Unable to invoke methods with return values in queued "
                     "connections");
            return false;
        }
        int nargs = 1; // include return type
        void **args = (void **) qMalloc(ParamCount * sizeof(void *));
        int *types = (int *) qMalloc(ParamCount * sizeof(int));
        types[0] = 0; // return type
        args[0] = 0;
        for (i = 1; i < ParamCount; ++i) {
            types[i] = QMetaType::type(typeNames[i]);
            if (types[i]) {
                args[i] = QMetaType::construct(types[i], param[i]);
                ++nargs;
            } else if (param[i]) {
                qWarning("QMetaObject::invokeMethod: Unable to handle unregistered datatype '%s'",
                         typeNames[i]);
                return false;
            }
        }

        QCoreApplication::postEvent(obj, new QMetaCallEvent(idx, 0, -1, -1, nargs, types, args));
    }
    return true;
}


Generated by  Doxygen 1.6.0   Back to index