static QVariantMap readAllProperties(QObject *object, int flags) { QVariantMap result; const QMetaObject *mo = object->metaObject(); // QObject has properties, so don't start from 0 for (int i = QObject::staticMetaObject.propertyCount(); i < mo->propertyCount(); ++i) { QMetaProperty mp = mo->property(i); // is it readable? if (!mp.isReadable()) continue; // is it a registered property? int typeId = mp.userType(); if (!typeId) continue; const char *signature = QDBusMetaType::typeToSignature(typeId); if (!signature) continue; // is this property visible from the outside? if ((mp.isScriptable() && flags & QDBusConnection::ExportScriptableProperties) || (!mp.isScriptable() && flags & QDBusConnection::ExportNonScriptableProperties)) { // yes, it's visible QVariant value = mp.read(object); if (value.isValid()) result.insert(QString::fromLatin1(mp.name()), value); } } return result; }
void QtInstance::getPropertyNames(ExecState* exec, PropertyNameArray& array) { // This is the enumerable properties, so put: // properties // dynamic properties // slots QObject* obj = getObject(); if (obj) { const QMetaObject* meta = obj->metaObject(); int i; for (i = 0; i < meta->propertyCount(); i++) { QMetaProperty prop = meta->property(i); if (prop.isScriptable()) array.add(Identifier(exec, prop.name())); } #ifndef QT_NO_PROPERTIES QList<QByteArray> dynProps = obj->dynamicPropertyNames(); foreach (const QByteArray& ba, dynProps) array.add(Identifier(exec, ba.constData())); #endif const int methodCount = meta->methodCount(); for (i = 0; i < methodCount; i++) { QMetaMethod method = meta->method(i); if (method.access() != QMetaMethod::Private) { QByteArray sig = method.methodSignature(); array.add(Identifier(exec, String(sig.constData(), sig.length()))); } } } }
QVariant ObjectStaticPropertyModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !m_obj || index.row() < 0 || index.row() >= m_obj.data()->metaObject()->propertyCount()) { return QVariant(); } const QMetaProperty prop = m_obj.data()->metaObject()->property(index.row()); if (role == Qt::DisplayRole) { if (index.column() == 0) { return prop.name(); } else if (index.column() == 1) { // QMetaProperty::read sets QVariant::typeName to int for enums, // so we need to handle that separately here const QVariant value = prop.read(m_obj.data()); const QString enumStr = Util::enumToString(value, prop.typeName(), m_obj.data()); if (!enumStr.isEmpty()) { return enumStr; } return VariantHandler::displayString(value); } else if (index.column() == 2) { return prop.typeName(); } else if (index.column() == 3) { const QMetaObject *mo = m_obj.data()->metaObject(); while (mo->propertyOffset() > index.row()) { mo = mo->superClass(); } return mo->className(); } } else if (role == Qt::DecorationRole) { if (index.column() == 1) { return VariantHandler::decoration(prop.read(m_obj.data())); } } else if (role == Qt::EditRole) { if (index.column() == 1) { return prop.read(m_obj.data()); } } else if (role == Qt::ToolTipRole) { const QString toolTip = tr("Constant: %1\nDesignable: %2\nFinal: %3\nResetable: %4\n" "Has notification: %5\nScriptable: %6\nStored: %7\nUser: %8\nWritable: %9"). arg(translateBool(prop.isConstant())). arg(translateBool(prop.isDesignable(m_obj.data()))). arg(translateBool(prop.isFinal())). arg(translateBool(prop.isResettable())). arg(translateBool(prop.hasNotifySignal())). arg(translateBool(prop.isScriptable(m_obj.data()))). arg(translateBool(prop.isStored(m_obj.data()))). arg(translateBool(prop.isUser(m_obj.data()))). arg(translateBool(prop.isWritable())); return toolTip; } return QVariant(); }
static int writeProperty(QObject *obj, const QByteArray &property_name, QVariant value, int propFlags = QDBusConnection::ExportAllProperties) { const QMetaObject *mo = obj->metaObject(); int pidx = mo->indexOfProperty(property_name); if (pidx == -1) { // this object has no property by that name return PropertyNotFound; } QMetaProperty mp = mo->property(pidx); // check if this property is writable if (!mp.isWritable()) return PropertyReadOnly; // check if this property is exported bool isScriptable = mp.isScriptable(); if (!(propFlags & QDBusConnection::ExportScriptableProperties) && isScriptable) return PropertyNotFound; if (!(propFlags & QDBusConnection::ExportNonScriptableProperties) && !isScriptable) return PropertyNotFound; // we found our property // do we have the right type? int id = mp.userType(); if (!id){ // type not registered or invalid / void? qWarning("QDBusConnection: Unable to handle unregistered datatype '%s' for property '%s::%s'", mp.typeName(), mo->className(), property_name.constData()); return PropertyWriteFailed; } if (id != QMetaType::QVariant && value.userType() == QDBusMetaTypeId::argument()) { // we have to demarshall before writing void *null = 0; QVariant other(id, null); if (!QDBusMetaType::demarshall(qvariant_cast<QDBusArgument>(value), id, other.data())) { qWarning("QDBusConnection: type `%s' (%d) is not registered with QtDBus. " "Use qDBusRegisterMetaType to register it", mp.typeName(), id); return PropertyWriteFailed; } value = other; } if (mp.userType() == qMetaTypeId<QDBusVariant>()) value = QVariant::fromValue(QDBusVariant(value)); // the property type here should match return mp.write(obj, value) ? PropertyWriteSuccess : PropertyWriteFailed; }
static bool NPClass_HasProperty(NPObject *npobj, NPIdentifier name) { NPClass_Prolog; const QByteArray qname = NPN_UTF8FromIdentifier(name); const QMetaObject *metaObject = qobject->metaObject(); int propertyIndex = metaObject->indexOfProperty(qname); if (propertyIndex == -1 || propertyIndex < metaOffset(metaObject, MetaProperty)) return false; QMetaProperty property = qobject->metaObject()->property(propertyIndex); if (!property.isScriptable()) return false; return true; }
QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObject *metaObject, const QString &property) { Q_ASSERT(metaObject); QDeclarativePropertyCache::Data rv; { const QMetaObject *cmo = metaObject; while (cmo) { int idx = metaObject->indexOfProperty(property.toUtf8()); if (idx != -1) { QMetaProperty p = metaObject->property(idx); if (p.isScriptable()) { rv.load(metaObject->property(idx)); if (!isDynamicMetaObject(cmo)) rv.flags |= Data::IsDirect; return rv; } else { while (cmo && cmo->propertyOffset() >= idx) cmo = cmo->superClass(); } } else { cmo = 0; } } } int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); QStringRef methodNameRef = methodName.leftRef(parenIdx); if (methodNameRef == property) { rv.load(m); if (!isDynamicMetaObject(m.enclosingMetaObject())) rv.flags |= Data::IsDirect; return rv; } } return rv; }
QVariant ObjectStaticPropertyModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !m_obj || index.row() < 0 || index.row() >= m_obj.data()->metaObject()->propertyCount()) { return QVariant(); } const QMetaProperty prop = m_obj.data()->metaObject()->property(index.row()); if (role == Qt::DisplayRole) { if (index.column() == 0) { return prop.name(); } else if (index.column() == 1) { return Util::variantToString(prop.read(m_obj.data())); } else if (index.column() == 2) { return prop.typeName(); } else if (index.column() == 3) { const QMetaObject *mo = m_obj.data()->metaObject(); while (mo->propertyOffset() > index.row()) { mo = mo->superClass(); } return mo->className(); } } else if (role == Qt::EditRole) { if (index.column() == 1) { return prop.read(m_obj.data()); } } else if (role == Qt::ToolTipRole) { const QString toolTip = tr("Constant: %1\nDesignable: %2\nFinal: %3\nResetable: %4\n" "Has notification: %5\nScriptable: %6\nStored: %7\nUser: %8\nWritable: %9"). arg(translateBool(prop.isConstant())). arg(translateBool(prop.isDesignable(m_obj.data()))). arg(translateBool(prop.isFinal())). arg(translateBool(prop.isResettable())). arg(translateBool(prop.hasNotifySignal())). arg(translateBool(prop.isScriptable(m_obj.data()))). arg(translateBool(prop.isStored(m_obj.data()))). arg(translateBool(prop.isUser(m_obj.data()))). arg(translateBool(prop.isWritable())); return toolTip; } return QVariant(); }
QString QMetaPropertyAdaptor::detailString(const QMetaProperty &prop) const { QObject *obj = object().qtObject(); QStringList s; s << tr("Constant: %1").arg(translateBool(prop.isConstant())); s << tr("Designable: %1").arg(translateBool(prop.isDesignable(obj))); s << tr("Final: %1").arg(translateBool(prop.isFinal())); if (prop.hasNotifySignal()) s << tr("Notification: %1").arg(Util::prettyMethodSignature(prop.notifySignal())); else s << tr("Notification: no"); s << tr("Resetable: %1").arg(translateBool(prop.isResettable())); #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) s << tr("Revision: %1").arg(prop.revision()); #endif s << tr("Scriptable: %1").arg(translateBool(prop.isScriptable(obj))); s << tr("Stored: %1").arg(translateBool(prop.isStored(obj))); s << tr("User: %1").arg(translateBool(prop.isUser(obj))); s << tr("Writable: %1").arg(translateBool(prop.isWritable())); return s.join(QStringLiteral("\n")); }
QString ObjectStaticPropertyModel::detailString(const QMetaProperty& prop) const { QStringList s; s << tr("Constant: %1").arg(translateBool(prop.isConstant())); s << tr("Designable: %1").arg(translateBool(prop.isDesignable(m_obj.data()))); s << tr("Final: %1").arg(translateBool(prop.isFinal())); if (prop.hasNotifySignal()) { s << tr("Notification: %1").arg(Util::prettyMethodSignature(prop.notifySignal())); } else { s << tr("Notification: no"); } s << tr("Resetable: %1").arg(translateBool(prop.isResettable())); #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) s << tr("Revision: %1").arg(prop.revision()); #endif s << tr("Scriptable: %1").arg(translateBool(prop.isScriptable(m_obj.data()))); s << tr("Stored: %1").arg(translateBool(prop.isStored(m_obj.data()))); s << tr("User: %1").arg(translateBool(prop.isUser(m_obj.data()))); s << tr("Writable: %1").arg(translateBool(prop.isWritable())); return s.join("\n"); }
QStringList REPL::_enumerateCompletions(QObject* obj) const { const QMetaObject* meta = obj->metaObject(); QMap<QString, bool> completions; // List up slots, signals, and invokable methods const int methodOffset = meta->methodOffset(); const int methodCount = meta->methodCount(); for (int i = methodOffset; i < methodCount; i++) { const QString name = QString::fromLatin1(meta->method(i).methodSignature()); // Ignore methods starting with underscores if (name.startsWith('_')) { continue; } // Keep only up to, but not including, first paren const int cutoff = name.indexOf('('); completions.insert((0 < cutoff ? name.left(cutoff) : name), true); } // List up properties const int propertyOffset = meta->propertyOffset(); const int propertyCount = meta->propertyCount(); for (int i = propertyOffset; i < propertyCount; i++) { const QMetaProperty prop = meta->property(i); // Ignore non-scriptable properties if (!prop.isScriptable()) { continue; } const QString name = QString::fromLatin1(prop.name()); // Ignore properties starting with underscores if (name.startsWith('_')) { continue; } completions.insert(name, true); } return completions.uniqueKeys(); }
// ### we may end up with a different search order than QtScript by not // folding this code into the fallbackMethod above, but Fields propagate out // of the binding code Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const { // Check static properties first QtInstance* qtinst = static_cast<QtInstance*>(instance); QObject* obj = qtinst->getObject(); UString ustring = identifier.ustring(); QString objName(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size())); QByteArray ba = objName.toAscii(); // First check for a cached field QtField* f = qtinst->m_fields.value(objName); if (obj) { if (f) { // We only cache real metaproperties, but we do store the // other types so we can delete them later if (f->fieldType() == QtField::MetaProperty) return f; else if (f->fieldType() == QtField::DynamicProperty) { if (obj->dynamicPropertyNames().indexOf(ba) >= 0) return f; else { // Dynamic property that disappeared qtinst->m_fields.remove(objName); delete f; } } else { QList<QObject*> children = obj->children(); for (int index = 0; index < children.count(); ++index) { QObject *child = children.at(index); if (child->objectName() == objName) return f; } // Didn't find it, delete it from the cache qtinst->m_fields.remove(objName); delete f; } } int index = m_metaObject->indexOfProperty(identifier.ascii()); if (index >= 0) { QMetaProperty prop = m_metaObject->property(index); if (prop.isScriptable(obj)) { f = new QtField(prop); qtinst->m_fields.insert(objName, f); return f; } } // Dynamic properties index = obj->dynamicPropertyNames().indexOf(ba); if (index >= 0) { f = new QtField(ba); qtinst->m_fields.insert(objName, f); return f; } // Child objects QList<QObject*> children = obj->children(); for (index = 0; index < children.count(); ++index) { QObject *child = children.at(index); if (child->objectName() == objName) { f = new QtField(child); qtinst->m_fields.insert(objName, f); return f; } } // Nothing named this return 0; } else { QByteArray ba(identifier.ascii()); // For compatibility with qtscript, cached methods don't cause // errors until they are accessed, so don't blindly create an error // here. if (qtinst->m_methods.contains(ba)) return 0; // deleted qobject, but can't throw an error from here (no exec) // create a fake QtField that will throw upon access if (!f) { f = new QtField(ba); qtinst->m_fields.insert(objName, f); } return f; } }
void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, int revision, Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) { Q_UNUSED(revision); allowedRevisionCache.append(0); QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); int methodCount = metaObject->methodCount(); // 3 to block the destroyed signal and the deleteLater() slot int methodOffset = qMax(3, metaObject->methodOffset()); methodIndexCache.resize(methodCount); for (int ii = methodOffset; ii < methodCount; ++ii) { QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); methodName = methodName.left(parenIdx); RData *data = new RData; data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName); methodIndexCache[ii] = data; data->load(m); if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method) data->flags |= methodFlags; else if (m.methodType() == QMetaMethod::Signal) data->flags |= signalFlags; data->metaObjectOffset = allowedRevisionCache.count() - 1; if (stringCache.contains(methodName)) { RData *old = stringCache[methodName]; // We only overload methods in the same class, exactly like C++ if (old->flags & Data::IsFunction && old->coreIndex >= methodOffset) data->relatedIndex = old->coreIndex; data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); data->overrideIndex = old->coreIndex; stringCache[methodName]->release(); identifierCache[data->identifier.identifier]->release(); } stringCache.insert(methodName, data); identifierCache.insert(data->identifier.identifier, data); data->addref(); data->addref(); } int propCount = metaObject->propertyCount(); int propOffset = metaObject->propertyOffset(); indexCache.resize(propCount); for (int ii = propOffset; ii < propCount; ++ii) { QMetaProperty p = metaObject->property(ii); if (!p.isScriptable()) continue; QString propName = QString::fromUtf8(p.name()); RData *data = new RData; data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName); indexCache[ii] = data; data->load(p, engine); data->flags |= propertyFlags; data->metaObjectOffset = allowedRevisionCache.count() - 1; if (stringCache.contains(propName)) { RData *old = stringCache[propName]; data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); data->overrideIndex = old->coreIndex; stringCache[propName]->release(); identifierCache[data->identifier.identifier]->release(); } stringCache.insert(propName, data); identifierCache.insert(data->identifier.identifier, data); data->addref(); data->addref(); } }
static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out) { int id = 1; int i = 0; if (!mo) return 3; QString topclass = qAxFactory()->exposeToSuperClass(className); if (topclass.isEmpty()) topclass = QLatin1String("QObject"); bool hasStockEvents = qAxFactory()->hasStockEvents(className); const QMetaObject *pmo = mo; do { pmo = pmo->superClass(); } while (pmo && topclass != QString::fromLatin1(pmo->className())); int enumoff = pmo ? pmo->enumeratorOffset() : mo->enumeratorOffset(); int methodoff = pmo ? pmo->methodOffset() : mo->methodOffset(); int propoff = pmo ? pmo->propertyOffset() : mo->propertyOffset(); int qtProps = 0; int qtSlots = 0; bool control = false; if (o && o->isWidgetType()) { qtProps = QWidget::staticMetaObject.propertyCount(); qtSlots = QWidget::staticMetaObject.methodCount(); control = true; } const QString classID = stripCurlyBraces(qAxFactory()->classID(className)); if (classID.isEmpty()) return 4; const QString interfaceID = stripCurlyBraces(qAxFactory()->interfaceID(className)); if (interfaceID.isEmpty()) return 5; const QString eventsID = stripCurlyBraces(qAxFactory()->eventsID(className)); const bool hasEvents = !eventsID.isEmpty(); QString cleanClassName = qax_clean_type(className, mo); QString defProp(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultProperty")).value())); QString defSignal(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultSignal")).value())); for (i = enumoff; i < mo->enumeratorCount(); ++i) { const QMetaEnum enumerator = mo->enumerator(i); if (enums.contains(enumerator.name())) continue; enums.append(enumerator.name()); out << "\tenum " << enumerator.name() << " {" << endl; for (int j = 0; j < enumerator.keyCount(); ++j) { QByteArray key(enumerator.key(j)); while (enumValues.contains(key)) { key += '_'; } enumValues.append(key); const uint value = uint(enumerator.value(j)); key = key.leftJustified(20); out << "\t\t" << key << "\t= "; if (enumerator.isFlag()) out << "0x" << QByteArray::number(value, 16).rightJustified(8, '0'); else out << value; if (j < enumerator.keyCount()-1) out << ", "; out << endl; } out << "\t};" << endl << endl; } // mouse cursor enum for QCursor support if (!enums.contains("MousePointer")) { enums.append("MousePointer"); out << "\tenum MousePointer {" << endl; out << "\t\tArrowCursor = " << Qt::ArrowCursor << ',' << endl; out << "\t\tUpArrowCursor = " << Qt::UpArrowCursor << ',' << endl; out << "\t\tCrossCursor = " << Qt::CrossCursor << ',' << endl; out << "\t\tWaitCursor = " << Qt::WaitCursor << ',' << endl; out << "\t\tIBeamCursor = " << Qt::IBeamCursor << ',' << endl; out << "\t\tSizeVerCursor = " << Qt::SizeVerCursor << ',' << endl; out << "\t\tSizeHorCursor = " << Qt::SizeHorCursor << ',' << endl; out << "\t\tSizeBDiagCursor = " << Qt::SizeBDiagCursor << ',' << endl; out << "\t\tSizeFDiagCursor = " << Qt::SizeFDiagCursor << ',' << endl; out << "\t\tSizeAllCursor = " << Qt::SizeAllCursor << ',' << endl; out << "\t\tBlankCursor = " << Qt::BlankCursor << ',' << endl; out << "\t\tSplitVCursor = " << Qt::SplitVCursor << ',' << endl; out << "\t\tSplitHCursor = " << Qt::SplitHCursor << ',' << endl; out << "\t\tPointingHandCursor = " << Qt::PointingHandCursor << ',' << endl; out << "\t\tForbiddenCursor = " << Qt::ForbiddenCursor << ',' << endl; out << "\t\tWhatsThisCursor = " << Qt::WhatsThisCursor << ',' << endl; out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl; out << "\t};" << endl << endl; } if (!enums.contains("FocusPolicy")) { enums.append("FocusPolicy"); out << "\tenum FocusPolicy {" << endl; out << "\t\tNoFocus = " << Qt::NoFocus << ',' << endl; out << "\t\tTabFocus = " << Qt::TabFocus << ',' << endl; out << "\t\tClickFocus = " << Qt::ClickFocus << ',' << endl; out << "\t\tStrongFocus = " << Qt::StrongFocus << ',' << endl; out << "\t\tWheelFocus = " << Qt::WheelFocus << endl; out << "\t};" << endl << endl; } out << endl; out << "\t[" << endl; out << "\t\tuuid(" << interfaceID << ")," << endl; out << "\t\thelpstring(\"" << cleanClassName << " Interface\")" << endl; out << "\t]" << endl; out << "\tdispinterface I" << cleanClassName << endl; out << "\t{" << endl; out << "\tproperties:" << endl; for (i = propoff; i < mo->propertyCount(); ++i) { const QMetaProperty property = mo->property(i); /* if (property.testFlags(QMetaProperty::Override)) continue;*/ if (i <= qtProps && ignoreProps(property.name())) continue; if (!property.name() || mo->indexOfProperty(property.name()) > i) continue; bool ok = true; QByteArray type(convertTypes(property.typeName(), &ok)); QByteArray name(replaceKeyword(property.name())); if (!ok) out << "\t/****** Property is of unsupported datatype" << endl; out << "\t\t[id(" << id << ')'; if (!property.isWritable()) out << ", readonly"; if (isBindable && property.isScriptable(o)) out << ", bindable"; if (!property.isDesignable(o)) out << ", nonbrowsable"; if (isBindable) out << ", requestedit"; if (defProp == QLatin1String(name)) out << ", uidefault"; out << "] " << type << ' ' << name << ';' << endl; if (!ok) out << "\t******/" << endl; ++id; } out << endl; out << "\tmethods:" << endl; int numDefArgs = 0; QByteArray outBuffer; for (i = methodoff; i < mo->methodCount(); ++i) { const QMetaMethod slot = mo->method(i); if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal) continue; if (slot.attributes() & QMetaMethod::Cloned) { ++numDefArgs; continue; } if (!outBuffer.isEmpty()) { outBuffer = addDefaultArguments(outBuffer, numDefArgs); numDefArgs = 0; out << outBuffer; outBuffer = QByteArray(); } QByteArray signature(slot.methodSignature()); QByteArray name(signature.left(signature.indexOf('('))); if (i <= qtSlots && ignoreSlots(name)) continue; signature.remove(0, name.length() + 1); signature.truncate(signature.length() - 1); name = renameOverloads(replaceKeyword(name)); if (ignoreSlots(name)) continue; QList<QByteArray> parameterTypes(slot.parameterTypes()); QList<QByteArray> parameterNames(slot.parameterNames()); bool ok = true; QByteArray type = slot.typeName(); if (type.isEmpty()) type = "void"; else type = convertTypes(type, &ok); QByteArray ptype(prototype(parameterTypes, parameterNames, &ok)); if (!ok) outBuffer += "\t/****** Slot parameter uses unsupported datatype\n"; outBuffer += "\t\t[id(" + QByteArray::number(id) + ")] " + type + ' ' + name + '(' + ptype + ");\n"; if (!ok) outBuffer += "\t******/\n"; ++id; } if (!outBuffer.isEmpty()) { outBuffer = addDefaultArguments(outBuffer, numDefArgs); numDefArgs = 0; out << outBuffer; outBuffer = QByteArray(); } out << "\t};" << endl << endl; mapping.clear(); id = 1; if (hasEvents) { out << "\t[" << endl; out << "\t\tuuid(" << eventsID << ")," << endl; out << "\t\thelpstring(\"" << cleanClassName << " Events Interface\")" << endl; out << "\t]" << endl; out << "\tdispinterface I" << cleanClassName << "Events" << endl; out << "\t{" << endl; out << "\tproperties:" << endl; out << "\tmethods:" << endl; if (hasStockEvents) { out << "\t/****** Stock events ******/" << endl; out << "\t\t[id(DISPID_CLICK)] void Click();" << endl; out << "\t\t[id(DISPID_DBLCLICK)] void DblClick();" << endl; out << "\t\t[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);" << endl; out << "\t\t[id(DISPID_KEYPRESS)] void KeyPress(short* KeyAscii);" << endl; out << "\t\t[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);" << endl; out << "\t\t[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl; out << "\t\t[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl; out << "\t\t[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl << endl; } for (i = methodoff; i < mo->methodCount(); ++i) { const QMetaMethod signal = mo->method(i); if (signal.methodType() != QMetaMethod::Signal) continue; QByteArray signature(signal.methodSignature()); QByteArray name(signature.left(signature.indexOf('('))); signature.remove(0, name.length() + 1); signature.truncate(signature.length() - 1); QList<QByteArray> parameterTypes(signal.parameterTypes()); QList<QByteArray> parameterNames(signal.parameterNames()); bool isDefault = defSignal == QLatin1String(name); name = renameOverloads(replaceKeyword(name)); bool ok = true; QByteArray type = signal.typeName(); if (!type.isEmpty() && type != "void") // signals with return value not supported continue; QByteArray ptype(prototype(parameterTypes, parameterNames, &ok)); if (!ok) out << "\t/****** Signal parameter uses unsupported datatype" << endl; out << "\t\t[id(" << id << ')'; if (isDefault) out << ", uidefault"; out << "] void " << name << '(' << ptype << ");" << endl; if (!ok) out << "\t******/" << endl; ++id; } out << "\t};" << endl << endl; } out << "\t[" << endl; if (qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no")) out << "\t\taggregatable," << endl; if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes")) out << "\t\tappobject," << endl; if (mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value()) out << "\t\tlicensed," << endl; const char *helpString = mo->classInfo(mo->indexOfClassInfo("Description")).value(); if (helpString) out << "\t\thelpstring(\"" << helpString << "\")," << endl; else out << "\t\thelpstring(\"" << cleanClassName << " Class\")," << endl; const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value(); if (classVersion) out << "\t\tversion(" << classVersion << ")," << endl; out << "\t\tuuid(" << classID << ')'; if (control) { out << ", " << endl; out << "\t\tcontrol"; } else if (!o) { out << ", " << endl; out << "\t\tnoncreatable"; } out << endl; out << "\t]" << endl; out << "\tcoclass " << cleanClassName << endl; out << "\t{" << endl; out << "\t\t[default] dispinterface I" << cleanClassName << ';' << endl; if (hasEvents) out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl; out << "\t};" << endl; return S_OK; }
QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node, const QDBusMessage &msg) { Q_ASSERT(msg.arguments().count() == 2); Q_ASSERT_X(!node.obj || QThread::currentThread() == node.obj->thread(), "QDBusConnection: internal threading error", "function called for an object that is in another thread!!"); QString interface_name = msg.arguments().at(0).toString(); QByteArray property_name = msg.arguments().at(1).toString().toUtf8(); QDBusAdaptorConnector *connector; QVariant value; bool interfaceFound = false; if (node.flags & QDBusConnection::ExportAdaptors && (connector = qDBusFindAdaptorConnector(node.obj))) { // find the class that implements interface_name or try until we've found the property // in case of an empty interface if (interface_name.isEmpty()) { for (QDBusAdaptorConnector::AdaptorMap::ConstIterator it = connector->adaptors.constBegin(), end = connector->adaptors.constEnd(); it != end; ++it) { const QMetaObject *mo = it->adaptor->metaObject(); int pidx = mo->indexOfProperty(property_name); if (pidx != -1) { value = mo->property(pidx).read(it->adaptor); break; } } } else { QDBusAdaptorConnector::AdaptorMap::ConstIterator it; it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(), interface_name); if (it != connector->adaptors.constEnd() && interface_name == QLatin1String(it->interface)) { interfaceFound = true; value = it->adaptor->property(property_name); } } } if (!interfaceFound && !value.isValid() && node.flags & (QDBusConnection::ExportAllProperties | QDBusConnection::ExportNonScriptableProperties)) { // try the object itself if (!interface_name.isEmpty()) interfaceFound = qDBusInterfaceInObject(node.obj, interface_name); if (interfaceFound) { int pidx = node.obj->metaObject()->indexOfProperty(property_name); if (pidx != -1) { QMetaProperty mp = node.obj->metaObject()->property(pidx); if ((mp.isScriptable() && (node.flags & QDBusConnection::ExportScriptableProperties)) || (!mp.isScriptable() && (node.flags & QDBusConnection::ExportNonScriptableProperties))) value = mp.read(node.obj); } } } if (!value.isValid()) { // the property was not found if (!interfaceFound) return interfaceNotFoundError(msg, interface_name); return propertyNotFoundError(msg, interface_name, property_name); } return msg.createReply(QVariant::fromValue(QDBusVariant(value))); }
void tst_QQmlMetaObject::property() { QFETCH(QString, testFile); QFETCH(QByteArray, cppTypeName); QFETCH(int, cppType); QFETCH(bool, isDefault); QFETCH(QVariant, expectedValue); QFETCH(bool, isWritable); QFETCH(QVariant, newValue); QQmlEngine engine; QQmlComponent component(&engine, testFileUrl(testFile)); QObject *object = component.create(); QVERIFY(object != 0); const QMetaObject *mo = object->metaObject(); QVERIFY(mo->superClass() != 0); QVERIFY(QByteArray(mo->className()).contains("_QML_")); QCOMPARE(mo->propertyOffset(), mo->superClass()->propertyCount()); QCOMPARE(mo->propertyCount(), mo->superClass()->propertyCount() + 1); QMetaProperty prop = mo->property(mo->propertyOffset()); QCOMPARE(prop.name(), "test"); QCOMPARE(QByteArray(prop.typeName()), cppTypeName); if (prop.userType() < QMetaType::User) QCOMPARE(prop.type(), QVariant::Type(cppType)); else QCOMPARE(prop.type(), QVariant::UserType); QCOMPARE(prop.userType(), cppType); QVERIFY(!prop.isConstant()); QVERIFY(!prop.isDesignable()); QVERIFY(!prop.isEnumType()); QVERIFY(!prop.isFinal()); QVERIFY(!prop.isFlagType()); QVERIFY(prop.isReadable()); QVERIFY(!prop.isResettable()); QVERIFY(prop.isScriptable()); QVERIFY(!prop.isStored()); QVERIFY(!prop.isUser()); QVERIFY(prop.isValid()); QCOMPARE(prop.isWritable(), isWritable); QCOMPARE(mo->classInfoOffset(), mo->superClass()->classInfoCount()); QCOMPARE(mo->classInfoCount(), mo->superClass()->classInfoCount() + (isDefault ? 1 : 0)); if (isDefault) { QMetaClassInfo info = mo->classInfo(mo->classInfoOffset()); QCOMPARE(info.name(), "DefaultProperty"); QCOMPARE(info.value(), "test"); } QCOMPARE(mo->methodOffset(), mo->superClass()->methodCount()); QCOMPARE(mo->methodCount(), mo->superClass()->methodCount() + 1); // the signal QVERIFY(prop.notifySignalIndex() != -1); QMetaMethod signal = prop.notifySignal(); QCOMPARE(signal.methodType(), QMetaMethod::Signal); QCOMPARE(signal.name(), QByteArray("testChanged")); QCOMPARE(signal.methodSignature(), QByteArray("testChanged()")); QCOMPARE(signal.access(), QMetaMethod::Public); QCOMPARE(signal.parameterCount(), 0); QCOMPARE(signal.parameterTypes(), QList<QByteArray>()); QCOMPARE(signal.parameterNames(), QList<QByteArray>()); QCOMPARE(signal.tag(), ""); QCOMPARE(signal.typeName(), "void"); QCOMPARE(signal.returnType(), int(QMetaType::Void)); QSignalSpy changedSpy(object, SIGNAL(testChanged())); QObject::connect(object, SIGNAL(testChanged()), object, SLOT(deleteLater())); if (expectedValue.isValid()) QCOMPARE(prop.read(object), expectedValue); else QVERIFY(prop.read(object).isValid()); QCOMPARE(changedSpy.count(), 0); if (isWritable) { QVERIFY(prop.write(object, newValue)); QCOMPARE(changedSpy.count(), 1); QCOMPARE(prop.read(object), newValue); } else { QVERIFY(!prop.write(object, prop.read(object))); QCOMPARE(changedSpy.count(), 0); } delete object; }
static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset) { QString retval; // start with properties: if (flags & (QDBusConnection::ExportScriptableProperties | QDBusConnection::ExportNonScriptableProperties)) { for (int i = propOffset; i < mo->propertyCount(); ++i) { static const char *accessvalues[] = {0, "read", "write", "readwrite"}; QMetaProperty mp = mo->property(i); if (!((mp.isScriptable() && (flags & QDBusConnection::ExportScriptableProperties)) || (!mp.isScriptable() && (flags & QDBusConnection::ExportNonScriptableProperties)))) continue; int access = 0; if (mp.isReadable()) access |= 1; if (mp.isWritable()) access |= 2; int typeId = qDBusNameToTypeId(mp.typeName()); if (!typeId) continue; const char *signature = QDBusMetaType::typeToSignature(typeId); if (!signature) continue; retval += QString::fromLatin1(" <property name=\"%1\" type=\"%2\" access=\"%3\"") .arg(QLatin1String(mp.name())) .arg(QLatin1String(signature)) .arg(QLatin1String(accessvalues[access])); if (QDBusMetaType::signatureToType(signature) == QVariant::Invalid) { const char *typeName = QVariant::typeToName(QVariant::Type(typeId)); retval += QString::fromLatin1(">\n <annotation name=\"com.trolltech.QtDBus.QtTypeName\" value=\"%3\"/>\n </property>\n") .arg(typeNameToXml(typeName)); } else { retval += QLatin1String("/>\n"); } } } // now add methods: for (int i = methodOffset; i < mo->methodCount(); ++i) { QMetaMethod mm = mo->method(i); QByteArray signature = mm.signature(); int paren = signature.indexOf('('); bool isSignal; if (mm.methodType() == QMetaMethod::Signal) // adding a signal isSignal = true; else if (mm.methodType() == QMetaMethod::Slot && mm.access() == QMetaMethod::Public) isSignal = false; else continue; // neither signal nor public slot if (isSignal && !(flags & (QDBusConnection::ExportScriptableSignals | QDBusConnection::ExportNonScriptableSignals))) continue; // we're not exporting any signals if (!isSignal && !(flags & (QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportNonScriptableSlots))) continue; // we're not exporting any slots QString xml = QString::fromLatin1(" <%1 name=\"%2\">\n") .arg(isSignal ? QLatin1String("signal") : QLatin1String("method")) .arg(QLatin1String(signature.left(paren))); // check the return type first int typeId = qDBusNameToTypeId(mm.typeName()); if (typeId) { const char *typeName = QDBusMetaType::typeToSignature(typeId); if (typeName) { xml += QString::fromLatin1(" <arg type=\"%1\" direction=\"out\"/>\n") .arg(typeNameToXml(typeName)); // do we need to describe this argument? if (QDBusMetaType::signatureToType(typeName) == QVariant::Invalid) xml += QString::fromLatin1(" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n") .arg(typeNameToXml(mm.typeName())); } else continue; } else if (*mm.typeName()) continue; // wasn't a valid type QList<QByteArray> names = mm.parameterNames(); QList<int> types; int inputCount = qDBusParametersForMethod(mm, types); if (inputCount == -1) continue; // invalid form if (isSignal && inputCount + 1 != types.count()) continue; // signal with output arguments? if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message) continue; // signal with QDBusMessage argument? if (isSignal && mm.attributes() & QMetaMethod::Cloned) continue; // cloned signal? int j; bool isScriptable = mm.attributes() & QMetaMethod::Scriptable; for (j = 1; j < types.count(); ++j) { // input parameter for a slot or output for a signal if (types.at(j) == QDBusMetaTypeId::message) { isScriptable = true; continue; } QString name; if (!names.at(j - 1).isEmpty()) name = QString::fromLatin1("name=\"%1\" ").arg(QLatin1String(names.at(j - 1))); bool isOutput = isSignal || j > inputCount; const char *signature = QDBusMetaType::typeToSignature(types.at(j)); xml += QString::fromLatin1(" <arg %1type=\"%2\" direction=\"%3\"/>\n") .arg(name) .arg(QLatin1String(signature)) .arg(isOutput ? QLatin1String("out") : QLatin1String("in")); // do we need to describe this argument? if (QDBusMetaType::signatureToType(signature) == QVariant::Invalid) { const char *typeName = QVariant::typeToName( QVariant::Type(types.at(j)) ); xml += QString::fromLatin1(" <annotation name=\"com.trolltech.QtDBus.QtTypeName.%1%2\" value=\"%3\"/>\n") .arg(isOutput ? QLatin1String("Out") : QLatin1String("In")) .arg(isOutput ? j - 1 : j - inputCount) .arg(typeNameToXml(typeName)); } } int wantedMask; if (isScriptable) wantedMask = isSignal ? QDBusConnection::ExportScriptableSignals : QDBusConnection::ExportScriptableSlots; else wantedMask = isSignal ? QDBusConnection::ExportNonScriptableSignals : QDBusConnection::ExportNonScriptableSlots; if ((flags & wantedMask) != wantedMask) continue; if (qDBusCheckAsyncTag(mm.tag())) // add the no-reply annotation xml += QLatin1String(" <annotation name=\"" ANNOTATION_NO_WAIT "\"" " value=\"true\"/>\n"); retval += xml; retval += QString::fromLatin1(" </%1>\n") .arg(isSignal ? QLatin1String("signal") : QLatin1String("method")); } return retval; }
void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, int revision, Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) { Q_UNUSED(revision); qPersistentDispose(constructor); // Now invalid bool dynamicMetaObject = isDynamicMetaObject(metaObject); allowedRevisionCache.append(0); int methodCount = metaObject->methodCount(); // 3 to block the destroyed signal and the deleteLater() slot int methodOffset = qMax(3, metaObject->methodOffset()); methodIndexCache.resize(methodCount - methodIndexCacheStart); for (int ii = methodOffset; ii < methodCount; ++ii) { QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; // Extract method name const char *signature = m.signature(); const char *cptr = signature; while (*cptr != '(') { Q_ASSERT(*cptr != 0); ++cptr; } QString str = dynamicMetaObject?QString::fromUtf8(signature, cptr - signature): QString::fromLatin1(signature, cptr - signature); QHashedString methodName(str); Data *data = &methodIndexCache[ii - methodIndexCacheStart]; data->lazyLoad(m); if (data->isSignal()) data->flags |= signalFlags; else data->flags |= methodFlags; if (!dynamicMetaObject) data->flags |= Data::IsDirect; data->metaObjectOffset = allowedRevisionCache.count() - 1; if (Data **old = stringCache.value(methodName)) { // We only overload methods in the same class, exactly like C++ if ((*old)->flags & Data::IsFunction && (*old)->coreIndex >= methodOffset) data->relatedIndex = (*old)->coreIndex; data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction); data->overrideIndex = (*old)->coreIndex; } stringCache.insert(methodName, data); } int propCount = metaObject->propertyCount(); int propOffset = metaObject->propertyOffset(); propertyIndexCache.resize(propCount - propertyIndexCacheStart); for (int ii = propOffset; ii < propCount; ++ii) { QMetaProperty p = metaObject->property(ii); if (!p.isScriptable()) continue; QString str = dynamicMetaObject?QString::fromUtf8(p.name()): QString::fromLatin1(p.name()); QHashedString propName(str); Data *data = &propertyIndexCache[ii - propertyIndexCacheStart]; data->lazyLoad(p, engine); data->flags |= propertyFlags; if (!dynamicMetaObject) data->flags |= Data::IsDirect; data->metaObjectOffset = allowedRevisionCache.count() - 1; if (Data **old = stringCache.value(propName)) { data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction); data->overrideIndex = (*old)->coreIndex; } stringCache.insert(propName, data); } }