📄 qscriptextqobject.cpp
字号:
_id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: execute(_a); break; } _id -= 1; } return _id;}void QScript::ConnectionQObject::execute(void **argv){ Q_ASSERT(m_slot.isValid()); QScriptEnginePrivate *eng = QScriptEnginePrivate::get(m_slot.engine()); QScriptFunction *fun = eng->convertToNativeFunction(m_slot); Q_ASSERT(fun != 0); QList<QByteArray> parameterTypes = m_method.parameterTypes(); int argc = parameterTypes.count(); QScriptValueImpl activation; eng->newActivation(&activation); QScriptObject *activation_data = activation.objectValue(); activation_data->m_scope = m_slot.scope(); int formalCount = fun->formals.count(); int mx = qMax(formalCount, argc); activation_data->m_members.resize(mx + 1); activation_data->m_objects.resize(mx + 1); for (int i = 0; i < mx; ++i) { QScriptNameIdImpl *nameId; if (i < formalCount) nameId = fun->formals.at(i); else nameId = 0; activation_data->m_members[i].object(nameId, i, QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); if (i < argc) { int argType = QMetaType::type(parameterTypes.at(i)); activation_data->m_objects[i] = eng->create(argType, argv[i + 1]); } else { activation_data->m_objects[i] = eng->undefinedValue(); } } QScriptValueImpl senderObject; if (sender() == m_sender.toQObject()) senderObject = m_sender; else senderObject = eng->newQObject(sender()); activation_data->m_members[mx].object(eng->idTable()->id___qt_sender__, mx, QScriptValue::SkipInEnumeration); activation_data->m_objects[mx] = senderObject; QScriptValueImpl thisObject; if (m_receiver.isObject()) thisObject = m_receiver; else thisObject = eng->globalObject(); QScriptContext *context = eng->pushContext(); QScriptContextPrivate *context_data = QScriptContextPrivate::get(context); context_data->m_activation = activation; context_data->m_callee = m_slot; context_data->m_thisObject = thisObject; context_data->argc = argc; context_data->args = const_cast<QScriptValueImpl*> (activation_data->m_objects.constData()); fun->execute(context_data); if (context->state() == QScriptContext::ExceptionState) { qWarning() << "***" << context->returnValue().toString(); // ### fixme } eng->popContext();}void QScript::ConnectionQObject::mark(int generation){ if (m_sender.isValid()) m_sender.mark(generation); if (m_receiver.isValid()) m_receiver.mark(generation); if (m_slot.isValid()) m_slot.mark(generation);}bool QScript::ConnectionQObject::hasTarget(const QScriptValueImpl &receiver, const QScriptValueImpl &slot) const{ if (receiver.isObject() != m_receiver.isObject()) return false; if ((receiver.isObject() && m_receiver.isObject()) && (receiver.objectValue() != m_receiver.objectValue())) { return false; } return (slot.objectValue() == m_slot.objectValue());}void QScript::QtPropertyFunction::execute(QScriptContextPrivate *context){ QScriptEngine *eng = context->engine(); QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(eng); QScriptValueImpl result = eng_p->undefinedValue(); QScriptValueImpl object = context->thisObject(); QObject *qobject = object.toQObject(); while ((!qobject || (qobject->metaObject() != m_meta)) && object.prototype().isObject()) { object = object.prototype(); qobject = object.toQObject(); } Q_ASSERT(qobject); QMetaProperty prop = m_meta->property(m_index); Q_ASSERT(prop.isScriptable()); if (context->argumentCount() == 0) { // get if (prop.isValid()) { QScriptable *scriptable = scriptableFromQObject(qobject); QScriptEngine *oldEngine = 0; if (scriptable) { oldEngine = QScriptablePrivate::get(scriptable)->engine; QScriptablePrivate::get(scriptable)->engine = eng; } QVariant v = prop.read(qobject); if (scriptable) QScriptablePrivate::get(scriptable)->engine = oldEngine; result = eng_p->valueFromVariant(v); } } else { // set QVariant v = variantFromValue(prop.userType(), context->argument(0)); QScriptable *scriptable = scriptableFromQObject(qobject); QScriptEngine *oldEngine = 0; if (scriptable) { oldEngine = QScriptablePrivate::get(scriptable)->engine; QScriptablePrivate::get(scriptable)->engine = eng; } prop.write(qobject, v); if (scriptable) QScriptablePrivate::get(scriptable)->engine = oldEngine; result = context->argument(0); } context->m_result = result;}static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str){ QByteArray scope; QByteArray name; int scopeIdx = str.indexOf("::"); if (scopeIdx != -1) { scope = str.left(scopeIdx); name = str.mid(scopeIdx + 2); } else { name = str; } for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { QMetaEnum m = meta->enumerator(i); if ((m.name() == name)/* && (scope.isEmpty() || (m.scope() == scope))*/) return i; } return -1;}void QScript::QtFunction::execute(QScriptContextPrivate *context){ if (!m_object) { context->throwError(QLatin1String("cannot call function of deleted QObject")); return; } QScriptEngine *eng = context->engine(); QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(eng); QScriptValueImpl result = eng_p->undefinedValue(); const QMetaObject *meta = m_object->metaObject(); QObject *thisQObject = context->thisObject().toQObject(); if (!thisQObject) // ### TypeError thisQObject = m_object; QByteArray funName; if (!meta->cast(thisQObject)) {#if 0 // ### find common superclass, see if initialIndex is // in that class (or a superclass of that class), // then it's still safe to execute it funName = methodName(meta->method(m_initialIndex)); context->throwError( QString::fromUtf8("cannot execute %0: %1 does not inherit %2") .arg(QLatin1String(funName)) .arg(QLatin1String(thisQObject->metaObject()->className())) .arg(QLatin1String(meta->className()))); return;#endif // invoking a function in the prototype thisQObject = m_object; }#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE QScriptMetaObject *metaCache = eng_p->cachedMetaObject(meta);#endif QScriptMetaMethod chosenMethod; int chosenIndex = -1; QVarLengthArray<QVariant, 9> args; QVector<QScriptMetaArguments> candidates; for (int index = m_initialIndex; index >= 0; --index) {#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE QScriptMetaMethod mtd = metaCache->findMethod(index); if (!mtd.isValid())#else QScriptMetaMethod mtd;#endif { QMetaMethod method = meta->method(index); QVector<QScriptMetaType> types; // resolve return type QByteArray returnTypeName = method.typeName(); int rtype = QMetaType::type(returnTypeName); if ((rtype == 0) && !returnTypeName.isEmpty()) { if (returnTypeName == "QVariant") { types.append(QScriptMetaType::variant()); } else if (returnTypeName.endsWith('*')) { types.append(QScriptMetaType::metaType(QMetaType::VoidStar, returnTypeName)); } else { int enumIndex = indexOfMetaEnum(meta, returnTypeName); if (enumIndex != -1) types.append(QScriptMetaType::metaEnum(enumIndex, returnTypeName)); else types.append(QScriptMetaType::unresolved(returnTypeName)); } } else { types.append(QScriptMetaType::metaType(rtype, returnTypeName)); } // resolve argument types QList<QByteArray> parameterTypeNames = method.parameterTypes(); for (int i = 0; i < parameterTypeNames.count(); ++i) { QByteArray argTypeName = parameterTypeNames.at(i); int atype = QMetaType::type(argTypeName); if (atype == 0) { if (argTypeName == "QVariant") { types.append(QScriptMetaType::variant()); } else { int enumIndex = indexOfMetaEnum(meta, argTypeName); if (enumIndex != -1) types.append(QScriptMetaType::metaEnum(enumIndex, argTypeName)); else types.append(QScriptMetaType::unresolved(argTypeName)); } } else { types.append(QScriptMetaType::metaType(atype, argTypeName)); } } mtd = QScriptMetaMethod(methodName(method), types);#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE if (mtd.fullyResolved()) metaCache->registerMethod(index, mtd);#endif } if (index == m_initialIndex) funName = mtd.name(); else if (mtd.name() != funName) continue; if (context->argumentCount() < mtd.argumentCount()) continue; if (!mtd.fullyResolved()) { // remember it so we can give an error message later, if necessary candidates.append(QScriptMetaArguments(/*matchDistance=*/INT_MAX, index, mtd, QVarLengthArray<QVariant, 9>())); continue; } if (args.count() != mtd.count()) args.resize(mtd.count()); QScriptMetaType retType = mtd.returnType(); args[0] = QVariant(retType.typeId(), (void *)0); // the result // try to convert arguments bool converted = true; int matchDistance = 0; for (int i = 0; converted && i < mtd.argumentCount(); ++i) { QScriptValueImpl actual = context->argument(i); QScriptMetaType argType = mtd.argumentType(i); int tid = argType.typeId(); QVariant v(tid, (void *)0); converted = eng_p->convert(actual, tid, v.data()); if (!converted) { if (actual.isVariant()) { QVariant &vv = actual.variantValue(); if (argType.isVariant()) { v = vv; converted = true; } else if (vv.canConvert(QVariant::Type(tid))) { v = vv; converted = v.convert(QVariant::Type(tid)); if (converted) matchDistance += 10; } else { QByteArray vvTypeName = vv.typeName(); if (vvTypeName.endsWith('*') && (vvTypeName.left(vvTypeName.size()-1) == argType.name())) { v = QVariant(tid, *reinterpret_cast<void* *>(vv.data())); converted = true; matchDistance += 10; } } } else if (actual.isNumber()) { // see if it's an enum value QMetaEnum m; if (argType.isMetaEnum()) { m = meta->enumerator(argType.enumeratorIndex()); } else { int mi = indexOfMetaEnum(meta, argType.name()); if (mi != -1) m = meta->enumerator(mi); } if (m.isValid()) { int ival = actual.toInt32(); if (m.valueToKey(ival) != 0) { qVariantSetValue(v, ival); converted = true; matchDistance += 10; } } } } else { // determine how well the conversion matched if (actual.isNumber()) { switch (tid) { case QMetaType::Double: // perfect break; case QMetaType::Float: matchDistance += 1; break; case QMetaType::LongLong: case QMetaType::ULongLong: matchDistance += 2; break; case QMetaType::Long: case QMetaType::ULong: matchDistance += 3; break; case QMetaType::Int: case QMetaType::UInt: matchDistance += 4; break; case QMetaType::Short: case QMetaType::UShort: matchDistance += 5; break; case QMetaType::Char: case QMetaType::UChar: matchDistance += 6; break; default: matchDistance += 10; break; } } else if (actual.isString()) { switch (tid) { case QMetaType::QString:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -