// Convert complex variant types to DOM properties with the help of QAbstractFormBuilder // Does not perform a check using QAbstractFormBuilder::checkProperty(). DomProperty *variantToDomProperty(QAbstractFormBuilder *afb, const QMetaObject *meta, const QString &pname, const QVariant &v) { const QFormBuilderStrings &strings = QFormBuilderStrings::instance(); DomProperty *dom_prop = new DomProperty(); dom_prop->setAttributeName(pname); const int pindex = meta->indexOfProperty(pname.toLatin1()); if (pindex != -1) { QMetaProperty meta_property = meta->property(pindex); if ((v.type() == QVariant::Int || v.type() == QVariant::UInt) && meta_property.isEnumType()) { const QMetaEnum e = meta_property.enumerator(); if (e.isFlag()) dom_prop->setElementSet(QString::fromAscii(e.valueToKeys(v.toInt()))); else dom_prop->setElementEnum(QString::fromAscii(e.valueToKey(v.toInt()))); return dom_prop; } if (!meta_property.hasStdCppSet() || (isOfType(meta, &QAbstractScrollArea::staticMetaObject) && pname == strings.cursorProperty)) dom_prop->setAttributeStdset(0); } // Try simple properties if (applySimpleProperty(v, isTranslatable(pname, v, meta), dom_prop)) return dom_prop; // Complex properties switch (v.type()) { case QVariant::Palette: { DomPalette *dom = new DomPalette(); QPalette palette = qvariant_cast<QPalette>(v); palette.setCurrentColorGroup(QPalette::Active); dom->setElementActive(afb->saveColorGroup(palette)); palette.setCurrentColorGroup(QPalette::Inactive); dom->setElementInactive(afb->saveColorGroup(palette)); palette.setCurrentColorGroup(QPalette::Disabled); dom->setElementDisabled(afb->saveColorGroup(palette)); dom_prop->setElementPalette(dom); } break; case QVariant::Brush: dom_prop->setElementBrush(afb->saveBrush(qvariant_cast<QBrush>(v))); break; default: delete dom_prop; if (afb->resourceBuilder()->isResourceType(v)) { dom_prop = afb->resourceBuilder()->saveResource(afb->workingDirectory(), v); if (dom_prop) dom_prop->setAttributeName(pname); break; } uiLibWarning(msgCannotWriteProperty(pname, v)); return 0; } return dom_prop; }
void MetaInfoPrivate::parseProperties(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const { Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject"); Q_ASSERT_X(nodeMetaInfo.isValid(), Q_FUNC_INFO, "invalid NodeMetaInfo"); for (int i = qMetaObject->propertyOffset(); i < qMetaObject->propertyCount(); ++i) { QMetaProperty qProperty = qMetaObject->property(i); PropertyMetaInfo propertyInfo; propertyInfo.setName(QLatin1String(qProperty.name())); QString typeName(qProperty.typeName()); QString noStar = typeName; bool star = false; while (noStar.contains('*')) {//strip star noStar.chop(1); star = true; } if (m_QtTypesToQmlTypes.contains(noStar)) { typeName = star ? m_QtTypesToQmlTypes.value(noStar) + '*' : m_QtTypesToQmlTypes.value(noStar); //### versions } propertyInfo.setType(typeName); propertyInfo.setValid(true); propertyInfo.setReadable(qProperty.isReadable()); propertyInfo.setWritable(qProperty.isWritable()); propertyInfo.setResettable(qProperty.isResettable()); propertyInfo.setEnumType(qProperty.isEnumType()); propertyInfo.setFlagType(qProperty.isFlagType()); if (propertyInfo.isEnumType()) { EnumeratorMetaInfo enumerator; QMetaEnum qEnumerator = qProperty.enumerator(); enumerator.setValid(qEnumerator.isValid()); enumerator.setIsFlagType(qEnumerator.isFlag()); enumerator.setScope(qEnumerator.scope()); enumerator.setName(qEnumerator.name()); for (int i = 0 ;i < qEnumerator.keyCount(); i++) { enumerator.addElement(qEnumerator.valueToKey(i), i); } propertyInfo.setEnumerator(enumerator); } nodeMetaInfo.addProperty(propertyInfo); } }
// Convert complex DOM types with the help of QAbstractFormBuilder QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta,const DomProperty *p) { // Complex types that need functions from QAbstractFormBuilder switch(p->kind()) { case DomProperty::String: { const int index = meta->indexOfProperty(p->attributeName().toUtf8()); if (index != -1 && meta->property(index).type() == QVariant::KeySequence) return QVariant::fromValue(QKeySequence(p->elementString()->text())); } break; case DomProperty::Palette: { const DomPalette *dom = p->elementPalette(); QPalette palette; if (dom->elementActive()) afb->setupColorGroup(palette, QPalette::Active, dom->elementActive()); if (dom->elementInactive()) afb->setupColorGroup(palette, QPalette::Inactive, dom->elementInactive()); if (dom->elementDisabled()) afb->setupColorGroup(palette, QPalette::Disabled, dom->elementDisabled()); palette.setCurrentColorGroup(QPalette::Active); return QVariant::fromValue(palette); } case DomProperty::Set: { const QByteArray pname = p->attributeName().toUtf8(); const int index = meta->indexOfProperty(pname); if (index == -1) { uiLibWarning(QCoreApplication::translate("QFormBuilder", "The set-type property %1 could not be read.").arg(p->attributeName())); return QVariant(); } const QMetaEnum e = meta->property(index).enumerator(); Q_ASSERT(e.isFlag() == true); return QVariant(e.keysToValue(p->elementSet().toUtf8())); } case DomProperty::Enum: { const QByteArray pname = p->attributeName().toUtf8(); const int index = meta->indexOfProperty(pname); QString enumValue = p->elementEnum(); // Triggers in case of objects in Designer like Spacer/Line for which properties // are serialized using language introspection. On preview, however, these objects are // emulated by hacks in the formbuilder (size policy/orientation) fixEnum(enumValue); if (index == -1) { // ### special-casing for Line (QFrame) -- fix for 4.2. Jambi hack for enumerations if (!qstrcmp(meta->className(), "QFrame") && (pname == QByteArray("orientation"))) { return QVariant(enumValue == QFormBuilderStrings::instance().horizontalPostFix ? QFrame::HLine : QFrame::VLine); } else { uiLibWarning(QCoreApplication::translate("QFormBuilder", "The enumeration-type property %1 could not be read.").arg(p->attributeName())); return QVariant(); } } const QMetaEnum e = meta->property(index).enumerator(); return QVariant(e.keyToValue(enumValue.toUtf8())); } case DomProperty::Brush: return QVariant::fromValue(afb->setupBrush(p->elementBrush())); default: if (afb->resourceBuilder()->isResourceProperty(p)) { return afb->resourceBuilder()->loadResource(afb->workingDirectory(), p); } break; } // simple type return domPropertyToVariant(p); }
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; }