forked from qt-creator/qt-creator
QmlDesigner: Introduction of PropertyMetaInfo
Because the project storage is integer id based the string based API isn't fitting well for the new approach. PropertyMetaInfo can be easier mapped to the project storage. Task-number: QDS-7197 Change-Id: I49bc650abdaacf4b039d76c2514b5ad05ec84abe Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -28,10 +28,13 @@
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
using PropertyName = QByteArray;
|
||||
using PropertyNameList = QList<PropertyName>;
|
||||
using PropertyNames = std::vector<PropertyName>;
|
||||
using TypeName = QByteArray;
|
||||
|
||||
}
|
||||
|
@@ -143,6 +143,8 @@ void ActionEditor::setModelNode(const ModelNode &modelNode)
|
||||
m_modelNode = modelNode;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool isLiteral(QmlJS::AST::Node *ast)
|
||||
{
|
||||
if (QmlJS::AST::cast<QmlJS::AST::StringLiteral *>(ast)
|
||||
@@ -154,6 +156,17 @@ bool isLiteral(QmlJS::AST::Node *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeName skipCpp(TypeName typeName)
|
||||
{
|
||||
// TODO remove after project storage introduction
|
||||
|
||||
if (typeName.contains("<cpp>."))
|
||||
typeName.remove(0, 6);
|
||||
|
||||
return typeName;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void ActionEditor::prepareConnections()
|
||||
{
|
||||
if (!m_modelNode.isValid())
|
||||
@@ -197,17 +210,15 @@ void ActionEditor::prepareConnections()
|
||||
|
||||
ActionEditorDialog::ConnectionOption connection(modelNode.id());
|
||||
|
||||
for (const auto &propertyName : modelNode.metaInfo().propertyNames()) {
|
||||
if (!typeWhiteList.contains(modelNode.metaInfo().propertyTypeName(propertyName)))
|
||||
for (const auto &property : modelNode.metaInfo().properties()) {
|
||||
const auto &propertyTypeName = property.propertyTypeName();
|
||||
if (!typeWhiteList.contains(propertyTypeName))
|
||||
continue;
|
||||
|
||||
const QString name = QString::fromUtf8(propertyName);
|
||||
const bool writeable = modelNode.metaInfo().propertyIsWritable(propertyName);
|
||||
TypeName type = modelNode.metaInfo().propertyTypeName(propertyName);
|
||||
if (type.contains("<cpp>."))
|
||||
type.remove(0, 6);
|
||||
|
||||
connection.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
|
||||
connection.properties.append(
|
||||
ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()),
|
||||
skipCpp(std::move(propertyTypeName)),
|
||||
property.isWritable()));
|
||||
}
|
||||
|
||||
for (const VariantProperty &variantProperty : modelNode.variantProperties()) {
|
||||
@@ -216,12 +227,12 @@ void ActionEditor::prepareConnections()
|
||||
continue;
|
||||
|
||||
const QString name = QString::fromUtf8(variantProperty.name());
|
||||
const bool writeable = modelNode.metaInfo().propertyIsWritable(variantProperty.name());
|
||||
TypeName type = variantProperty.dynamicTypeName();
|
||||
if (type.contains("<cpp>."))
|
||||
type.remove(0, 6);
|
||||
const bool writeable = modelNode.metaInfo().property(variantProperty.name()).isWritable();
|
||||
|
||||
connection.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
|
||||
connection.properties.append(
|
||||
ActionEditorDialog::PropertyOption(name,
|
||||
skipCpp(variantProperty.dynamicTypeName()),
|
||||
writeable));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,18 +270,16 @@ void ActionEditor::prepareConnections()
|
||||
NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo(data.typeName.toUtf8());
|
||||
if (metaInfo.isValid()) {
|
||||
ActionEditorDialog::SingletonOption singelton;
|
||||
for (const PropertyName &propertyName : metaInfo.propertyNames()) {
|
||||
TypeName type = metaInfo.propertyTypeName(propertyName);
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
const TypeName &typeName = property.propertyTypeName();
|
||||
|
||||
if (!typeWhiteList.contains(type))
|
||||
if (!typeWhiteList.contains(typeName))
|
||||
continue;
|
||||
|
||||
const QString name = QString::fromUtf8(propertyName);
|
||||
const bool writeable = metaInfo.propertyIsWritable(propertyName);
|
||||
if (type.contains("<cpp>."))
|
||||
type.remove(0, 6);
|
||||
|
||||
singelton.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
|
||||
singelton.properties.append(
|
||||
ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()),
|
||||
skipCpp(typeName),
|
||||
property.isWritable()));
|
||||
}
|
||||
|
||||
if (!singelton.properties.isEmpty()) {
|
||||
|
@@ -113,7 +113,7 @@ void BindingEditor::setBackendValue(const QVariant &backendValue)
|
||||
const ModelNode node = propertyEditorValue->modelNode();
|
||||
|
||||
if (node.isValid()) {
|
||||
m_backendValueTypeName = node.metaInfo().propertyTypeName(propertyEditorValue->name());
|
||||
m_backendValueTypeName = node.metaInfo().property(propertyEditorValue->name()).propertyTypeName();
|
||||
|
||||
QString nodeId = node.id();
|
||||
if (nodeId.isEmpty())
|
||||
@@ -205,14 +205,14 @@ void BindingEditor::prepareBindings()
|
||||
|
||||
for (const auto &objnode : allNodes) {
|
||||
BindingEditorDialog::BindingOption binding;
|
||||
for (const auto &propertyName : objnode.metaInfo().propertyNames()) {
|
||||
TypeName propertyTypeName = objnode.metaInfo().propertyTypeName(propertyName);
|
||||
for (const auto &property : objnode.metaInfo().properties()) {
|
||||
const TypeName &propertyTypeName = property.propertyTypeName();
|
||||
|
||||
if (skipTypeFiltering
|
||||
|| (m_backendValueTypeName == propertyTypeName)
|
||||
|| isVariant(propertyTypeName)
|
||||
|| (targetTypeIsNumeric && isNumeric(propertyTypeName))) {
|
||||
binding.properties.append(QString::fromUtf8(propertyName));
|
||||
binding.properties.append(QString::fromUtf8(property.name()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,15 +259,15 @@ void BindingEditor::prepareBindings()
|
||||
if (metaInfo.isValid()) {
|
||||
BindingEditorDialog::BindingOption binding;
|
||||
|
||||
for (const PropertyName &propertyName : metaInfo.propertyNames()) {
|
||||
TypeName propertyTypeName = metaInfo.propertyTypeName(propertyName);
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
TypeName propertyTypeName = property.propertyTypeName();
|
||||
|
||||
if (skipTypeFiltering
|
||||
|| (m_backendValueTypeName == propertyTypeName)
|
||||
|| (isVariant(propertyTypeName))
|
||||
|| (targetTypeIsNumeric && isNumeric(propertyTypeName))
|
||||
|| (isColor(m_backendValueTypeName) && isColor(propertyTypeName))) {
|
||||
binding.properties.append(QString::fromUtf8(propertyName));
|
||||
binding.properties.append(QString::fromUtf8(property.name()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -39,6 +39,8 @@
|
||||
#include <qmlitemnode.h>
|
||||
#include <nodeabstractproperty.h>
|
||||
|
||||
#include <utils/set_algorithm.h>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QTableView>
|
||||
@@ -137,6 +139,20 @@ void SignalList::setModelNode(const ModelNode &modelNode)
|
||||
m_modelNode = modelNode;
|
||||
}
|
||||
|
||||
namespace {
|
||||
template<typename Callback>
|
||||
void callOnlyMouseSignalNames(const PropertyNameList &signalNames,
|
||||
const PropertyNameList &mouseSignalNames,
|
||||
const Callback &callback)
|
||||
{
|
||||
std::set_union(signalNames.begin(),
|
||||
signalNames.end(),
|
||||
mouseSignalNames.begin(),
|
||||
mouseSignalNames.end(),
|
||||
Utils::make_iterator(callback));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SignalList::prepareSignals()
|
||||
{
|
||||
if (!m_modelNode.isValid())
|
||||
@@ -145,27 +161,21 @@ void SignalList::prepareSignals()
|
||||
QList<QmlConnections> connections = QmlFlowViewNode::getAssociatedConnections(m_modelNode);
|
||||
|
||||
for (ModelNode &node : m_modelNode.view()->allModelNodes()) {
|
||||
// Collect all items which contain at least one of the specified signals
|
||||
const PropertyNameList signalNames = node.metaInfo().signalNames();
|
||||
// Put the signals into a QSet to avoid duplicates
|
||||
auto signalNamesSet = QSet<PropertyName>(signalNames.begin(), signalNames.end());
|
||||
for (const PropertyName &signal : signalNamesSet) {
|
||||
if (QmlFlowViewNode::st_mouseSignals.contains(signal))
|
||||
appendSignalToModel(connections, node, signal);
|
||||
}
|
||||
callOnlyMouseSignalNames(node.metaInfo().signalNames(),
|
||||
QmlFlowViewNode::mouseSignals(),
|
||||
[&](const PropertyName &signal) {
|
||||
appendSignalToModel(connections, node, signal);
|
||||
});
|
||||
|
||||
// Gather valid properties and aliases from components
|
||||
for (const PropertyName &property : node.metaInfo().propertyNames()) {
|
||||
const TypeName propertyType = node.metaInfo().propertyTypeName(property);
|
||||
const NodeMetaInfo info = m_modelNode.model()->metaInfo(propertyType);
|
||||
// Collect all items which contain at least one of the specified signals
|
||||
const PropertyNameList signalNames = info.signalNames();
|
||||
// Put the signals into a QSet to avoid duplicates
|
||||
auto signalNamesSet = QSet<PropertyName>(signalNames.begin(), signalNames.end());
|
||||
for (const PropertyName &signal : signalNamesSet) {
|
||||
if (QmlFlowViewNode::st_mouseSignals.contains(signal))
|
||||
appendSignalToModel(connections, node, signal, property);
|
||||
}
|
||||
for (const auto &property : node.metaInfo().properties()) {
|
||||
const NodeMetaInfo info = m_modelNode.model()->metaInfo(property.propertyTypeName());
|
||||
|
||||
callOnlyMouseSignalNames(info.signalNames(),
|
||||
QmlFlowViewNode::mouseSignals(),
|
||||
[&](const PropertyName &signal) {
|
||||
appendSignalToModel(connections, node, signal);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -568,11 +568,17 @@ void layoutGridLayout(const SelectionContext &selectionContext)
|
||||
}
|
||||
}
|
||||
|
||||
static PropertyNameList sortedPropertyNameList(const PropertyNameList &nameList)
|
||||
static PropertyNameList sortedPropertyNameList(const PropertyMetaInfos &properties)
|
||||
{
|
||||
PropertyNameList sortedPropertyNameList = nameList;
|
||||
std::stable_sort(sortedPropertyNameList.begin(), sortedPropertyNameList.end());
|
||||
return sortedPropertyNameList;
|
||||
auto propertyNames = Utils::transform<PropertyNameList>(properties, [](const auto &property) {
|
||||
return property.name();
|
||||
});
|
||||
|
||||
std::sort(propertyNames.begin(), propertyNames.end());
|
||||
|
||||
propertyNames.erase(std::unique(propertyNames.begin(), propertyNames.end()), propertyNames.end());
|
||||
|
||||
return propertyNames;
|
||||
}
|
||||
|
||||
static QString toUpper(const QString &signal)
|
||||
@@ -628,12 +634,14 @@ static QStringList getSortedSignalNameList(const ModelNode &modelNode)
|
||||
QStringList signalNames;
|
||||
|
||||
if (metaInfo.isValid()) {
|
||||
const PropertyNameList signalNameList = sortedPropertyNameList(metaInfo.signalNames());
|
||||
// TODO seem to be broken because there can be properties without notifier and the notifier can be even have a different name
|
||||
|
||||
const PropertyNameList signalNameList = metaInfo.signalNames();
|
||||
for (const PropertyName &signalName : signalNameList)
|
||||
if (!signalName.contains("Changed"))
|
||||
signalNames.append(QString::fromUtf8(signalName));
|
||||
|
||||
const PropertyNameList propertyNameList = sortedPropertyNameList(metaInfo.propertyNames());
|
||||
const PropertyNameList propertyNameList = sortedPropertyNameList(metaInfo.properties());
|
||||
for (const PropertyName &propertyName : propertyNameList)
|
||||
if (!propertyName.contains("."))
|
||||
signalNames.append(QString::fromUtf8(propertyName + "Changed"));
|
||||
|
@@ -138,14 +138,15 @@ QStringList BindingModel::possibleTargetProperties(const BindingProperty &bindin
|
||||
NodeMetaInfo metaInfo = modelNode.metaInfo();
|
||||
|
||||
if (metaInfo.isValid()) {
|
||||
QStringList possibleProperties;
|
||||
const QList<PropertyName> propertyNames = metaInfo.propertyNames();
|
||||
for (const PropertyName &propertyName : propertyNames) {
|
||||
if (metaInfo.propertyIsWritable(propertyName))
|
||||
possibleProperties << QString::fromUtf8(propertyName);
|
||||
const auto properties = metaInfo.properties();
|
||||
QStringList writableProperties;
|
||||
writableProperties.reserve(static_cast<int>(properties.size()));
|
||||
for (const auto &property : properties) {
|
||||
if (property.isWritable())
|
||||
writableProperties.push_back(QString::fromUtf8(property.name()));
|
||||
}
|
||||
|
||||
return possibleProperties;
|
||||
return writableProperties;
|
||||
}
|
||||
|
||||
return QStringList();
|
||||
@@ -159,11 +160,10 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin
|
||||
|
||||
TypeName typeName;
|
||||
|
||||
if (bindingProperty.parentModelNode().metaInfo().isValid()) {
|
||||
typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name());
|
||||
} else {
|
||||
if (auto metaInfo = bindingProperty.parentModelNode().metaInfo(); metaInfo.isValid())
|
||||
typeName = metaInfo.property(bindingProperty.name()).propertyTypeName();
|
||||
else
|
||||
qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
|
||||
}
|
||||
|
||||
const QString &id = stringlist.constFirst();
|
||||
|
||||
@@ -178,9 +178,9 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin
|
||||
NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
||||
|
||||
if (metaInfo.isValid()) {
|
||||
for (const PropertyName &propertyName : metaInfo.propertyNames()) {
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
//without check for now
|
||||
possibleProperties << QString::fromUtf8(propertyName);
|
||||
possibleProperties.push_back(QString::fromUtf8(property.name()));
|
||||
}
|
||||
|
||||
return possibleProperties;
|
||||
@@ -207,9 +207,9 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin
|
||||
}
|
||||
|
||||
if (metaInfo.isValid()) {
|
||||
for (const PropertyName &propertyName : metaInfo.propertyNames()) {
|
||||
if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
|
||||
possibleProperties << QString::fromUtf8(propertyName);
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
if (property.propertyTypeName() == typeName) //### todo proper check
|
||||
possibleProperties.push_back(QString::fromUtf8(property.name()));
|
||||
}
|
||||
} else {
|
||||
qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node";
|
||||
@@ -233,10 +233,9 @@ static PropertyName unusedProperty(const ModelNode &modelNode)
|
||||
{
|
||||
PropertyName propertyName = "none";
|
||||
if (modelNode.metaInfo().isValid()) {
|
||||
const QList<PropertyName> propertyNames = modelNode.metaInfo().propertyNames();
|
||||
for (const PropertyName &propertyName : propertyNames) {
|
||||
if (modelNode.metaInfo().propertyIsWritable(propertyName) && !modelNode.hasProperty(propertyName))
|
||||
return propertyName;
|
||||
for (const auto &property : modelNode.metaInfo().properties()) {
|
||||
if (property.isWritable() && !modelNode.hasProperty(propertyName))
|
||||
return property.name();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -475,7 +475,7 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co
|
||||
auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) {
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) {
|
||||
NodeMetaInfo propertyMetaInfo = connectionView()->model()->metaInfo(
|
||||
metaInfo.propertyTypeName(aliasPart.toUtf8()));
|
||||
metaInfo.property(aliasPart.toUtf8()).propertyTypeName());
|
||||
if (propertyMetaInfo.isValid()) {
|
||||
return propertyNameListToStringList(propertyMetaInfo.signalNames());
|
||||
}
|
||||
|
@@ -216,8 +216,9 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
return;
|
||||
|
||||
const ModelNode node = property.parentModelNode();
|
||||
const TypeName typeName = property.isDynamic() ? property.dynamicTypeName()
|
||||
: node.metaInfo().propertyTypeName(property.name());
|
||||
const TypeName typeName = property.isDynamic()
|
||||
? property.dynamicTypeName()
|
||||
: node.metaInfo().property(property.name()).propertyTypeName();
|
||||
|
||||
const QString targetName = node.displayName() + "." + property.name();
|
||||
|
||||
|
@@ -298,23 +298,19 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
||||
|
||||
auto addMetaInfoProperties = [&](const NodeMetaInfo& itemMetaInfo, QString itemName){
|
||||
if (itemMetaInfo.isValid()) {
|
||||
for (const PropertyName &propertyName : itemMetaInfo.propertyNames()) {
|
||||
TypeName propertyType = itemMetaInfo.propertyTypeName(propertyName);
|
||||
for (const auto &property : itemMetaInfo.properties()) {
|
||||
TypeName propertyType = property.propertyTypeName();
|
||||
if (!propertyType.isEmpty()) {
|
||||
//first letter is a reliable item indicator
|
||||
QChar firstLetter = QString::fromUtf8(propertyType).at(0);
|
||||
if (firstLetter.isLetter() && firstLetter.isUpper()) {
|
||||
if (!itemMetaInfo.propertyIsEnumType(propertyName)
|
||||
&& !itemMetaInfo.propertyIsPrivate(propertyName)
|
||||
&& !itemMetaInfo.propertyIsListProperty(propertyName)
|
||||
&& !itemMetaInfo.propertyIsPointer(propertyName)) {
|
||||
if (!property.isEnumType() && !property.isPrivate()
|
||||
&& !property.isListProperty() && !property.isPointer()) {
|
||||
NodeMetaInfo propertyMetaInfo =
|
||||
connectionModel->connectionView()->model()->metaInfo(propertyType);
|
||||
if (propertyMetaInfo.isValid()) {
|
||||
if (propertyMetaInfo.isQmlItem()) {
|
||||
connectionComboBox->addItem(itemName
|
||||
+ "."
|
||||
+ propertyName);
|
||||
connectionComboBox->addItem(itemName + "." + property.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QMessageBox>
|
||||
@@ -345,10 +346,9 @@ QStringList DynamicPropertiesModel::possibleTargetProperties(const BindingProper
|
||||
|
||||
if (metaInfo.isValid()) {
|
||||
QStringList possibleProperties;
|
||||
const QList<PropertyName> propertyNames = metaInfo.propertyNames();
|
||||
for (const PropertyName &propertyName : propertyNames) {
|
||||
if (metaInfo.propertyIsWritable(propertyName))
|
||||
possibleProperties << QString::fromUtf8(propertyName);
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
if (property.isWritable())
|
||||
possibleProperties.push_back(QString::fromUtf8(property.name()));
|
||||
}
|
||||
|
||||
return possibleProperties;
|
||||
@@ -383,8 +383,8 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper
|
||||
|
||||
PropertyName typeName;
|
||||
|
||||
if (bindingProperty.parentModelNode().metaInfo().isValid()) {
|
||||
typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name());
|
||||
if (auto metaInfo = bindingProperty.parentModelNode().metaInfo(); metaInfo.isValid()) {
|
||||
typeName = metaInfo.property(bindingProperty.name()).propertyTypeName();
|
||||
} else {
|
||||
qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
|
||||
}
|
||||
@@ -402,10 +402,9 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper
|
||||
|
||||
if (metaInfo.isValid()) {
|
||||
QStringList possibleProperties;
|
||||
const QList<PropertyName> propertyNames = metaInfo.propertyNames();
|
||||
for (const PropertyName &propertyName : propertyNames) {
|
||||
if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
|
||||
possibleProperties << QString::fromUtf8(propertyName);
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
if (property.propertyTypeName() == typeName) //### todo proper check
|
||||
possibleProperties.push_back(QString::fromUtf8(property.name()));
|
||||
}
|
||||
return possibleProperties;
|
||||
} else {
|
||||
|
@@ -658,7 +658,7 @@ void DesignDocument::paste()
|
||||
PropertyName defaultProperty(targetNode.metaInfo().defaultPropertyName());
|
||||
|
||||
scatterItem(pastedNode, targetNode);
|
||||
if (targetNode.metaInfo().propertyIsListProperty(defaultProperty))
|
||||
if (targetNode.metaInfo().property(defaultProperty).isListProperty())
|
||||
targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode);
|
||||
else
|
||||
qWarning() << "Cannot reparent to" << targetNode;
|
||||
|
@@ -99,7 +99,8 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName)
|
||||
QTC_ASSERT(metaInfo.isValid(), return);
|
||||
|
||||
// Create a list of properties available for the new type
|
||||
PropertyNameList propertiesAndSignals(metaInfo.propertyNames());
|
||||
PropertyNameList propertiesAndSignals = Utils::transform<PropertyNameList>(
|
||||
metaInfo.properties(), [](const auto &property) { return property.name(); });
|
||||
// Add signals to the list
|
||||
const PropertyNameList signalNames = metaInfo.signalNames();
|
||||
for (const PropertyName &signal : signalNames) {
|
||||
|
@@ -270,9 +270,12 @@ void MaterialEditorQmlBackend::setup(const QmlObjectNode &selectedMaterialNode,
|
||||
if (selectedMaterialNode.isValid()) {
|
||||
m_contextObject->setModel(materialEditor->model());
|
||||
|
||||
const PropertyNameList propertyNames = selectedMaterialNode.modelNode().metaInfo().propertyNames();
|
||||
for (const PropertyName &propertyName : propertyNames)
|
||||
createPropertyEditorValue(selectedMaterialNode, propertyName, selectedMaterialNode.instanceValue(propertyName), materialEditor);
|
||||
for (const auto &property : selectedMaterialNode.modelNode().metaInfo().properties()) {
|
||||
createPropertyEditorValue(selectedMaterialNode,
|
||||
property.name(),
|
||||
selectedMaterialNode.instanceValue(property.name()),
|
||||
materialEditor);
|
||||
}
|
||||
|
||||
// model node
|
||||
m_backendModelNode.setup(selectedMaterialNode.modelNode());
|
||||
|
@@ -125,7 +125,7 @@ void MaterialEditorView::changeValue(const QString &name)
|
||||
QVariant castedValue;
|
||||
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) {
|
||||
castedValue = metaInfo.propertyCastedValue(propertyName, value->value());
|
||||
castedValue = metaInfo.property(propertyName).castedValue(value->value());
|
||||
} else {
|
||||
qWarning() << __FUNCTION__ << propertyName << "cannot be casted (metainfo)";
|
||||
return;
|
||||
@@ -139,8 +139,7 @@ void MaterialEditorView::changeValue(const QString &name)
|
||||
bool propertyTypeUrl = false;
|
||||
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) {
|
||||
if (metaInfo.propertyTypeName(propertyName) == "QUrl"
|
||||
|| metaInfo.propertyTypeName(propertyName) == "url") {
|
||||
if (metaInfo.property(propertyName).hasPropertyTypeName("QUrl", "url")) {
|
||||
// turn absolute local file paths into relative paths
|
||||
propertyTypeUrl = true;
|
||||
QString filePath = castedValue.toUrl().toString();
|
||||
@@ -202,13 +201,15 @@ void MaterialEditorView::changeExpression(const QString &propertyName)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_selectedMaterial.metaInfo().isValid() && m_selectedMaterial.metaInfo().hasProperty(name)) {
|
||||
if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "QColor") {
|
||||
if (auto metaInfo = m_selectedMaterial.metaInfo();
|
||||
metaInfo.isValid() && metaInfo.hasProperty(name)) {
|
||||
auto propertyTypeName = metaInfo.property(name).propertyTypeName();
|
||||
if (propertyTypeName == "QColor") {
|
||||
if (QColor(value->expression().remove('"')).isValid()) {
|
||||
qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"')));
|
||||
return;
|
||||
}
|
||||
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "bool") {
|
||||
} else if (propertyTypeName == "bool") {
|
||||
if (isTrueFalseLiteral(value->expression())) {
|
||||
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
|
||||
qmlObjectNode.setVariantProperty(name, true);
|
||||
@@ -216,21 +217,21 @@ void MaterialEditorView::changeExpression(const QString &propertyName)
|
||||
qmlObjectNode.setVariantProperty(name, false);
|
||||
return;
|
||||
}
|
||||
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "int") {
|
||||
} else if (propertyTypeName == "int") {
|
||||
bool ok;
|
||||
int intValue = value->expression().toInt(&ok);
|
||||
if (ok) {
|
||||
qmlObjectNode.setVariantProperty(name, intValue);
|
||||
return;
|
||||
}
|
||||
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "qreal") {
|
||||
} else if (propertyTypeName == "qreal") {
|
||||
bool ok;
|
||||
qreal realValue = value->expression().toDouble(&ok);
|
||||
if (ok) {
|
||||
qmlObjectNode.setVariantProperty(name, realValue);
|
||||
return;
|
||||
}
|
||||
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "QVariant") {
|
||||
} else if (propertyTypeName == "QVariant") {
|
||||
bool ok;
|
||||
qreal realValue = value->expression().toDouble(&ok);
|
||||
if (ok) {
|
||||
@@ -809,7 +810,7 @@ void QmlDesigner::MaterialEditorView::highlightSupportedProperties(bool highligh
|
||||
QTC_ASSERT(metaInfo.isValid(), return);
|
||||
|
||||
for (const QString &propName : propNames) {
|
||||
if (metaInfo.propertyTypeName(propName.toLatin1()) == "QtQuick3D.Texture") {
|
||||
if (metaInfo.property(propName.toUtf8()).hasPropertyTypeName("QtQuick3D.Texture")) {
|
||||
QObject *propEditorValObj = propMap.value(propName).value<QObject *>();
|
||||
PropertyEditorValue *propEditorVal = qobject_cast<PropertyEditorValue *>(propEditorValObj);
|
||||
propEditorVal->setHasActiveDrag(highlight);
|
||||
|
@@ -65,11 +65,10 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.DefaultMaterial")
|
||||
|| parentInfo.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
|
||||
// All texture properties are valid targets
|
||||
const PropertyNameList targetNodeNameList = parentInfo.propertyNames();
|
||||
for (const PropertyName &name : targetNodeNameList) {
|
||||
TypeName propType = parentInfo.propertyTypeName(name);
|
||||
for (const auto &property : parentInfo.properties()) {
|
||||
const TypeName &propType = property.propertyTypeName();
|
||||
if (propType == textureType || propType == textureTypeCpp) {
|
||||
propertyList.append(QString::fromLatin1(name));
|
||||
propertyList.append(QString::fromUtf8(property.name()));
|
||||
if (breakOnFirst)
|
||||
return;
|
||||
}
|
||||
@@ -168,15 +167,13 @@ ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
|
||||
|
||||
// Create dialog for selecting writable properties of exact property type
|
||||
ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
|
||||
const ModelNode &targetNode, TypeName type, QWidget *parent)
|
||||
const ModelNode &targetNode, TypeName propertyType, QWidget *parent)
|
||||
{
|
||||
const NodeMetaInfo metaInfo = targetNode.metaInfo();
|
||||
const PropertyNameList propNames = metaInfo.propertyNames();
|
||||
const TypeName property(type);
|
||||
QStringList matchingNames;
|
||||
for (const auto &propName : propNames) {
|
||||
if (metaInfo.propertyTypeName(propName) == property && metaInfo.propertyIsWritable(propName))
|
||||
matchingNames.append(QString::fromLatin1(propName));
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
if (property.hasPropertyTypeName(propertyType) && property.isWritable())
|
||||
matchingNames.append(QString::fromUtf8(property.name()));
|
||||
}
|
||||
|
||||
if (!matchingNames.isEmpty())
|
||||
|
@@ -725,7 +725,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
||||
}
|
||||
}
|
||||
|
||||
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
|
||||
if (targetNode.metaInfo().property(selectedProp).isListProperty()) {
|
||||
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
|
||||
listProp.addModelNodeToArray(newModelNode);
|
||||
validContainer = true;
|
||||
@@ -1105,7 +1105,7 @@ ModelNode NavigatorTreeModel::createTextureNode(const NodeAbstractProperty &targ
|
||||
|
||||
TypeName propertyType(const NodeAbstractProperty &property)
|
||||
{
|
||||
return property.parentModelNode().metaInfo().propertyTypeName(property.name());
|
||||
return property.parentModelNode().metaInfo().property(property.name()).propertyTypeName();
|
||||
}
|
||||
|
||||
void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProperty,
|
||||
|
@@ -220,7 +220,10 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
||||
}
|
||||
|
||||
// Create a list of properties available for the new type
|
||||
QList<PropertyName> propertiesAndSignals(metaInfo.propertyNames());
|
||||
auto propertiesAndSignals = Utils::transform<PropertyNameList>(metaInfo.properties(),
|
||||
[](const auto &property) {
|
||||
return property.name();
|
||||
});
|
||||
// Add signals to the list
|
||||
for (const auto &signal : metaInfo.signalNames()) {
|
||||
if (signal.isEmpty())
|
||||
|
@@ -25,8 +25,9 @@
|
||||
|
||||
#include "propertyeditorqmlbackend.h"
|
||||
|
||||
#include "propertyeditorvalue.h"
|
||||
#include "propertyeditortransaction.h"
|
||||
#include "propertyeditorvalue.h"
|
||||
#include "propertymetainfo.h"
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <qmltimeline.h>
|
||||
@@ -415,10 +416,13 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
|
||||
if (propertyEditorBenchmark().isInfoEnabled())
|
||||
time.start();
|
||||
|
||||
const QList<PropertyName> propertyNames = qmlObjectNode.modelNode().metaInfo().propertyNames();
|
||||
for (const PropertyName &propertyName : propertyNames)
|
||||
createPropertyEditorValue(qmlObjectNode, propertyName, qmlObjectNode.instanceValue(propertyName), propertyEditor);
|
||||
|
||||
for (const auto &property : qmlObjectNode.modelNode().metaInfo().properties()) {
|
||||
auto propertyName = property.name();
|
||||
createPropertyEditorValue(qmlObjectNode,
|
||||
propertyName,
|
||||
qmlObjectNode.instanceValue(propertyName),
|
||||
propertyEditor);
|
||||
}
|
||||
setupLayoutAttachedProperties(qmlObjectNode, propertyEditor);
|
||||
setupAuxiliaryProperties(qmlObjectNode, propertyEditor);
|
||||
|
||||
@@ -514,9 +518,11 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl
|
||||
{
|
||||
NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo(typeName);
|
||||
|
||||
const QList<PropertyName> propertyNames = metaInfo.propertyNames();
|
||||
for (const PropertyName &propertyName : propertyNames)
|
||||
setupPropertyEditorValue(propertyName, propertyEditor, QString::fromUtf8(metaInfo.propertyTypeName(propertyName)));
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
setupPropertyEditorValue(property.name(),
|
||||
propertyEditor,
|
||||
QString::fromUtf8(property.propertyTypeName()));
|
||||
}
|
||||
|
||||
auto valueObject = qobject_cast<PropertyEditorValue *>(variantToQObject(
|
||||
m_backendValuesPropertyMap.value(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY)));
|
||||
@@ -579,7 +585,7 @@ inline bool dotPropertyHeuristic(const QmlObjectNode &node, const NodeMetaInfo &
|
||||
const PropertyName parentProperty = list.first();
|
||||
const PropertyName itemProperty = list.last();
|
||||
|
||||
TypeName typeName = type.propertyTypeName(parentProperty);
|
||||
TypeName typeName = type.property(parentProperty).propertyTypeName();
|
||||
|
||||
NodeMetaInfo itemInfo = node.view()->model()->metaInfo("QtQuick.Item");
|
||||
NodeMetaInfo textInfo = node.view()->model()->metaInfo("QtQuick.Text");
|
||||
@@ -596,7 +602,7 @@ inline bool dotPropertyHeuristic(const QmlObjectNode &node, const NodeMetaInfo &
|
||||
return true;
|
||||
}
|
||||
|
||||
QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &metaType,
|
||||
const NodeMetaInfo &superType,
|
||||
const QmlObjectNode &node)
|
||||
{
|
||||
@@ -615,20 +621,22 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
allTypes.append(variantToStringList(node->property("typeNames").value));
|
||||
}
|
||||
|
||||
const QList<PropertyName> allProperties = type.propertyNames();
|
||||
|
||||
QMap<PropertyName, QList<PropertyName>> propertyMap;
|
||||
QList<PropertyName> separateSectionProperties;
|
||||
auto propertyMetaInfoCompare = [](const auto &first, const auto &second) {
|
||||
return first.name() < second.name();
|
||||
};
|
||||
std::map<PropertyMetaInfo, PropertyMetaInfos, decltype(propertyMetaInfoCompare)> propertyMap(
|
||||
propertyMetaInfoCompare);
|
||||
PropertyMetaInfos separateSectionProperties;
|
||||
|
||||
// Iterate over all properties and isolate the properties which have their own template
|
||||
for (const PropertyName &propertyName : allProperties) {
|
||||
for (const auto &property : metaType.properties()) {
|
||||
const auto &propertyName = property.name();
|
||||
if (propertyName.startsWith("__"))
|
||||
continue; // private API
|
||||
|
||||
if (!superType.hasProperty(propertyName)
|
||||
&& type.propertyIsWritable(propertyName)
|
||||
&& dotPropertyHeuristic(node, type, propertyName)) {
|
||||
QString typeName = QString::fromLatin1(type.propertyTypeName(propertyName));
|
||||
if (!superType.hasProperty(propertyName) // TODO add property.isLocalProperty()
|
||||
&& property.isWritable() && dotPropertyHeuristic(node, metaType, propertyName)) {
|
||||
QString typeName = QString::fromUtf8(property.propertyTypeName());
|
||||
|
||||
if (typeName == "alias" && node.isValid())
|
||||
typeName = QString::fromLatin1(node.instanceType(propertyName));
|
||||
@@ -636,18 +644,16 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
// Check if a template for the type exists
|
||||
if (allTypes.contains(typeName)) {
|
||||
if (separateSectionTypes.contains(typeName)) { // template enforces separate section
|
||||
separateSectionProperties.append(propertyName);
|
||||
separateSectionProperties.push_back(property);
|
||||
} else {
|
||||
if (propertyName.contains('.')) {
|
||||
const PropertyName parentProperty = propertyName.split('.').first();
|
||||
const PropertyName parentPropertyName = propertyName.split('.').first();
|
||||
const PropertyMetaInfo parentProperty = metaType.property(
|
||||
parentPropertyName);
|
||||
|
||||
if (propertyMap.contains(parentProperty))
|
||||
propertyMap[parentProperty].append(propertyName);
|
||||
else
|
||||
propertyMap[parentProperty] = { propertyName };
|
||||
propertyMap[parentProperty].push_back(property);
|
||||
} else {
|
||||
if (!propertyMap.contains(propertyName))
|
||||
propertyMap[propertyName] = {};
|
||||
propertyMap[property];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,28 +661,29 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
}
|
||||
|
||||
// Filter out the properties which have a basic type e.g. int, string, bool
|
||||
QList<PropertyName> basicProperties;
|
||||
PropertyMetaInfos basicProperties;
|
||||
auto it = propertyMap.begin();
|
||||
while (it != propertyMap.end()) {
|
||||
if (it.value().empty()) {
|
||||
basicProperties.append(it.key());
|
||||
if (it->second.empty()) {
|
||||
basicProperties.push_back(it->first);
|
||||
it = propertyMap.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
Utils::sort(basicProperties);
|
||||
Utils::sort(basicProperties, propertyMetaInfoCompare);
|
||||
|
||||
auto findAndFillTemplate = [&nodes, &node, &type](const PropertyName &label,
|
||||
const PropertyName &property) {
|
||||
PropertyName underscoreProperty = property;
|
||||
auto findAndFillTemplate = [&nodes, &node](const PropertyName &label,
|
||||
const PropertyMetaInfo &property) {
|
||||
const auto &propertyName = property.name();
|
||||
PropertyName underscoreProperty = propertyName;
|
||||
underscoreProperty.replace('.', '_');
|
||||
|
||||
TypeName typeName = type.propertyTypeName(property);
|
||||
TypeName typeName = property.propertyTypeName();
|
||||
// alias resolution only possible with instance
|
||||
if (typeName == "alias" && node.isValid())
|
||||
typeName = node.instanceType(property);
|
||||
typeName = node.instanceType(propertyName);
|
||||
|
||||
QString filledTemplate;
|
||||
for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) {
|
||||
@@ -730,8 +737,8 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
qmlInnerTemplate += "bottomPadding: 10\n";
|
||||
qmlInnerTemplate += "SectionLayout {\n";
|
||||
|
||||
for (const auto &p : qAsConst(basicProperties))
|
||||
qmlInnerTemplate += findAndFillTemplate(p, p);
|
||||
for (const auto &basicProperty : std::as_const(basicProperties))
|
||||
qmlInnerTemplate += findAndFillTemplate(basicProperty.name(), basicProperty);
|
||||
|
||||
qmlInnerTemplate += "}\n"; // SectionLayout
|
||||
qmlInnerTemplate += "}\n"; // Column
|
||||
@@ -740,16 +747,17 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
// Second the section containing properties of complex type for which no specific template exists e.g. Button
|
||||
if (!propertyMap.empty()) {
|
||||
emptyTemplate = false;
|
||||
for (auto it = propertyMap.cbegin(); it != propertyMap.cend(); ++it) {
|
||||
const auto &key = it.key();
|
||||
TypeName parentTypeName = type.propertyTypeName(key);
|
||||
for (auto &[property, properties] : propertyMap) {
|
||||
// for (auto it = propertyMap.cbegin(); it != propertyMap.cend(); ++it) {
|
||||
TypeName parentTypeName = property.propertyTypeName();
|
||||
// alias resolution only possible with instance
|
||||
if (parentTypeName == "alias" && node.isValid())
|
||||
parentTypeName = node.instanceType(key);
|
||||
parentTypeName = node.instanceType(property.name());
|
||||
|
||||
qmlInnerTemplate += "Section {\n";
|
||||
qmlInnerTemplate += QStringLiteral("caption: \"%1 - %2\"\n")
|
||||
.arg(QString::fromUtf8(key), QString::fromUtf8(parentTypeName));
|
||||
.arg(QString::fromUtf8(property.name()),
|
||||
QString::fromUtf8(parentTypeName));
|
||||
qmlInnerTemplate += anchorLeftRight;
|
||||
qmlInnerTemplate += "leftPadding: 8\n";
|
||||
qmlInnerTemplate += "rightPadding: 0\n";
|
||||
@@ -757,12 +765,14 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
qmlInnerTemplate += "level: 1\n";
|
||||
qmlInnerTemplate += "SectionLayout {\n";
|
||||
|
||||
auto properties = it.value();
|
||||
Utils::sort(properties);
|
||||
Utils::sort(properties, propertyMetaInfoCompare);
|
||||
|
||||
for (const auto &p : qAsConst(properties)) {
|
||||
const PropertyName shortName = p.contains('.') ? p.split('.').last() : p;
|
||||
qmlInnerTemplate += findAndFillTemplate(shortName, p);
|
||||
for (const auto &subProperty : properties) {
|
||||
const auto &propertyName = subProperty.name();
|
||||
auto found = std::find(propertyName.rbegin(), propertyName.rend(), '.');
|
||||
const PropertyName shortName{found.base(),
|
||||
std::distance(found.base(), propertyName.end())};
|
||||
qmlInnerTemplate += findAndFillTemplate(shortName, property);
|
||||
}
|
||||
|
||||
qmlInnerTemplate += "}\n"; // SectionLayout
|
||||
@@ -773,9 +783,9 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
||||
// Third the section containing properties of complex type for which a specific template exists e.g. Rectangle, Image
|
||||
if (!separateSectionProperties.empty()) {
|
||||
emptyTemplate = false;
|
||||
Utils::sort(separateSectionProperties);
|
||||
for (const auto &p : qAsConst(separateSectionProperties))
|
||||
qmlInnerTemplate += findAndFillTemplate(p, p);
|
||||
Utils::sort(separateSectionProperties, propertyMetaInfoCompare);
|
||||
for (const auto &property : separateSectionProperties)
|
||||
qmlInnerTemplate += findAndFillTemplate(property.name(), property);
|
||||
}
|
||||
|
||||
qmlInnerTemplate += "}\n"; // Column
|
||||
|
@@ -60,9 +60,13 @@ PropertyEditorValue::PropertyEditorValue(QObject *parent)
|
||||
QVariant PropertyEditorValue::value() const
|
||||
{
|
||||
QVariant returnValue = m_value;
|
||||
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
|
||||
if (modelNode().metaInfo().propertyTypeName(name()) == "QUrl")
|
||||
if (modelNode().isValid()) {
|
||||
if (auto metaInfo = modelNode().metaInfo();
|
||||
metaInfo.isValid() && metaInfo.hasProperty(name())
|
||||
&& metaInfo.property(name()).hasPropertyTypeName("QUrl", "url")) {
|
||||
returnValue = returnValue.toUrl().toString();
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -100,28 +104,30 @@ static void fixAmbigousColorNames(const QmlDesigner::ModelNode &modelNode,
|
||||
const QmlDesigner::PropertyName &name,
|
||||
QVariant *value)
|
||||
{
|
||||
if (modelNode.isValid() && modelNode.metaInfo().isValid()
|
||||
&& (modelNode.metaInfo().propertyTypeName(name) == "QColor"
|
||||
|| modelNode.metaInfo().propertyTypeName(name) == "color")) {
|
||||
if ((value->type() == QVariant::Color)) {
|
||||
QColor color = value->value<QColor>();
|
||||
int alpha = color.alpha();
|
||||
color = QColor(color.name());
|
||||
color.setAlpha(alpha);
|
||||
*value = color;
|
||||
} else if (value->toString() != QStringLiteral("transparent")) {
|
||||
*value = QColor(value->toString()).name(QColor::HexArgb);
|
||||
if (modelNode.isValid()) {
|
||||
if (auto metaInfo = modelNode.metaInfo();
|
||||
metaInfo.isValid() && metaInfo.property(name).hasPropertyTypeName("QColor", "color")) {
|
||||
if ((value->type() == QVariant::Color)) {
|
||||
QColor color = value->value<QColor>();
|
||||
int alpha = color.alpha();
|
||||
color = QColor(color.name());
|
||||
color.setAlpha(alpha);
|
||||
*value = color;
|
||||
} else if (value->toString() != QStringLiteral("transparent")) {
|
||||
*value = QColor(value->toString()).name(QColor::HexArgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fixUrl(const QmlDesigner::ModelNode &modelNode, const QmlDesigner::PropertyName &name, QVariant *value)
|
||||
{
|
||||
if (modelNode.isValid() && modelNode.metaInfo().isValid()
|
||||
&& (modelNode.metaInfo().propertyTypeName(name) == "QUrl"
|
||||
|| modelNode.metaInfo().propertyTypeName(name) == "url")) {
|
||||
if (!value->isValid())
|
||||
*value = QStringLiteral("");
|
||||
if (modelNode.isValid()) {
|
||||
if (auto metaInfo = modelNode.metaInfo();
|
||||
metaInfo.isValid() && metaInfo.property(name).hasPropertyTypeName("QUrl", "url"))
|
||||
|
||||
if (!value->isValid())
|
||||
*value = QStringLiteral("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,9 +146,13 @@ void PropertyEditorValue::setValueWithEmit(const QVariant &value)
|
||||
{
|
||||
if (!compareVariants(value, m_value ) || isBound()) {
|
||||
QVariant newValue = value;
|
||||
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
|
||||
if (modelNode().metaInfo().propertyTypeName(name()) == "QUrl")
|
||||
if (modelNode().isValid()) {
|
||||
if (auto metaInfo = modelNode().metaInfo();
|
||||
metaInfo.isValid() && metaInfo.hasProperty(name())
|
||||
&& metaInfo.property(name()).hasPropertyTypeName("QUrl")) {
|
||||
newValue = QUrl(newValue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (cleverDoubleCompare(newValue, m_value))
|
||||
return;
|
||||
@@ -255,12 +265,14 @@ void PropertyEditorValue::setIsValid(bool valid)
|
||||
|
||||
bool PropertyEditorValue::isTranslated() const
|
||||
{
|
||||
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) {
|
||||
if (modelNode().metaInfo().propertyTypeName(name()) == "QString" || modelNode().metaInfo().propertyTypeName(name()) == "string") {
|
||||
if (modelNode().isValid()) {
|
||||
if (auto metaInfo = modelNode().metaInfo();
|
||||
metaInfo.isValid() && metaInfo.hasProperty(name())
|
||||
&& metaInfo.property(name()).hasPropertyTypeName("QString", "string")) {
|
||||
const QmlDesigner::QmlObjectNode objectNode(modelNode());
|
||||
if (objectNode.isValid() && objectNode.hasBindingProperty(name())) {
|
||||
const QRegularExpression rx(QRegularExpression::anchoredPattern(
|
||||
"qsTr(|Id|anslate)\\(\".*\"\\)"));
|
||||
const QRegularExpression rx(
|
||||
QRegularExpression::anchoredPattern("qsTr(|Id|anslate)\\(\".*\"\\)"));
|
||||
//qsTr()
|
||||
if (objectNode.propertyAffectedByCurrentState(name())) {
|
||||
return expression().contains(rx);
|
||||
@@ -268,7 +280,6 @@ bool PropertyEditorValue::isTranslated() const
|
||||
return modelNode().bindingProperty(name()).expression().contains(rx);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -424,12 +435,14 @@ void PropertyEditorValue::removeAliasExport()
|
||||
|
||||
QString PropertyEditorValue::getTranslationContext() const
|
||||
{
|
||||
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) {
|
||||
if (modelNode().metaInfo().propertyTypeName(name()) == "QString" || modelNode().metaInfo().propertyTypeName(name()) == "string") {
|
||||
if (modelNode().isValid()) {
|
||||
if (auto metaInfo = modelNode().metaInfo();
|
||||
metaInfo.isValid() && metaInfo.hasProperty(name())
|
||||
&& metaInfo.property(name()).hasPropertyTypeName("QString", "string")) {
|
||||
const QmlDesigner::QmlObjectNode objectNode(modelNode());
|
||||
if (objectNode.isValid() && objectNode.hasBindingProperty(name())) {
|
||||
const QRegularExpression rx(QRegularExpression::anchoredPattern(
|
||||
"qsTranslate\\(\"(.*)\"\\s*,\\s*\".*\"\\s*\\)"));
|
||||
"qsTranslate\\(\"(.*)\"\\s*,\\s*\".*\"\\s*\\)"));
|
||||
const QRegularExpressionMatch match = rx.match(expression());
|
||||
if (match.hasMatch())
|
||||
return match.captured(1);
|
||||
@@ -519,7 +532,7 @@ bool PropertyEditorValue::idListReplace(int idx, const QString &value)
|
||||
void PropertyEditorValue::commitDrop(const QString &path)
|
||||
{
|
||||
if (m_modelNode.isSubclassOf("QtQuick3D.Material")
|
||||
&& m_modelNode.metaInfo().propertyTypeName(m_name) == "QtQuick3D.Texture") {
|
||||
&& m_modelNode.metaInfo().property(m_name).hasPropertyTypeName("QtQuick3D.Texture")) {
|
||||
// create a texture node
|
||||
QmlDesigner::NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo("QtQuick3D.Texture");
|
||||
QmlDesigner::ModelNode texture = m_modelNode.view()->createModelNode("QtQuick3D.Texture",
|
||||
@@ -618,8 +631,12 @@ void PropertyEditorNodeWrapper::add(const QString &type)
|
||||
QmlDesigner::TypeName propertyType = type.toUtf8();
|
||||
|
||||
if ((m_editorValue && m_editorValue->modelNode().isValid())) {
|
||||
if (propertyType.isEmpty())
|
||||
propertyType = m_editorValue->modelNode().metaInfo().propertyTypeName(m_editorValue->name());
|
||||
if (propertyType.isEmpty()) {
|
||||
propertyType = m_editorValue->modelNode()
|
||||
.metaInfo()
|
||||
.property(m_editorValue->name())
|
||||
.propertyTypeName();
|
||||
}
|
||||
while (propertyType.contains('*')) //strip star
|
||||
propertyType.chop(1);
|
||||
m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 7);
|
||||
@@ -681,9 +698,9 @@ void PropertyEditorNodeWrapper::setup()
|
||||
m_valuesPropertyMap.clear(propertyName);
|
||||
qDeleteAll(m_valuesPropertyMap.children());
|
||||
|
||||
const QList<QmlDesigner::PropertyName> propertyNameList = m_modelNode.metaInfo().propertyNames();
|
||||
for (const QmlDesigner::PropertyName &propertyName : propertyNameList) {
|
||||
if (qmlObjectNode.isValid()) {
|
||||
if (qmlObjectNode.isValid()) {
|
||||
for (const auto &property : m_modelNode.metaInfo().properties()) {
|
||||
const auto &propertyName = property.name();
|
||||
auto valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
|
||||
valueObject->setName(propertyName);
|
||||
valueObject->setValue(qmlObjectNode.instanceValue(propertyName));
|
||||
|
@@ -185,7 +185,7 @@ void PropertyEditorView::changeValue(const QString &name)
|
||||
QVariant castedValue;
|
||||
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) {
|
||||
castedValue = metaInfo.propertyCastedValue(propertyName, value->value());
|
||||
castedValue = metaInfo.property(propertyName).castedValue(value->value());
|
||||
} else if (propertyIsAttachedLayoutProperty(propertyName)) {
|
||||
castedValue = value->value();
|
||||
} else {
|
||||
@@ -200,17 +200,15 @@ void PropertyEditorView::changeValue(const QString &name)
|
||||
|
||||
bool propertyTypeUrl = false;
|
||||
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) {
|
||||
if (metaInfo.propertyTypeName(propertyName) == "QUrl"
|
||||
|| metaInfo.propertyTypeName(propertyName) == "url") {
|
||||
// turn absolute local file paths into relative paths
|
||||
propertyTypeUrl = true;
|
||||
QString filePath = castedValue.toUrl().toString();
|
||||
QFileInfo fi(filePath);
|
||||
if (fi.exists() && fi.isAbsolute()) {
|
||||
QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath());
|
||||
castedValue = QUrl(fileDir.relativeFilePath(filePath));
|
||||
}
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)
|
||||
&& metaInfo.property(propertyName).hasPropertyTypeName("QUrl", "url")) {
|
||||
// turn absolute local file paths into relative paths
|
||||
propertyTypeUrl = true;
|
||||
QString filePath = castedValue.toUrl().toString();
|
||||
QFileInfo fi(filePath);
|
||||
if (fi.exists() && fi.isAbsolute()) {
|
||||
QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath());
|
||||
castedValue = QUrl(fileDir.relativeFilePath(filePath));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,13 +270,15 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
|
||||
return;
|
||||
}
|
||||
|
||||
if (qmlObjectNode->modelNode().metaInfo().isValid() && qmlObjectNode->modelNode().metaInfo().hasProperty(name)) {
|
||||
if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QColor") {
|
||||
if (auto metaInfo = qmlObjectNode->modelNode().metaInfo();
|
||||
metaInfo.isValid() && metaInfo.hasProperty(name)) {
|
||||
const auto &propertTypeName = metaInfo.property(name).propertyTypeName();
|
||||
if (propertTypeName == "QColor") {
|
||||
if (QColor(value->expression().remove('"')).isValid()) {
|
||||
qmlObjectNode->setVariantProperty(name, QColor(value->expression().remove('"')));
|
||||
return;
|
||||
}
|
||||
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "bool") {
|
||||
} else if (propertTypeName == "bool") {
|
||||
if (isTrueFalseLiteral(value->expression())) {
|
||||
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
|
||||
qmlObjectNode->setVariantProperty(name, true);
|
||||
@@ -286,21 +286,21 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
|
||||
qmlObjectNode->setVariantProperty(name, false);
|
||||
return;
|
||||
}
|
||||
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "int") {
|
||||
} else if (propertTypeName == "int") {
|
||||
bool ok;
|
||||
int intValue = value->expression().toInt(&ok);
|
||||
if (ok) {
|
||||
qmlObjectNode->setVariantProperty(name, intValue);
|
||||
return;
|
||||
}
|
||||
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "qreal") {
|
||||
} else if (propertTypeName == "qreal") {
|
||||
bool ok;
|
||||
qreal realValue = value->expression().toDouble(&ok);
|
||||
if (ok) {
|
||||
qmlObjectNode->setVariantProperty(name, realValue);
|
||||
return;
|
||||
}
|
||||
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QVariant") {
|
||||
} else if (propertTypeName == "QVariant") {
|
||||
bool ok;
|
||||
qreal realValue = value->expression().toDouble(&ok);
|
||||
if (ok) {
|
||||
|
@@ -53,15 +53,8 @@ namespace {
|
||||
bool modelNodeHasUrlSource(const QmlDesigner::ModelNode &modelNode)
|
||||
{
|
||||
QmlDesigner::NodeMetaInfo metaInfo = modelNode.metaInfo();
|
||||
if (metaInfo.isValid()) {
|
||||
if (metaInfo.hasProperty("source")) {
|
||||
if (metaInfo.propertyTypeName("source") == "QUrl")
|
||||
return true;
|
||||
if (metaInfo.propertyTypeName("source") == "url")
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return metaInfo.isValid() && metaInfo.hasProperty("source")
|
||||
&& metaInfo.property("source").hasPropertyTypeName("QUrl", "url");
|
||||
}
|
||||
|
||||
} //namespace
|
||||
|
@@ -234,8 +234,10 @@ TimelinePropertyItem *TimelinePropertyItem::create(const QmlTimelineKeyframeGrou
|
||||
if (!objectNode.isValid())
|
||||
return item;
|
||||
|
||||
auto nameOfType = objectNode.modelNode().metaInfo().propertyTypeName(
|
||||
item->m_frames.propertyName());
|
||||
auto nameOfType = objectNode.modelNode()
|
||||
.metaInfo()
|
||||
.property(item->m_frames.propertyName())
|
||||
.propertyTypeName();
|
||||
item->m_control = createTimelineControl(nameOfType);
|
||||
if (item->m_control) {
|
||||
item->m_control->setSize((TimelineConstants::sectionWidth / 2.6) - 10,
|
||||
|
@@ -226,7 +226,7 @@ ModelNode TransitionEditorView::addNewTransition()
|
||||
if (target.isValid() && target.hasMetaInfo()) {
|
||||
const QString targetId = target.id();
|
||||
for (const VariantProperty &property : change.modelNode().variantProperties()) {
|
||||
TypeName typeName = target.metaInfo().propertyTypeName(property.name());
|
||||
TypeName typeName = target.metaInfo().property(property.name()).propertyTypeName();
|
||||
if (typeName.startsWith("<cpp>."))
|
||||
typeName.remove(0, 6);
|
||||
|
||||
|
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qmldesignercorelib_global.h>
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class EnumerationMetaInfo
|
||||
{
|
||||
public:
|
||||
EnumerationMetaInfo(QSharedPointer<class NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
|
||||
const TypeName &enumeration);
|
||||
~EnumerationMetaInfo();
|
||||
|
||||
private:
|
||||
QSharedPointer<class NodeMetaInfoPrivate> m_nodeMetaInfoPrivateData;
|
||||
const TypeName &m_enumeration;
|
||||
};
|
||||
|
||||
using EnumerationMetaInfos = std::vector<EnumerationMetaInfo>;
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -42,6 +42,7 @@ class ItemLibraryInfo;
|
||||
namespace Internal {
|
||||
class MetaInfoPrivate;
|
||||
class ModelPrivate;
|
||||
class MetaInfoReader;
|
||||
class SubComponentManagerPrivate;
|
||||
using MetaInfoPrivatePointer = QSharedPointer<MetaInfoPrivate>;
|
||||
}
|
||||
|
@@ -44,8 +44,7 @@ namespace QmlDesigner {
|
||||
namespace Internal {
|
||||
class ModelPrivate;
|
||||
class WriteLocker;
|
||||
class NodeMetaInfoPrivate;
|
||||
} // namespace Internal
|
||||
} //Internal
|
||||
|
||||
class AnchorLine;
|
||||
class ModelNode;
|
||||
@@ -70,7 +69,7 @@ class QMLDESIGNERCORE_EXPORT Model : public QObject
|
||||
friend AbstractView;
|
||||
friend Internal::ModelPrivate;
|
||||
friend Internal::WriteLocker;
|
||||
friend Internal::NodeMetaInfoPrivate;
|
||||
friend class NodeMetaInfoPrivate;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
@@ -141,4 +140,4 @@ private:
|
||||
Internal::ModelPrivate *d;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
}
|
||||
|
@@ -174,7 +174,7 @@ public:
|
||||
Model *model() const;
|
||||
AbstractView *view() const;
|
||||
|
||||
const NodeMetaInfo metaInfo() const;
|
||||
NodeMetaInfo metaInfo() const;
|
||||
bool hasMetaInfo() const;
|
||||
|
||||
bool isSelected() const;
|
||||
|
@@ -25,12 +25,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "invalidmetainfoexception.h"
|
||||
#include "propertymetainfo.h"
|
||||
#include "qmldesignercorelib_global.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QIcon>
|
||||
|
||||
#include "qmldesignercorelib_global.h"
|
||||
#include "invalidmetainfoexception.h"
|
||||
#include <vector>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDeclarativeContext;
|
||||
@@ -42,14 +45,6 @@ class MetaInfo;
|
||||
class Model;
|
||||
class AbstractProperty;
|
||||
|
||||
namespace Internal {
|
||||
class MetaInfoPrivate;
|
||||
class MetaInfoReader;
|
||||
class SubComponentManagerPrivate;
|
||||
class ItemLibraryEntryData;
|
||||
class NodeMetaInfoPrivate;
|
||||
}
|
||||
|
||||
class QMLDESIGNERCORE_EXPORT NodeMetaInfo
|
||||
{
|
||||
public:
|
||||
@@ -64,20 +59,13 @@ public:
|
||||
bool isValid() const;
|
||||
bool isFileComponent() const;
|
||||
bool hasProperty(const PropertyName &propertyName) const;
|
||||
PropertyNameList propertyNames() const;
|
||||
PropertyMetaInfos properties() const;
|
||||
PropertyMetaInfos localProperties() const;
|
||||
PropertyMetaInfo property(const PropertyName &propertyName) const;
|
||||
PropertyNameList signalNames() const;
|
||||
PropertyNameList slotNames() const;
|
||||
PropertyNameList directPropertyNames() const;
|
||||
PropertyName defaultPropertyName() const;
|
||||
bool hasDefaultProperty() const;
|
||||
TypeName propertyTypeName(const PropertyName &propertyName) const;
|
||||
bool propertyIsWritable(const PropertyName &propertyName) const;
|
||||
bool propertyIsListProperty(const PropertyName &propertyName) const;
|
||||
bool propertyIsEnumType(const PropertyName &propertyName) const;
|
||||
bool propertyIsPrivate(const PropertyName &propertyName) const;
|
||||
bool propertyIsPointer(const PropertyName &propertyName) const;
|
||||
QStringList propertyKeysForEnum(const PropertyName &propertyName) const;
|
||||
QVariant propertyCastedValue(const PropertyName &propertyName, const QVariant &value) const;
|
||||
|
||||
QList<NodeMetaInfo> classHierarchy() const;
|
||||
QList<NodeMetaInfo> superClasses() const;
|
||||
@@ -104,7 +92,9 @@ public:
|
||||
QString importDirectoryPath() const;
|
||||
|
||||
private:
|
||||
QSharedPointer<Internal::NodeMetaInfoPrivate> m_privateData;
|
||||
QSharedPointer<class NodeMetaInfoPrivate> m_privateData;
|
||||
};
|
||||
|
||||
using NodeMetaInfos = std::vector<NodeMetaInfo>;
|
||||
|
||||
} //QmlDesigner
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qmldesignercorelib_global.h>
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class PropertyMetaInfo
|
||||
{
|
||||
public:
|
||||
PropertyMetaInfo(QSharedPointer<class NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
|
||||
const PropertyName &propertyName);
|
||||
~PropertyMetaInfo();
|
||||
|
||||
const TypeName &propertyTypeName() const;
|
||||
class NodeMetaInfo propertyNodeMetaInfo() const;
|
||||
|
||||
bool isWritable() const;
|
||||
bool isListProperty() const;
|
||||
bool isEnumType() const;
|
||||
bool isPrivate() const;
|
||||
bool isPointer() const;
|
||||
QVariant castedValue(const QVariant &value) const;
|
||||
const PropertyName &name() const & { return m_propertyName; }
|
||||
|
||||
template<typename... TypeName>
|
||||
bool hasPropertyTypeName(const TypeName &...typeName) const
|
||||
{
|
||||
auto propertyTypeName_ = propertyTypeName();
|
||||
return ((propertyTypeName_ == typeName) || ...);
|
||||
}
|
||||
|
||||
private:
|
||||
QSharedPointer<class NodeMetaInfoPrivate> m_nodeMetaInfoPrivateData;
|
||||
PropertyName m_propertyName;
|
||||
};
|
||||
|
||||
using PropertyMetaInfos = std::vector<PropertyMetaInfo>;
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -212,12 +212,14 @@ public:
|
||||
void setStartFlowItem(const QmlFlowItemNode &flowItem);
|
||||
ModelNode createTransition();
|
||||
|
||||
static PropertyNameList st_mouseSignals;
|
||||
static QList<QmlConnections> getAssociatedConnections(const ModelNode &node);
|
||||
|
||||
static const PropertyNameList &mouseSignals() { return s_mouseSignals; }
|
||||
|
||||
protected:
|
||||
QList<ModelNode> transitionsForProperty(const PropertyName &propertyName, const ModelNode &modelNode);
|
||||
|
||||
private:
|
||||
static PropertyNameList s_mouseSignals;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -46,17 +46,6 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
struct TypeDescription
|
||||
{
|
||||
QString className;
|
||||
int minorVersion{};
|
||||
int majorVersion{};
|
||||
};
|
||||
|
||||
} //Internal
|
||||
|
||||
/*!
|
||||
\class QmlDesigner::NodeMetaInfo
|
||||
\ingroup CoreModel
|
||||
@@ -74,7 +63,14 @@ NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
|
||||
\see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
|
||||
*/
|
||||
|
||||
namespace Internal {
|
||||
namespace {
|
||||
|
||||
struct TypeDescription
|
||||
{
|
||||
QString className;
|
||||
int minorVersion{};
|
||||
int majorVersion{};
|
||||
};
|
||||
|
||||
using namespace QmlJS;
|
||||
|
||||
@@ -516,6 +512,9 @@ PropertyNameList getSignals(const ObjectValue *objectValue, const ContextPtr &co
|
||||
signalList.append(getSignals(prototype, context, true));
|
||||
}
|
||||
|
||||
std::sort(signalList.begin(), signalList.end());
|
||||
signalList.erase(std::unique(signalList.begin(), signalList.end()), signalList.end());
|
||||
|
||||
return signalList;
|
||||
}
|
||||
|
||||
@@ -544,6 +543,9 @@ PropertyNameList getSlots(const ObjectValue *objectValue, const ContextPtr &cont
|
||||
slotList.append(getSlots(prototype, context, true));
|
||||
}
|
||||
|
||||
std::sort(slotList.begin(), slotList.end());
|
||||
slotList.erase(std::unique(slotList.begin(), slotList.end()), slotList.end());
|
||||
|
||||
return slotList;
|
||||
}
|
||||
|
||||
@@ -604,6 +606,7 @@ QVector<PropertyInfo> getObjectTypes(const ObjectValue *objectValue, const Conte
|
||||
|
||||
return propertyList;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class NodeMetaInfoPrivate
|
||||
{
|
||||
@@ -614,12 +617,12 @@ public:
|
||||
|
||||
bool isValid() const;
|
||||
bool isFileComponent() const;
|
||||
PropertyNameList properties() const;
|
||||
PropertyNameList localProperties() const;
|
||||
const PropertyNameList &properties() const;
|
||||
const PropertyNameList &localProperties() const;
|
||||
PropertyNameList signalNames() const;
|
||||
PropertyNameList slotNames() const;
|
||||
PropertyName defaultPropertyName() const;
|
||||
TypeName propertyType(const PropertyName &propertyName) const;
|
||||
const TypeName &propertyType(const PropertyName &propertyName) const;
|
||||
|
||||
void setupPrototypes();
|
||||
QList<TypeDescription> prototypes() const;
|
||||
@@ -634,7 +637,7 @@ public:
|
||||
|
||||
int majorVersion() const;
|
||||
int minorVersion() const;
|
||||
TypeName qualfiedTypeName() const;
|
||||
const TypeName &qualfiedTypeName() const;
|
||||
Model *model() const;
|
||||
|
||||
QByteArray cppPackageName() const;
|
||||
@@ -691,14 +694,14 @@ bool NodeMetaInfoPrivate::isFileComponent() const
|
||||
return m_isFileComponent;
|
||||
}
|
||||
|
||||
PropertyNameList NodeMetaInfoPrivate::properties() const
|
||||
const PropertyNameList &NodeMetaInfoPrivate::properties() const
|
||||
{
|
||||
ensureProperties();
|
||||
|
||||
return m_properties;
|
||||
}
|
||||
|
||||
PropertyNameList NodeMetaInfoPrivate::localProperties() const
|
||||
const PropertyNameList &NodeMetaInfoPrivate::localProperties() const
|
||||
{
|
||||
ensureProperties();
|
||||
|
||||
@@ -741,8 +744,9 @@ static inline TypeName stringIdentifier( const TypeName &type, int maj, int min)
|
||||
|
||||
NodeMetaInfoPrivate::Pointer NodeMetaInfoPrivate::create(Model *model, const TypeName &type, int major, int minor)
|
||||
{
|
||||
if (model->d->m_nodeMetaInfoCache.contains(stringIdentifier(type, major, minor)))
|
||||
return model->d->m_nodeMetaInfoCache.value(stringIdentifier(type, major, minor));
|
||||
auto &&cache = model->d->m_nodeMetaInfoCache;
|
||||
if (auto found = cache.find(stringIdentifier(type, major, minor)); found != cache.end())
|
||||
return *found;
|
||||
|
||||
Pointer newData(new NodeMetaInfoPrivate(model, type, major, minor));
|
||||
if (newData->isValid())
|
||||
@@ -1144,7 +1148,7 @@ int NodeMetaInfoPrivate::minorVersion() const
|
||||
return m_minorVersion;
|
||||
}
|
||||
|
||||
TypeName NodeMetaInfoPrivate::qualfiedTypeName() const
|
||||
const TypeName &NodeMetaInfoPrivate::qualfiedTypeName() const
|
||||
{
|
||||
return m_qualfiedTypeName;
|
||||
}
|
||||
@@ -1248,12 +1252,16 @@ bool NodeMetaInfoPrivate::isValid() const
|
||||
return m_isValid && context() && document();
|
||||
}
|
||||
|
||||
TypeName NodeMetaInfoPrivate::propertyType(const PropertyName &propertyName) const
|
||||
namespace {
|
||||
TypeName nonexistingTypeName("Property does not exist...");
|
||||
}
|
||||
|
||||
const TypeName &NodeMetaInfoPrivate::propertyType(const PropertyName &propertyName) const
|
||||
{
|
||||
ensureProperties();
|
||||
|
||||
if (!m_properties.contains(propertyName))
|
||||
return TypeName("Property does not exist...");
|
||||
return nonexistingTypeName;
|
||||
return m_propertyTypes.at(m_properties.indexOf(propertyName));
|
||||
}
|
||||
|
||||
@@ -1386,14 +1394,14 @@ void NodeMetaInfoPrivate::initialiseProperties()
|
||||
m_slots = getSlots(m_objectValue, context());
|
||||
}
|
||||
|
||||
} //namespace Internal
|
||||
|
||||
NodeMetaInfo::NodeMetaInfo() : m_privateData(new Internal::NodeMetaInfoPrivate())
|
||||
NodeMetaInfo::NodeMetaInfo()
|
||||
: m_privateData(QSharedPointer<NodeMetaInfoPrivate>::create())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NodeMetaInfo::NodeMetaInfo(Model *model, const TypeName &type, int maj, int min) : m_privateData(Internal::NodeMetaInfoPrivate::create(model, type, maj, min))
|
||||
NodeMetaInfo::NodeMetaInfo(Model *model, const TypeName &type, int maj, int min)
|
||||
: m_privateData(NodeMetaInfoPrivate::create(model, type, maj, min))
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1422,12 +1430,38 @@ bool NodeMetaInfo::isFileComponent() const
|
||||
|
||||
bool NodeMetaInfo::hasProperty(const PropertyName &propertyName) const
|
||||
{
|
||||
return propertyNames().contains(propertyName);
|
||||
return m_privateData->properties().contains(propertyName);
|
||||
}
|
||||
|
||||
PropertyNameList NodeMetaInfo::propertyNames() const
|
||||
PropertyMetaInfos NodeMetaInfo::properties() const
|
||||
{
|
||||
return m_privateData->properties();
|
||||
const auto &properties = m_privateData->properties();
|
||||
|
||||
PropertyMetaInfos propertyMetaInfos;
|
||||
propertyMetaInfos.reserve(static_cast<std::size_t>(properties.size()));
|
||||
|
||||
for (const auto &name : properties)
|
||||
propertyMetaInfos.emplace_back(m_privateData, name);
|
||||
|
||||
return propertyMetaInfos;
|
||||
}
|
||||
|
||||
PropertyMetaInfos NodeMetaInfo::localProperties() const
|
||||
{
|
||||
const auto &properties = m_privateData->localProperties();
|
||||
|
||||
PropertyMetaInfos propertyMetaInfos;
|
||||
propertyMetaInfos.reserve(static_cast<std::size_t>(properties.size()));
|
||||
|
||||
for (const auto &name : properties)
|
||||
propertyMetaInfos.emplace_back(m_privateData, name);
|
||||
|
||||
return propertyMetaInfos;
|
||||
}
|
||||
|
||||
PropertyMetaInfo NodeMetaInfo::property(const PropertyName &propertyName) const
|
||||
{
|
||||
return PropertyMetaInfo{m_privateData, propertyName};
|
||||
}
|
||||
|
||||
PropertyNameList NodeMetaInfo::signalNames() const
|
||||
@@ -1440,11 +1474,6 @@ PropertyNameList NodeMetaInfo::slotNames() const
|
||||
return m_privateData->slotNames();
|
||||
}
|
||||
|
||||
PropertyNameList NodeMetaInfo::directPropertyNames() const
|
||||
{
|
||||
return m_privateData->localProperties();
|
||||
}
|
||||
|
||||
PropertyName NodeMetaInfo::defaultPropertyName() const
|
||||
{
|
||||
return m_privateData->defaultPropertyName();
|
||||
@@ -1455,84 +1484,6 @@ bool NodeMetaInfo::hasDefaultProperty() const
|
||||
return !defaultPropertyName().isEmpty();
|
||||
}
|
||||
|
||||
TypeName NodeMetaInfo::propertyTypeName(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->propertyType(propertyName);
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::propertyIsWritable(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->isPropertyWritable(propertyName);
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::propertyIsListProperty(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->isPropertyList(propertyName);
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::propertyIsEnumType(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->isPropertyEnum(propertyName);
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::propertyIsPrivate(const PropertyName &propertyName) const
|
||||
{
|
||||
return propertyName.startsWith("__");
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::propertyIsPointer(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->isPropertyPointer(propertyName);
|
||||
}
|
||||
|
||||
QStringList NodeMetaInfo::propertyKeysForEnum(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->keysForEnum(QString::fromUtf8(propertyTypeName(propertyName)));
|
||||
}
|
||||
|
||||
QVariant NodeMetaInfo::propertyCastedValue(const PropertyName &propertyName, const QVariant &value) const
|
||||
{
|
||||
const QVariant variant = value;
|
||||
QVariant copyVariant = variant;
|
||||
if (propertyIsEnumType(propertyName)
|
||||
|| variant.canConvert<Enumeration>())
|
||||
return variant;
|
||||
|
||||
const TypeName typeName = propertyTypeName(propertyName);
|
||||
|
||||
QVariant::Type typeId = m_privateData->variantTypeId(propertyName);
|
||||
|
||||
if (variant.type() == QVariant::UserType && variant.userType() == ModelNode::variantUserType()) {
|
||||
return variant;
|
||||
} else if (typeId == QVariant::UserType && typeName == "QVariant") {
|
||||
return variant;
|
||||
} else if (typeId == QVariant::UserType && typeName == "variant") {
|
||||
return variant;
|
||||
} else if (typeId == QVariant::UserType && typeName == "var") {
|
||||
return variant;
|
||||
} else if (variant.type() == QVariant::List) {
|
||||
// TODO: check the contents of the list
|
||||
return variant;
|
||||
} else if (typeName == "var" || typeName == "variant") {
|
||||
return variant;
|
||||
} else if (typeName == "alias") {
|
||||
// TODO: The QML compiler resolves the alias type. We probably should do the same.
|
||||
return variant;
|
||||
} else if (typeName == "<cpp>.double") {
|
||||
return variant.toDouble();
|
||||
} else if (typeName == "<cpp>.float") {
|
||||
return variant.toFloat();
|
||||
} else if (typeName == "<cpp>.int") {
|
||||
return variant.toInt();
|
||||
} else if (typeName == "<cpp>.bool") {
|
||||
return variant.toBool();
|
||||
} else if (copyVariant.convert(typeId)) {
|
||||
return copyVariant;
|
||||
}
|
||||
|
||||
return Internal::PropertyParser::variantFromString(variant.toString());
|
||||
}
|
||||
|
||||
QList<NodeMetaInfo> NodeMetaInfo::classHierarchy() const
|
||||
{
|
||||
QList<NodeMetaInfo> hierarchy = {*this};
|
||||
@@ -1543,7 +1494,7 @@ QList<NodeMetaInfo> NodeMetaInfo::classHierarchy() const
|
||||
QList<NodeMetaInfo> NodeMetaInfo::superClasses() const
|
||||
{
|
||||
Model *model = m_privateData->model();
|
||||
return Utils::transform(m_privateData->prototypes(), [model](const Internal::TypeDescription &type) {
|
||||
return Utils::transform(m_privateData->prototypes(), [model](const TypeDescription &type) {
|
||||
return NodeMetaInfo(model, type.className.toUtf8(), type.majorVersion, type.minorVersion);
|
||||
});
|
||||
}
|
||||
@@ -1556,7 +1507,7 @@ NodeMetaInfo NodeMetaInfo::directSuperClass() const
|
||||
bool NodeMetaInfo::defaultPropertyIsComponent() const
|
||||
{
|
||||
if (hasDefaultProperty())
|
||||
return propertyTypeName(defaultPropertyName()) == "Component";
|
||||
return property(defaultPropertyName()).hasPropertyTypeName("Component");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1613,21 +1564,24 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
|
||||
if (typeName() == type && availableInVersion(majorVersion, minorVersion))
|
||||
return true;
|
||||
|
||||
if (m_privateData->prototypeCachePositives().contains(Internal::stringIdentifier(type, majorVersion, minorVersion)))
|
||||
if (m_privateData->prototypeCachePositives().contains(
|
||||
stringIdentifier(type, majorVersion, minorVersion)))
|
||||
return true; //take a shortcut - optimization
|
||||
|
||||
if (m_privateData->prototypeCacheNegatives().contains(Internal::stringIdentifier(type, majorVersion, minorVersion)))
|
||||
if (m_privateData->prototypeCacheNegatives().contains(
|
||||
stringIdentifier(type, majorVersion, minorVersion)))
|
||||
return false; //take a shortcut - optimization
|
||||
|
||||
const QList<NodeMetaInfo> superClassList = superClasses();
|
||||
for (const NodeMetaInfo &superClass : superClassList) {
|
||||
if (superClass.m_privateData->cleverCheckType(type)
|
||||
&& superClass.availableInVersion(majorVersion, minorVersion)) {
|
||||
m_privateData->prototypeCachePositives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion));
|
||||
m_privateData->prototypeCachePositives().insert(
|
||||
stringIdentifier(type, majorVersion, minorVersion));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
m_privateData->prototypeCacheNegatives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion));
|
||||
m_privateData->prototypeCacheNegatives().insert(stringIdentifier(type, majorVersion, minorVersion));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1668,4 +1622,90 @@ bool NodeMetaInfo::isTabView() const
|
||||
return isSubclassOf("QtQuick.Controls.TabView");
|
||||
}
|
||||
|
||||
PropertyMetaInfo::PropertyMetaInfo(QSharedPointer<NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
|
||||
const PropertyName &propertyName)
|
||||
: m_nodeMetaInfoPrivateData{nodeMetaInfoPrivateData}
|
||||
, m_propertyName{propertyName}
|
||||
|
||||
{}
|
||||
|
||||
PropertyMetaInfo::~PropertyMetaInfo() {}
|
||||
|
||||
const TypeName &PropertyMetaInfo::propertyTypeName() const
|
||||
{
|
||||
return m_nodeMetaInfoPrivateData->propertyType(m_propertyName);
|
||||
}
|
||||
|
||||
NodeMetaInfo PropertyMetaInfo::propertyNodeMetaInfo() const
|
||||
{
|
||||
return m_nodeMetaInfoPrivateData->model()->metaInfo(propertyTypeName());
|
||||
}
|
||||
|
||||
bool PropertyMetaInfo::isWritable() const
|
||||
{
|
||||
return m_nodeMetaInfoPrivateData->isPropertyWritable(m_propertyName);
|
||||
}
|
||||
|
||||
bool PropertyMetaInfo::isListProperty() const
|
||||
{
|
||||
return m_nodeMetaInfoPrivateData->isPropertyList(m_propertyName);
|
||||
}
|
||||
|
||||
bool PropertyMetaInfo::isEnumType() const
|
||||
{
|
||||
return m_nodeMetaInfoPrivateData->isPropertyEnum(m_propertyName);
|
||||
}
|
||||
|
||||
bool PropertyMetaInfo::isPrivate() const
|
||||
{
|
||||
return m_propertyName.startsWith("__");
|
||||
}
|
||||
|
||||
bool PropertyMetaInfo::isPointer() const
|
||||
{
|
||||
return m_nodeMetaInfoPrivateData->isPropertyPointer(m_propertyName);
|
||||
}
|
||||
|
||||
QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
|
||||
{
|
||||
const QVariant variant = value;
|
||||
QVariant copyVariant = variant;
|
||||
if (isEnumType() || variant.canConvert<Enumeration>())
|
||||
return variant;
|
||||
|
||||
const TypeName &typeName = propertyTypeName();
|
||||
|
||||
QVariant::Type typeId = m_nodeMetaInfoPrivateData->variantTypeId(m_propertyName);
|
||||
|
||||
if (variant.type() == QVariant::UserType && variant.userType() == ModelNode::variantUserType()) {
|
||||
return variant;
|
||||
} else if (typeId == QVariant::UserType && typeName == "QVariant") {
|
||||
return variant;
|
||||
} else if (typeId == QVariant::UserType && typeName == "variant") {
|
||||
return variant;
|
||||
} else if (typeId == QVariant::UserType && typeName == "var") {
|
||||
return variant;
|
||||
} else if (variant.type() == QVariant::List) {
|
||||
// TODO: check the contents of the list
|
||||
return variant;
|
||||
} else if (typeName == "var" || typeName == "variant") {
|
||||
return variant;
|
||||
} else if (typeName == "alias") {
|
||||
// TODO: The QML compiler resolves the alias type. We probably should do the same.
|
||||
return variant;
|
||||
} else if (typeName == "<cpp>.double") {
|
||||
return variant.toDouble();
|
||||
} else if (typeName == "<cpp>.float") {
|
||||
return variant.toFloat();
|
||||
} else if (typeName == "<cpp>.int") {
|
||||
return variant.toInt();
|
||||
} else if (typeName == "<cpp>.bool") {
|
||||
return variant.toBool();
|
||||
} else if (copyVariant.convert(typeId)) {
|
||||
return copyVariant;
|
||||
}
|
||||
|
||||
return Internal::PropertyParser::variantFromString(variant.toString());
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -46,6 +46,7 @@ namespace QmlDesigner {
|
||||
class AbstractProperty;
|
||||
class RewriterView;
|
||||
class NodeInstanceView;
|
||||
class NodeMetaInfoPrivate;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
@@ -85,7 +86,7 @@ class ModelPrivate : public QObject {
|
||||
|
||||
friend Model;
|
||||
friend Internal::WriteLocker;
|
||||
friend Internal::NodeMetaInfoPrivate;
|
||||
friend NodeMetaInfoPrivate;
|
||||
|
||||
public:
|
||||
ModelPrivate(Model *model);
|
||||
|
@@ -855,7 +855,7 @@ bool ModelNode::hasAnySubModelNodes() const
|
||||
return !nodeAbstractProperties().isEmpty();
|
||||
}
|
||||
|
||||
const NodeMetaInfo ModelNode::metaInfo() const
|
||||
NodeMetaInfo ModelNode::metaInfo() const
|
||||
{
|
||||
if (!isValid()) {
|
||||
Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
|
||||
|
@@ -33,6 +33,8 @@
|
||||
#include "model.h"
|
||||
#include "model_p.h"
|
||||
|
||||
#include <nodemetainfo.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
NodeAbstractProperty::NodeAbstractProperty() = default;
|
||||
@@ -53,10 +55,14 @@ NodeAbstractProperty::NodeAbstractProperty(const Internal::InternalNodeAbstractP
|
||||
|
||||
void NodeAbstractProperty::reparentHere(const ModelNode &modelNode)
|
||||
{
|
||||
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeAbstractProperty())
|
||||
if (internalNode()->hasProperty(name())
|
||||
&& !internalNode()->property(name())->isNodeAbstractProperty()) {
|
||||
reparentHere(modelNode, isNodeListProperty());
|
||||
else
|
||||
reparentHere(modelNode, parentModelNode().metaInfo().propertyIsListProperty(name()) || isDefaultProperty()); //we could use the metasystem instead?
|
||||
} else {
|
||||
reparentHere(modelNode,
|
||||
parentModelNode().metaInfo().property(name()).isListProperty()
|
||||
|| isDefaultProperty()); //we could use the metasystem instead?
|
||||
}
|
||||
}
|
||||
|
||||
void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNodeList, const TypeName &dynamicTypeName)
|
||||
|
@@ -993,8 +993,14 @@ QList<ModelNode> QmlFlowViewNode::transitionsForProperty(const PropertyName &pro
|
||||
return list;
|
||||
}
|
||||
|
||||
PropertyNameList QmlFlowViewNode::st_mouseSignals = { "clicked", "doubleClicked", "pressAndHold",
|
||||
"pressed", "released", "wheel" };
|
||||
PropertyNameList QmlFlowViewNode::s_mouseSignals = []() {
|
||||
PropertyNameList mouseSignals = {
|
||||
"clicked", "doubleClicked", "pressed", "pressAndHold", "released", "wheel"};
|
||||
|
||||
Q_ASSERT(std::is_sorted(mouseSignals.begin(), mouseSignals.end()));
|
||||
|
||||
return mouseSignals;
|
||||
}();
|
||||
|
||||
QList<QmlConnections> QmlFlowViewNode::getAssociatedConnections(const ModelNode &node)
|
||||
{
|
||||
@@ -1020,8 +1026,7 @@ QList<QmlConnections> QmlFlowViewNode::getAssociatedConnections(const ModelNode
|
||||
sourceProperty = sourceComponents[1];
|
||||
}
|
||||
|
||||
if (st_mouseSignals.contains(signalWithoutPrefix)
|
||||
&& sourceId == node.id()
|
||||
if (mouseSignals().contains(signalWithoutPrefix) && sourceId == node.id()
|
||||
&& sourceProperty == "trigger()")
|
||||
return true;
|
||||
}
|
||||
|
@@ -246,17 +246,17 @@ QVariant QmlObjectNode::modelValue(const PropertyName &name) const
|
||||
|
||||
bool QmlObjectNode::isTranslatableText(const PropertyName &name) const
|
||||
{
|
||||
if (modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name))
|
||||
if (modelNode().metaInfo().propertyTypeName(name) == "QString" || modelNode().metaInfo().propertyTypeName(name) == "string") {
|
||||
if (modelNode().hasBindingProperty(name)) {
|
||||
static QRegularExpression regularExpressionPattern(
|
||||
QLatin1String("^qsTr(|Id|anslate)\\(\".*\"\\)$"));
|
||||
return modelNode().bindingProperty(name).expression().contains(regularExpressionPattern);
|
||||
}
|
||||
|
||||
return false;
|
||||
if (modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name)
|
||||
&& modelNode().metaInfo().property(name).hasPropertyTypeName("QString", "string")) {
|
||||
if (modelNode().hasBindingProperty(name)) {
|
||||
static QRegularExpression regularExpressionPattern(
|
||||
QLatin1String("^qsTr(|Id|anslate)\\(\".*\"\\)$"));
|
||||
return modelNode().bindingProperty(name).expression().contains(regularExpressionPattern);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -213,7 +213,7 @@ TypeName QmlTimelineKeyframeGroup::valueType() const
|
||||
TypeName typeName;
|
||||
|
||||
if (targetNode.isValid() && targetNode.hasMetaInfo())
|
||||
typeName = targetNode.metaInfo().propertyTypeName(propertyName());
|
||||
typeName = targetNode.metaInfo().property(propertyName()).propertyTypeName();
|
||||
|
||||
if (typeName.startsWith("<cpp>."))
|
||||
typeName.remove(0, 6);
|
||||
|
@@ -223,7 +223,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
|
||||
if (!forceNonDefaultProperty.isEmpty()) {
|
||||
const NodeMetaInfo metaInfo = parentQmlItemNode.modelNode().metaInfo();
|
||||
if (metaInfo.hasProperty(forceNonDefaultProperty)) {
|
||||
if (!metaInfo.propertyIsListProperty(forceNonDefaultProperty)
|
||||
if (!metaInfo.property(forceNonDefaultProperty).isListProperty()
|
||||
&& parentQmlItemNode.modelNode().hasNodeProperty(forceNonDefaultProperty)) {
|
||||
parentQmlItemNode.removeProperty(forceNonDefaultProperty);
|
||||
}
|
||||
@@ -324,7 +324,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
|
||||
const ModelNode parentNode = parentProperty.parentModelNode();
|
||||
const NodeMetaInfo metaInfo = parentNode.metaInfo();
|
||||
|
||||
if (metaInfo.isValid() && !metaInfo.propertyIsListProperty(propertyName)
|
||||
if (metaInfo.isValid() && !metaInfo.property(propertyName).isListProperty()
|
||||
&& parentProperty.isNodeProperty()) {
|
||||
parentNode.removeProperty(propertyName);
|
||||
}
|
||||
|
@@ -337,8 +337,9 @@ bool propertyIsComponentType(const QmlDesigner::NodeAbstractProperty &property,
|
||||
if (model->metaInfo(type).isSubclassOf("QtQuick.Component") && !isComponentType(type))
|
||||
return false; //If the type is already a subclass of Component keep it
|
||||
|
||||
return property.parentModelNode().isValid() &&
|
||||
isComponentType(property.parentModelNode().metaInfo().propertyTypeName(property.name()));
|
||||
return property.parentModelNode().isValid()
|
||||
&& isComponentType(
|
||||
property.parentModelNode().metaInfo().property(property.name()).propertyTypeName());
|
||||
}
|
||||
|
||||
QString extractComponentFromQml(const QString &source)
|
||||
|
@@ -153,6 +153,7 @@ function(extend_with_qmldesigner_core target_name)
|
||||
include/componenttextmodifier.h
|
||||
include/customnotifications.h
|
||||
include/documentmessage.h
|
||||
include/enumerationmetainfo.h
|
||||
include/exception.h
|
||||
include/forwardview.h
|
||||
include/imagecacheauxiliarydata.h
|
||||
@@ -184,6 +185,7 @@ function(extend_with_qmldesigner_core target_name)
|
||||
include/notimplementedexception.h
|
||||
include/plaintexteditmodifier.h
|
||||
include/propertycontainer.h
|
||||
include/propertymetainfo.h
|
||||
include/propertynode.h
|
||||
include/propertyparser.h
|
||||
include/qmlanchors.h
|
||||
|
@@ -266,6 +266,7 @@ Project {
|
||||
"include/bindingproperty.h",
|
||||
"include/componenttextmodifier.h",
|
||||
"include/customnotifications.h",
|
||||
"include/enumerationmetainfo.h",
|
||||
"include/exception.h",
|
||||
"include/forwardview.h",
|
||||
"include/import.h",
|
||||
@@ -296,6 +297,7 @@ Project {
|
||||
"include/notimplementedexception.h",
|
||||
"include/plaintexteditmodifier.h",
|
||||
"include/propertycontainer.h",
|
||||
"include/propertymetainfo.h",
|
||||
"include/propertynode.h",
|
||||
"include/propertyparser.h",
|
||||
"include/qmlanchors.h",
|
||||
|
@@ -130,7 +130,7 @@ public:
|
||||
QSize{300, 300},
|
||||
QSize{1000, 1000},
|
||||
ImageCacheCollectorNullImageHandling::DontCaptureNullImage};
|
||||
TimeStampProvider timeStampProvider;
|
||||
PreviewTimeStampProvider timeStampProvider;
|
||||
AsynchronousExplicitImageCache cache{storage};
|
||||
AsynchronousImageFactory factory{storage, timeStampProvider, collector};
|
||||
};
|
||||
|
@@ -1,5 +1,5 @@
|
||||
add_qtc_test(tst_qml_testcore
|
||||
CONDITION TARGET QmlProjectManager
|
||||
CONDITION TARGET QmlProjectManager AND Qt5_VERSION VERSION_GREATER_EQUAL 6.2.0
|
||||
DEFINES
|
||||
QT_CREATOR
|
||||
QMLDESIGNER_TEST
|
||||
|
@@ -4232,6 +4232,17 @@ void tst_TestCore::testCopyModelRewriter2()
|
||||
QCOMPARE(stripWhiteSpaces(textEdit2.toPlainText()), stripWhiteSpaces(qmlString1));
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool contains(const QmlDesigner::PropertyMetaInfos &properties, QUtf8StringView propertyName)
|
||||
{
|
||||
auto found = std::find_if(properties.begin(), properties.end(), [&](const auto &property) {
|
||||
return property.name() == propertyName;
|
||||
});
|
||||
|
||||
return found != properties.end();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void tst_TestCore::testSubComponentManager()
|
||||
{
|
||||
const QString qmlString("import QtQuick 2.15\n"
|
||||
@@ -4267,7 +4278,7 @@ void tst_TestCore::testSubComponentManager()
|
||||
subComponentManager->update(QUrl::fromLocalFile(fileName), model->imports());
|
||||
|
||||
QVERIFY(model->hasNodeMetaInfo("QtQuick.Rectangle", 2, 15));
|
||||
QVERIFY(model->metaInfo("QtQuick.Rectangle").propertyNames().contains("border.width"));
|
||||
QVERIFY(contains(model->metaInfo("QtQuick.Rectangle").properties(), "border.width"));
|
||||
|
||||
model->rewriterView()->setTextModifier(&modifier);
|
||||
|
||||
@@ -4276,14 +4287,14 @@ void tst_TestCore::testSubComponentManager()
|
||||
QVERIFY(model->rewriterView()->rootModelNode().isValid());
|
||||
|
||||
QVERIFY(model->hasNodeMetaInfo("QtQuick.Rectangle", 2, 15));
|
||||
QVERIFY(model->metaInfo("QtQuick.Rectangle").propertyNames().contains("border.width"));
|
||||
QVERIFY(contains(model->metaInfo("QtQuick.Rectangle").properties(), "border.width"));
|
||||
|
||||
QVERIFY(model->metaInfo("<cpp>.QQuickPen").isValid());
|
||||
|
||||
QSKIP("File components not working TODO", SkipAll);
|
||||
NodeMetaInfo myButtonMetaInfo = model->metaInfo("MyButton");
|
||||
QVERIFY(myButtonMetaInfo.isValid());
|
||||
QVERIFY(myButtonMetaInfo.propertyNames().contains("border.width"));
|
||||
QVERIFY(contains(myButtonMetaInfo.properties(), "border.width"));
|
||||
QVERIFY(myButtonMetaInfo.hasProperty("border.width"));
|
||||
}
|
||||
|
||||
@@ -4638,7 +4649,7 @@ void tst_TestCore::testMetaInfoCustomType()
|
||||
QCOMPARE(propertyChangesInfo.superClasses().size(), 3);
|
||||
|
||||
// DeclarativePropertyChanges just has 3 properties
|
||||
QCOMPARE(propertyChangesInfo.propertyNames().size() - stateOperationInfo.propertyNames().size(), 3);
|
||||
QCOMPARE(propertyChangesInfo.properties().size() - stateOperationInfo.properties().size(), 3);
|
||||
|
||||
QApplication::processEvents();
|
||||
}
|
||||
@@ -4656,15 +4667,13 @@ void tst_TestCore::testMetaInfoEnums()
|
||||
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("transformOrigin"));
|
||||
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsEnumType("transformOrigin"));
|
||||
QCOMPARE(view->rootModelNode().metaInfo().propertyTypeName("transformOrigin"), QmlDesigner::TypeName("TransformOrigin"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("transformOrigin").contains(QLatin1String("Bottom")));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("transformOrigin").contains(QLatin1String("Top")));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("transformOrigin").isEnumType());
|
||||
QCOMPARE(view->rootModelNode().metaInfo().property("transformOrigin").propertyTypeName(),
|
||||
QmlDesigner::TypeName("TransformOrigin"));
|
||||
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsEnumType("horizontalAlignment"));
|
||||
QCOMPARE(view->rootModelNode().metaInfo().propertyTypeName("horizontalAlignment"), QmlDesigner::TypeName("HAlignment"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("horizontalAlignment").contains(QLatin1String("AlignLeft")));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("horizontalAlignment").contains(QLatin1String("AlignRight")));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("horizontalAlignment").isEnumType());
|
||||
QCOMPARE(view->rootModelNode().metaInfo().property("horizontalAlignment").propertyTypeName(),
|
||||
QmlDesigner::TypeName("HAlignment"));
|
||||
|
||||
QApplication::processEvents();
|
||||
}
|
||||
@@ -4743,8 +4752,8 @@ void tst_TestCore::testMetaInfoProperties()
|
||||
QVERIFY(textNodeMetaInfo.hasProperty("objectName")); // QtQuick.QObject
|
||||
QVERIFY(!textNodeMetaInfo.hasProperty("bla"));
|
||||
|
||||
QVERIFY(textNodeMetaInfo.propertyIsWritable("text"));
|
||||
QVERIFY(textNodeMetaInfo.propertyIsWritable("x"));
|
||||
QVERIFY(textNodeMetaInfo.property("text").isWritable());
|
||||
QVERIFY(textNodeMetaInfo.property("x").isWritable());
|
||||
|
||||
QApplication::processEvents();
|
||||
}
|
||||
@@ -4761,22 +4770,23 @@ void tst_TestCore::testMetaInfoDotProperties()
|
||||
QVERIFY(model->hasNodeMetaInfo("QtQuick.Text"));
|
||||
|
||||
QVERIFY(model->metaInfo("QtQuick.Rectangle").hasProperty("border"));
|
||||
QCOMPARE(model->metaInfo("QtQuick.Rectangle").propertyTypeName("border"), QmlDesigner::TypeName("<cpp>.QQuickPen"));
|
||||
QCOMPARE(model->metaInfo("QtQuick.Rectangle").property("border").propertyTypeName(),
|
||||
QmlDesigner::TypeName("<cpp>.QQuickPen"));
|
||||
|
||||
QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Text"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("font"));
|
||||
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.bold"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyNames().contains("font.bold"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyNames().contains("font.pointSize"));
|
||||
QVERIFY(contains(view->rootModelNode().metaInfo().properties(), "font.bold"));
|
||||
QVERIFY(contains(view->rootModelNode().metaInfo().properties(), "font.pointSize"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.pointSize"));
|
||||
|
||||
ModelNode rectNode(addNodeListChild(view->rootModelNode(), "QtQuick.Rectangle", 2, 0, "data"));
|
||||
|
||||
QVERIFY(rectNode.metaInfo().propertyNames().contains("implicitHeight"));
|
||||
QVERIFY(rectNode.metaInfo().propertyNames().contains("implicitWidth"));
|
||||
QVERIFY(rectNode.metaInfo().propertyNames().contains("anchors.topMargin"));
|
||||
QVERIFY(rectNode.metaInfo().propertyNames().contains("border.width"));
|
||||
QVERIFY(contains(rectNode.metaInfo().properties(), "implicitHeight"));
|
||||
QVERIFY(contains(rectNode.metaInfo().properties(), "implicitWidth"));
|
||||
QVERIFY(contains(rectNode.metaInfo().properties(), "anchors.topMargin"));
|
||||
QVERIFY(contains(rectNode.metaInfo().properties(), "border.width"));
|
||||
QVERIFY(rectNode.metaInfo().hasProperty("border"));
|
||||
QVERIFY(rectNode.metaInfo().hasProperty("border.width"));
|
||||
|
||||
@@ -4796,20 +4806,20 @@ void tst_TestCore::testMetaInfoListProperties()
|
||||
QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Item"));
|
||||
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("states"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("states"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("states").isListProperty());
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("children"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("children"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("children").isListProperty());
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("data"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("data"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("data").isListProperty());
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("resources"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("resources"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("resources").isListProperty());
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("transitions"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("transitions"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("transitions").isListProperty());
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("transform"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("transform"));
|
||||
QVERIFY(view->rootModelNode().metaInfo().property("transform").isListProperty());
|
||||
|
||||
QVERIFY(view->rootModelNode().metaInfo().hasProperty("parent"));
|
||||
QVERIFY(!view->rootModelNode().metaInfo().propertyIsListProperty("parent"));
|
||||
QVERIFY(!view->rootModelNode().metaInfo().property("parent").isListProperty());
|
||||
|
||||
QApplication::processEvents();
|
||||
}
|
||||
@@ -4904,8 +4914,8 @@ void tst_TestCore::testQtQuickControls2()
|
||||
QVERIFY(rootModelNode.metaInfo().isGraphicalItem());
|
||||
QVERIFY(rootModelNode.isSubclassOf("QtQuick.Window.Window", -1, -1));
|
||||
|
||||
QVERIFY(!rootModelNode.metaInfo().directPropertyNames().contains("visible"));
|
||||
QVERIFY(rootModelNode.metaInfo().propertyNames().contains("visible"));
|
||||
QVERIFY(!contains(rootModelNode.metaInfo().localProperties(), "visible"));
|
||||
QVERIFY(contains(rootModelNode.metaInfo().properties(), "visible"));
|
||||
|
||||
QVERIFY(!rootModelNode.allSubModelNodes().isEmpty());
|
||||
ModelNode button = rootModelNode.allSubModelNodes().first();
|
||||
|
@@ -25,12 +25,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "propertymetainfo.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "qmldesignercorelib_global.h"
|
||||
#include <qmldesignercorelib_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDeclarativeContext;
|
||||
@@ -51,19 +53,14 @@ public:
|
||||
bool isValid() const { return {}; }
|
||||
bool isFileComponent() const { return {}; }
|
||||
bool hasProperty(const PropertyName &) const { return {}; }
|
||||
PropertyMetaInfos properties() const { return {}; }
|
||||
PropertyMetaInfos localProperties() const { return {}; }
|
||||
PropertyMetaInfo property(const PropertyName &) const { return {}; }
|
||||
PropertyNameList propertyNames() const { return {}; }
|
||||
PropertyNameList signalNames() const { return {}; }
|
||||
PropertyNameList directPropertyNames() const { return {}; }
|
||||
PropertyName defaultPropertyName() const { return "data"; }
|
||||
bool hasDefaultProperty() const { return {}; }
|
||||
TypeName propertyTypeName(const PropertyName &) const { return {}; }
|
||||
bool propertyIsWritable(const PropertyName &) const { return {}; }
|
||||
bool propertyIsListProperty(const PropertyName &) const { return {}; }
|
||||
bool propertyIsEnumType(const PropertyName &) const { return {}; }
|
||||
bool propertyIsPrivate(const PropertyName &) const { return {}; }
|
||||
QString propertyEnumScope(const PropertyName &) const { return {}; }
|
||||
QStringList propertyKeysForEnum(const PropertyName &) const { return {}; }
|
||||
QVariant propertyCastedValue(const PropertyName &, const QVariant &) const { return {}; }
|
||||
|
||||
QList<NodeMetaInfo> classHierarchy() const { return {}; }
|
||||
QList<NodeMetaInfo> superClasses() const { return {}; }
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qmldesignercorelib_global.h>
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class PropertyMetaInfo
|
||||
{
|
||||
public:
|
||||
PropertyMetaInfo() = default;
|
||||
PropertyMetaInfo(QSharedPointer<class NodeMetaInfoPrivate>, const PropertyName &) {}
|
||||
~PropertyMetaInfo() {}
|
||||
|
||||
const TypeName &propertyTypeName() const
|
||||
{
|
||||
static TypeName foo;
|
||||
return foo;
|
||||
}
|
||||
class NodeMetaInfo propertyNodeMetaInfo() const;
|
||||
|
||||
bool isWritable() const { return {}; }
|
||||
bool isListProperty() const { return {}; }
|
||||
bool isEnumType() const { return {}; }
|
||||
bool isPrivate() const { return {}; }
|
||||
bool isPointer() const { return {}; }
|
||||
QVariant castedValue(const QVariant &) const { return {}; }
|
||||
PropertyName name() const & { return {}; }
|
||||
|
||||
template<typename... TypeName>
|
||||
bool hasPropertyTypeName(const TypeName &...typeName) const
|
||||
{
|
||||
auto propertyTypeName_ = propertyTypeName();
|
||||
return ((propertyTypeName_ == typeName) && ...);
|
||||
}
|
||||
};
|
||||
|
||||
using PropertyMetaInfos = std::vector<PropertyMetaInfo>;
|
||||
|
||||
} // namespace QmlDesigner
|
Reference in New Issue
Block a user