void SimApplication::response( const QSimTerminalResponse& resp ) { // Save the target information. QObject *target = d->target; const char *slot = d->slot; // Clear the command details, in preparation for a new command. if ( resp.command().type() != QSimCommand::SetupMenu ) { d->expectedType = QSimCommand::NoCommand; d->currentCommand = QByteArray(); } d->target = 0; d->slot = 0; // Process the response. d->inResponse = true; if ( target && slot ) { // Invoke the slot and pass "resp" to it. QByteArray name( slot + 1 ); name = QMetaObject::normalizedSignature( name.constData() ); int index = target->metaObject()->indexOfMethod( name.constData() ); if ( index != -1 ) { void *args[2]; args[0] = 0; args[1] = (void *)&resp; target->qt_metacall ( QMetaObject::InvokeMetaMethod, index, args ); } } d->inResponse = false; // Answer the AT+CSIM command and send notification of the new command. if ( !d->rules ) return; if ( d->currentCommand.isEmpty() || resp.command().type() == QSimCommand::SetupMenu ) { // No new command, so respond with a simple OK. d->rules->respond( "+CSIM: 4,9000\nOK" ); } else { // There is a new command, so send back 91XX to the TERMINAL RESPONSE // or ENVELOPE request to indicate that we have another command to // be fetched. Then send the unsolicited "*TCMD" notification. QByteArray data; data += (char)0x91; data += (char)(d->currentCommand.size()); d->rules->respond( "+CSIM: " + QString::number( data.size() * 2 ) + "," + QAtUtils::toHex( data ) + "\nOK" ); d->rules->unsolicited ( "*TCMD: " + QString::number( d->currentCommand.size() ) ); } }
int GoValueMetaObject::metaCall(QMetaObject::Call c, int idx, void **a) { //qWarning() << "GoValueMetaObject::metaCall" << c << idx; switch (c) { case QMetaObject::ReadProperty: case QMetaObject::WriteProperty: { // TODO Cache propertyOffset, methodOffset (and maybe qmlEngine) int propOffset = propertyOffset(); if (idx < propOffset) { return value->qt_metacall(c, idx, a); } GoMemberInfo *memberInfo = typeInfo->fields; for (int i = 0; i < typeInfo->fieldsLen; i++) { if (memberInfo->metaIndex == idx) { if (c == QMetaObject::ReadProperty) { DataValue result; hookGoValueReadField(qmlEngine(value), ref, memberInfo->reflectIndex, memberInfo->reflectGetIndex, memberInfo->reflectSetIndex, &result); if (memberInfo->memberType == DTListProperty) { if (result.dataType != DTListProperty) { panicf("reading DTListProperty field returned non-DTListProperty result"); } QQmlListProperty<QObject> *in = *reinterpret_cast<QQmlListProperty<QObject> **>(result.data); QQmlListProperty<QObject> *out = reinterpret_cast<QQmlListProperty<QObject> *>(a[0]); *out = *in; // TODO Could provide a single variable in the stack to ReadField instead. delete in; } else { QVariant *out = reinterpret_cast<QVariant *>(a[0]); unpackDataValue(&result, out); } } else { DataValue assign; QVariant *in = reinterpret_cast<QVariant *>(a[0]); packDataValue(in, &assign); hookGoValueWriteField(qmlEngine(value), ref, memberInfo->reflectIndex, memberInfo->reflectSetIndex, &assign); activate(value, methodOffset() + (idx - propOffset), 0); } return -1; } memberInfo++; } QMetaProperty prop = property(idx); qWarning() << "Property" << prop.name() << "not found!?"; break; } case QMetaObject::InvokeMetaMethod: { if (idx < methodOffset()) { return value->qt_metacall(c, idx, a); } GoMemberInfo *memberInfo = typeInfo->methods; for (int i = 0; i < typeInfo->methodsLen; i++) { if (memberInfo->metaIndex == idx) { // args[0] is the result if any. DataValue args[1 + MaxParams]; for (int i = 1; i < memberInfo->numIn+1; i++) { packDataValue(reinterpret_cast<QVariant *>(a[i]), &args[i]); } hookGoValueCallMethod(qmlEngine(value), ref, memberInfo->reflectIndex, args); if (memberInfo->numOut > 0) { unpackDataValue(&args[0], reinterpret_cast<QVariant *>(a[0])); } return -1; } memberInfo++; } QMetaMethod m = method(idx); qWarning() << "Method" << m.name() << "not found!?"; break; } default: break; // Unhandled. } return -1; }
bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer) { static unsigned int recursiveEntry = 0; if (directReturnValuePointer) { *directReturnValuePointer = NULL; } // store the current storage position, so that we can get back to this state after a slot is called // (do this locally, so that we have all positions on the stack PythonQtValueStoragePosition globalValueStoragePos; PythonQtValueStoragePosition globalPtrStoragePos; PythonQtValueStoragePosition globalVariantStoragePos; PythonQtConv::global_valueStorage.getPos(globalValueStoragePos); PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos); PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos); recursiveEntry++; // the arguments that are passed to qt_metacall void* argList[PYTHONQT_MAX_ARGS]; PyObject* result = NULL; int argc = info->parameterCount(); const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters(); const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0); // set return argument to NULL argList[0] = NULL; bool ok = true; bool skipFirst = false; if (info->isInstanceDecorator()) { skipFirst = true; // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer void* arg1 = firstArgument; if (!arg1) { arg1 = objectToCall; } if (arg1) { // upcast to correct parent class arg1 = ((char*)arg1)+info->upcastingOffset(); } argList[1] = &arg1; if (ok) { for (int i = 2; i<argc && ok; i++) { const PythonQtSlotInfo::ParameterInfo& param = params.at(i); argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo); if (argList[i]==NULL) { ok = false; break; } } } } else { for (int i = 1; i<argc && ok; i++) { const PythonQtSlotInfo::ParameterInfo& param = params.at(i); argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo); if (argList[i]==NULL) { ok = false; break; } } } if (ok) { // parameters are ok, now create the qt return value which is assigned to by metacall if (returnValueParam.typeId != QMetaType::Void) { // create empty default value for the return value if (!directReturnValuePointer) { // create empty default value for the return value argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam); if (argList[0]==NULL) { // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and // pass its internal pointer PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name); if (info && info->pythonQtClassWrapper()) { PyObject* emptyTuple = PyTuple_New(0); // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL); if (result) { argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr; } Py_DECREF(emptyTuple); } } } else { // we can use our pointer directly! argList[0] = directReturnValuePointer; } } PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB(); if (profilingCB) { const char* className = NULL; if (info->decorator()) { className = info->decorator()->metaObject()->className(); } else { className = objectToCall->metaObject()->className(); } profilingCB(PythonQt::Enter, className, info->metaMethod()->signature()); } // invoke the slot via metacall bool hadException = false; QObject* obj = info->decorator()?info->decorator():objectToCall; if (!obj) { hadException = true; PyErr_SetString(PyExc_RuntimeError, "Trying to call a slot on a deleted QObject!"); } else { try { obj->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList); } catch (std::bad_alloc & e) { hadException = true; QByteArray what("std::bad_alloc: "); what += e.what(); PyErr_SetString(PyExc_MemoryError, what.constData()); } catch (std::runtime_error & e) { hadException = true; QByteArray what("std::runtime_error: "); what += e.what(); PyErr_SetString(PyExc_RuntimeError, what.constData()); } catch (std::logic_error & e) { hadException = true; QByteArray what("std::logic_error: "); what += e.what(); PyErr_SetString(PyExc_RuntimeError, what.constData()); } catch (std::exception& e) { hadException = true; QByteArray what("std::exception: "); what += e.what(); PyErr_SetString(PyExc_StandardError, what.constData()); } } if (profilingCB) { profilingCB(PythonQt::Leave, NULL, NULL); } // handle the return value (which in most cases still needs to be converted to a Python object) if (!hadException) { if (argList[0] || returnValueParam.typeId == QMetaType::Void) { if (directReturnValuePointer) { result = NULL; } else { // the resulting object maybe present already, because we created it above at 1)... if (!result) { result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]); } } } else { QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class."; PyErr_SetString(PyExc_ValueError, e.toLatin1().data()); result = NULL; } } else { result = NULL; } } recursiveEntry--; // reset the parameter storage position to the stored pos to "pop" the parameter stack PythonQtConv::global_valueStorage.setPos(globalValueStoragePos); PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos); PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos); *pythonReturnValue = result; // NOTE: it is important to only return here, otherwise the stack will not be popped!!! return result || (directReturnValuePointer && *directReturnValuePointer); }