Beispiel #1
0
bool UiExtractor::checkProperty(QObject *obj, const QString &prop) const
{
  const QMetaObject *mo = obj->metaObject();
  const QMetaProperty mp = mo->property(mo->indexOfProperty(prop.toLatin1()));

  // TODO come up with some more aggressive filtering
  if (mp.isValid() && mp.isDesignable(obj) && mp.isStored(obj) && mp.isWritable()) {
    const QVariant value = mp.read(obj);

    // try to figure out the default by resetting to it
    if (mp.isResettable()) {
      mp.reset(obj);
      if (mp.read(obj) == value) {
        return false;
      }
      mp.write(obj, value);
      return true;
    }

    // some guessing for non-resettable properties
    if (value.isNull() || !value.isValid()) {
      return false;
    }

    if (value.type() == QVariant::String) {
      return !value.toString().isEmpty();
    } else if (value.type() == QVariant::Locale) {
      return value.value<QLocale>() != QLocale::system();
    }

    return true;
  }

  return false;
}
Beispiel #2
0
QT_BEGIN_NAMESPACE

QDeclarativePropertyCache::Data::Flags QDeclarativePropertyCache::Data::flagsForProperty(const QMetaProperty &p, QDeclarativeEngine *engine) 
{
    int propType = p.userType();

    Flags flags;

    if (p.isConstant())
        flags |= Data::IsConstant;
    if (p.isWritable())
        flags |= Data::IsWritable;
    if (p.isResettable())
        flags |= Data::IsResettable;

    if (propType == qMetaTypeId<QDeclarativeBinding *>()) {
        flags |= Data::IsQmlBinding;
    } else if (propType == qMetaTypeId<QScriptValue>()) {
        flags |= Data::IsQScriptValue;
    } else if (p.isEnumType()) {
        flags |= Data::IsEnumType;
    } else {
        QDeclarativeMetaType::TypeCategory cat = engine ? QDeclarativeEnginePrivate::get(engine)->typeCategory(propType)
                                               : QDeclarativeMetaType::typeCategory(propType);
        if (cat == QDeclarativeMetaType::Object)
            flags |= Data::IsQObjectDerived;
        else if (cat == QDeclarativeMetaType::List)
            flags |= Data::IsQList;
    }

    return flags;
}
Beispiel #3
0
void AbstractParam::resetValue() {
    const QMetaObject *mo = metaObject();
    int i = mo->indexOfProperty("value");
    if (i >= 0) {
        QMetaProperty mp = mo->property(i);
        if (mp.isResettable()) {
            mp.reset(this);
        }
    }
}
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();
}
Beispiel #5
0
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);
    }
}
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();
}
QT_BEGIN_NAMESPACE

// Flags that do *NOT* depend on the property's QMetaProperty::userType() and thus are quick
// to load
static QDeclarativePropertyCache::Data::Flags fastFlagsForProperty(const QMetaProperty &p)
{
    QDeclarativePropertyCache::Data::Flags flags;

    if (p.isConstant())
        flags |= QDeclarativePropertyCache::Data::IsConstant;
    if (p.isWritable())
        flags |= QDeclarativePropertyCache::Data::IsWritable;
    if (p.isResettable())
        flags |= QDeclarativePropertyCache::Data::IsResettable;
    if (p.isFinal())
        flags |= QDeclarativePropertyCache::Data::IsFinal;
    if (p.isEnumType())
        flags |= QDeclarativePropertyCache::Data::IsEnumType;

    return flags;
}
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");
}
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"));
}
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());
  const QVariant value = prop.read(m_obj.data());
  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 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(value);
    }
  } else if (role == Qt::EditRole) {
    if (index.column() == 1 && prop.isWritable()) {
      return value;
    }
  } else if (role == Qt::ToolTipRole) {
    return detailString(prop);
  } else if (role == PropertyModel::ActionRole) {
    return (prop.isResettable() ? PropertyModel::Reset : PropertyModel::NoAction)
         | ((MetaObjectRepository::instance()->metaObject(value.typeName()) && *reinterpret_cast<void* const*>(value.data())) || value.value<QObject*>()
            ? PropertyModel::NavigateTo
            : PropertyModel::NoAction);
  } else if (role == PropertyModel::ValueRole) {
    return value;
  } else if (role == PropertyModel::AppropriateToolRole) {
    ToolModel *toolModel = Probe::instance()->toolModel();
    ToolFactory *factory;
    if (value.canConvert<QObject*>())
      factory = toolModel->data(toolModel->toolForObject(value.value<QObject*>()), ToolModelRole::ToolFactory).value<ToolFactory*>();
    else
      factory = toolModel->data(toolModel->toolForObject(*reinterpret_cast<void* const*>(value.data()), value.typeName()), ToolModelRole::ToolFactory).value<ToolFactory*>();
    if (factory) {
      return factory->name();
    }
    return QVariant();
  }

  return QVariant();
}
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;
}