forked from qt-creator/qt-creator
Extend bindingmodel and minor fixes
- Include singletons in the list of sources (former sourceModelNodes)
- Do not suggest sources on bindings that are initialized without a
source node. Prevent constructs like
"property string p: button.qsTr("STREXPR3")".
- Allow changing the name of the target property and update the
delegate properly when doing so.
- Remove superfluous emitCurrentIndex emission from the
dynamicpropertiesmodel.
- Add missing qml imports.
Note that it is still possible to create illegal constructs if the user
wants to.
Change-Id: I084978f2f8d451df076d1b556db15764e17e31fb
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import StudioTheme 1.0 as StudioTheme
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
import HelperWidgets as HelperWidgets
|
||||||
|
|
||||||
PopupDialog {
|
PopupDialog {
|
||||||
property alias backend: form.backend
|
property alias backend: form.backend
|
||||||
@@ -15,7 +16,7 @@ PopupDialog {
|
|||||||
text: qsTr("Owner")
|
text: qsTr("Owner")
|
||||||
font.pixelSize: StudioTheme.Values.myFontSize
|
font.pixelSize: StudioTheme.Values.myFontSize
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
ToolTipArea {
|
HelperWidgets.ToolTipArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
tooltip: qsTr("The owner of the property")
|
tooltip: qsTr("The owner of the property")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,10 +64,16 @@ Column {
|
|||||||
onCurrentTypeIndexChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
|
onCurrentTypeIndexChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupLabel {
|
StudioControls.TopLevelComboBox {
|
||||||
|
id: name
|
||||||
width: root.columnWidth
|
width: root.columnWidth
|
||||||
text: backend.property.currentText
|
style: StudioTheme.Values.connectionPopupControlStyle
|
||||||
}
|
|
||||||
|
|
||||||
|
model: backend.property.model ?? []
|
||||||
|
|
||||||
|
onActivated: backend.property.activateIndex(name.currentIndex)
|
||||||
|
property int currentTypeIndex: backend.property.currentIndex ?? 0
|
||||||
|
onCurrentTypeIndexChanged: name.currentIndex = name.currentTypeIndex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import StudioControls 1.0 as StudioControls
|
import StudioControls 1.0 as StudioControls
|
||||||
import StudioTheme 1.0 as StudioTheme
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
import HelperWidgets 2.0 as HelperWidgets
|
||||||
|
|
||||||
PopupDialog {
|
PopupDialog {
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ PopupDialog {
|
|||||||
text: qsTr("Target")
|
text: qsTr("Target")
|
||||||
font.pixelSize: StudioTheme.Values.myFontSize
|
font.pixelSize: StudioTheme.Values.myFontSize
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
ToolTipArea {
|
HelperWidgets.ToolTipArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
tooltip: qsTr("Choose the target for the signal.")
|
tooltip: qsTr("Choose the target for the signal.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Text {
|
|||||||
color: StudioTheme.Values.themeTextColor
|
color: StudioTheme.Values.themeTextColor
|
||||||
font.pixelSize: StudioTheme.Values.myFontSize
|
font.pixelSize: StudioTheme.Values.myFontSize
|
||||||
property alias tooltip: area.tooltip
|
property alias tooltip: area.tooltip
|
||||||
ToolTipArea {
|
HelperWidgets.ToolTipArea {
|
||||||
id: area
|
id: area
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
tooltip: qsTr("missing")
|
tooltip: qsTr("missing")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import StudioTheme 1.0 as StudioTheme
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
import HelperWidgets as HelperWidgets
|
||||||
|
|
||||||
PopupDialog {
|
PopupDialog {
|
||||||
property alias backend: form.backend
|
property alias backend: form.backend
|
||||||
@@ -16,7 +17,7 @@ PopupDialog {
|
|||||||
text: qsTr("Owner")
|
text: qsTr("Owner")
|
||||||
font.pixelSize: StudioTheme.Values.myFontSize
|
font.pixelSize: StudioTheme.Values.myFontSize
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
ToolTipArea {
|
HelperWidgets.ToolTipArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
tooltip: qsTr("The owner of the property")
|
tooltip: qsTr("The owner of the property")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "bindingmodelitem.h"
|
#include "bindingmodelitem.h"
|
||||||
#include "connectionview.h"
|
#include "connectionview.h"
|
||||||
#include "connectioneditorutils.h"
|
#include "connectioneditorutils.h"
|
||||||
|
#include "modelfwd.h"
|
||||||
|
|
||||||
#include <bindingproperty.h>
|
#include <bindingproperty.h>
|
||||||
#include <nodemetainfo.h>
|
#include <nodemetainfo.h>
|
||||||
@@ -145,11 +146,12 @@ void BindingModel::updateItem(const BindingProperty &property)
|
|||||||
item->updateProperty(property);
|
item->updateProperty(property);
|
||||||
else
|
else
|
||||||
appendRow(new BindingModelItem(property));
|
appendRow(new BindingModelItem(property));
|
||||||
|
|
||||||
|
m_delegate->update(currentProperty(), m_connectionView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindingModel::removeItem(const AbstractProperty &property)
|
void BindingModel::removeItem(const AbstractProperty &property)
|
||||||
{
|
{
|
||||||
|
|
||||||
AbstractProperty current = currentProperty();
|
AbstractProperty current = currentProperty();
|
||||||
if (auto index = rowForProperty(property))
|
if (auto index = rowForProperty(property))
|
||||||
static_cast<void>(removeRow(*index));
|
static_cast<void>(removeRow(*index));
|
||||||
@@ -167,7 +169,33 @@ void BindingModel::commitExpression(int row, const QString &expression)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
connectionView()->executeInTransaction(__FUNCTION__, [&bindingProperty, expression]() {
|
connectionView()->executeInTransaction(__FUNCTION__, [&bindingProperty, expression]() {
|
||||||
|
if (bindingProperty.isDynamic()) {
|
||||||
|
TypeName type = bindingProperty.dynamicTypeName();
|
||||||
|
bindingProperty.setDynamicTypeNameAndExpression(type, expression);
|
||||||
|
} else {
|
||||||
bindingProperty.setExpression(expression.trimmed());
|
bindingProperty.setExpression(expression.trimmed());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingModel::commitPropertyName(int row, const PropertyName &name)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(connectionView(), return);
|
||||||
|
|
||||||
|
BindingProperty bindingProperty = propertyForRow(row);
|
||||||
|
if (!bindingProperty.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
connectionView()->executeInTransaction(__FUNCTION__, [&]() {
|
||||||
|
const TypeName type = bindingProperty.dynamicTypeName();
|
||||||
|
const QString expression = bindingProperty.expression();
|
||||||
|
|
||||||
|
ModelNode node = bindingProperty.parentModelNode();
|
||||||
|
node.removeProperty(bindingProperty.name());
|
||||||
|
if (bindingProperty.isDynamic())
|
||||||
|
node.bindingProperty(name).setDynamicTypeNameAndExpression(type, expression);
|
||||||
|
else
|
||||||
|
node.bindingProperty(name).setExpression(expression);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +256,10 @@ BindingModelBackendDelegate::BindingModelBackendDelegate(BindingModel *parent)
|
|||||||
connect(&m_sourceNodeProperty, &StudioQmlComboBoxBackend::activated, this, [this]() {
|
connect(&m_sourceNodeProperty, &StudioQmlComboBoxBackend::activated, this, [this]() {
|
||||||
expressionChanged();
|
expressionChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(&m_property, &StudioQmlComboBoxBackend::activated, this, [this]() {
|
||||||
|
propertyNameChanged();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindingModelBackendDelegate::update(const BindingProperty &property, AbstractView *view)
|
void BindingModelBackendDelegate::update(const BindingProperty &property, AbstractView *view)
|
||||||
@@ -243,17 +275,20 @@ void BindingModelBackendDelegate::update(const BindingProperty &property, Abstra
|
|||||||
|
|
||||||
auto [sourceNodeName, sourcePropertyName] = splitExpression(property.expression());
|
auto [sourceNodeName, sourcePropertyName] = splitExpression(property.expression());
|
||||||
|
|
||||||
QString targetName = QString::fromUtf8(property.name());
|
QStringList sourceNodes = {};
|
||||||
m_targetNode = idOrTypeName(property.parentModelNode());
|
if (!sourceNodeName.isEmpty())
|
||||||
|
sourceNodes = addName(availableSources(view), sourceNodeName);
|
||||||
|
|
||||||
auto modelNodes = addName(availableModelNodes(view), sourceNodeName);
|
m_sourceNode.setModel(sourceNodes);
|
||||||
m_sourceNode.setModel(modelNodes);
|
|
||||||
m_sourceNode.setCurrentText(sourceNodeName);
|
m_sourceNode.setCurrentText(sourceNodeName);
|
||||||
|
|
||||||
auto sourceproperties = addName(availableSourceProperties(property, view), sourcePropertyName);
|
auto sourceproperties = addName(availableSourceProperties(property, view), sourcePropertyName);
|
||||||
m_sourceNodeProperty.setModel(sourceproperties);
|
m_sourceNodeProperty.setModel(sourceproperties);
|
||||||
m_sourceNodeProperty.setCurrentText(sourcePropertyName);
|
m_sourceNodeProperty.setCurrentText(sourcePropertyName);
|
||||||
|
|
||||||
|
QString targetName = QString::fromUtf8(property.name());
|
||||||
|
m_targetNode = idOrTypeName(property.parentModelNode());
|
||||||
|
|
||||||
auto targetProperties = addName(availableTargetProperties(property), targetName);
|
auto targetProperties = addName(availableTargetProperties(property), targetName);
|
||||||
m_property.setModel(targetProperties);
|
m_property.setModel(targetProperties);
|
||||||
m_property.setCurrentText(targetName);
|
m_property.setCurrentText(targetName);
|
||||||
@@ -283,12 +318,12 @@ StudioQmlComboBoxBackend *BindingModelBackendDelegate::sourceProperty()
|
|||||||
|
|
||||||
void BindingModelBackendDelegate::expressionChanged() const
|
void BindingModelBackendDelegate::expressionChanged() const
|
||||||
{
|
{
|
||||||
|
auto commit = [this]() {
|
||||||
BindingModel *model = qobject_cast<BindingModel *>(parent());
|
BindingModel *model = qobject_cast<BindingModel *>(parent());
|
||||||
QTC_ASSERT(model, return);
|
QTC_ASSERT(model, return);
|
||||||
|
|
||||||
const QString sourceNode = m_sourceNode.currentText();
|
const QString sourceNode = m_sourceNode.currentText();
|
||||||
const QString sourceProperty = m_sourceNodeProperty.currentText();
|
const QString sourceProperty = m_sourceNodeProperty.currentText();
|
||||||
|
|
||||||
QString expression;
|
QString expression;
|
||||||
if (sourceProperty.isEmpty())
|
if (sourceProperty.isEmpty())
|
||||||
expression = sourceNode;
|
expression = sourceNode;
|
||||||
@@ -297,6 +332,22 @@ void BindingModelBackendDelegate::expressionChanged() const
|
|||||||
|
|
||||||
int row = model->currentIndex();
|
int row = model->currentIndex();
|
||||||
model->commitExpression(row, expression);
|
model->commitExpression(row, expression);
|
||||||
|
};
|
||||||
|
|
||||||
|
callLater(commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingModelBackendDelegate::propertyNameChanged() const
|
||||||
|
{
|
||||||
|
auto commit = [this]() {
|
||||||
|
BindingModel *model = qobject_cast<BindingModel *>(parent());
|
||||||
|
QTC_ASSERT(model, return);
|
||||||
|
const PropertyName propertyName = m_property.currentText().toUtf8();
|
||||||
|
int row = model->currentIndex();
|
||||||
|
model->commitPropertyName(row, propertyName);
|
||||||
|
};
|
||||||
|
|
||||||
|
callLater(commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public:
|
|||||||
void removeItem(const AbstractProperty &property);
|
void removeItem(const AbstractProperty &property);
|
||||||
|
|
||||||
void commitExpression(int row, const QString &expression);
|
void commitExpression(int row, const QString &expression);
|
||||||
|
void commitPropertyName(int row, const PropertyName &name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
@@ -86,6 +87,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
QString targetNode() const;
|
QString targetNode() const;
|
||||||
void expressionChanged() const;
|
void expressionChanged() const;
|
||||||
|
void propertyNameChanged() const;
|
||||||
|
|
||||||
StudioQmlComboBoxBackend *property();
|
StudioQmlComboBoxBackend *property();
|
||||||
StudioQmlComboBoxBackend *sourceNode();
|
StudioQmlComboBoxBackend *sourceNode();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <qmldesignertr.h>
|
#include <qmldesignertr.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
@@ -82,6 +83,38 @@ NodeMetaInfo dynamicTypeMetaInfo(const AbstractProperty& property)
|
|||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool metaInfoIsCompatibleUnsafe(const NodeMetaInfo &sourceType, const NodeMetaInfo &targetType)
|
||||||
|
{
|
||||||
|
if (sourceType.isVariant())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (sourceType.isBool() && targetType.isBool())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (sourceType == targetType)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (sourceType.isNumber() && targetType.isNumber())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (sourceType.isString() && targetType.isString())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (sourceType.isUrl() && targetType.isUrl())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (sourceType.isColor() && targetType.isColor())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool metaInfoIsCompatible(const NodeMetaInfo &sourceType, const PropertyMetaInfo &metaInfo)
|
||||||
|
{
|
||||||
|
NodeMetaInfo targetType = metaInfo.propertyType();
|
||||||
|
return metaInfoIsCompatibleUnsafe(sourceType, targetType);
|
||||||
|
}
|
||||||
|
|
||||||
QVariant typeConvertVariant(const QVariant &variant, const QmlDesigner::TypeName &typeName)
|
QVariant typeConvertVariant(const QVariant &variant, const QmlDesigner::TypeName &typeName)
|
||||||
{
|
{
|
||||||
QVariant returnValue = variant;
|
QVariant returnValue = variant;
|
||||||
@@ -217,7 +250,21 @@ QString defaultExpressionForType(const TypeName &type)
|
|||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList availableModelNodes(AbstractView *view)
|
QStringList singletonsFromView(AbstractView *view)
|
||||||
|
{
|
||||||
|
RewriterView *rv = view->rewriterView();
|
||||||
|
if (!rv)
|
||||||
|
return { };
|
||||||
|
|
||||||
|
QStringList out;
|
||||||
|
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||||
|
if (data.isSingleton && !data.typeName.isEmpty())
|
||||||
|
out.push_back(data.typeName);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList availableSources(AbstractView *view)
|
||||||
{
|
{
|
||||||
QStringList sourceNodes;
|
QStringList sourceNodes;
|
||||||
for (const ModelNode &modelNode : view->allModelNodes()) {
|
for (const ModelNode &modelNode : view->allModelNodes()) {
|
||||||
@@ -225,22 +272,7 @@ QStringList availableModelNodes(AbstractView *view)
|
|||||||
sourceNodes.append(modelNode.id());
|
sourceNodes.append(modelNode.id());
|
||||||
}
|
}
|
||||||
std::sort(sourceNodes.begin(), sourceNodes.end());
|
std::sort(sourceNodes.begin(), sourceNodes.end());
|
||||||
return sourceNodes;
|
return singletonsFromView(view) + sourceNodes;
|
||||||
}
|
|
||||||
|
|
||||||
QStringList dynamicPropertyNamesFromNode(const ModelNode& node)
|
|
||||||
{
|
|
||||||
QStringList dynamicProperties;
|
|
||||||
for (const VariantProperty &variantProperty : node.variantProperties()) {
|
|
||||||
if (variantProperty.isDynamic())
|
|
||||||
dynamicProperties << QString::fromUtf8(variantProperty.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const BindingProperty &bindingProperty : node.bindingProperties()) {
|
|
||||||
if (bindingProperty.isDynamic())
|
|
||||||
dynamicProperties << QString::fromUtf8((bindingProperty.name()));
|
|
||||||
}
|
|
||||||
return dynamicProperties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList availableTargetProperties(const BindingProperty &bindingProperty)
|
QStringList availableTargetProperties(const BindingProperty &bindingProperty)
|
||||||
@@ -261,10 +293,9 @@ QStringList availableTargetProperties(const BindingProperty &bindingProperty)
|
|||||||
writableProperties.push_back(QString::fromUtf8(property.name()));
|
writableProperties.push_back(QString::fromUtf8(property.name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return dynamicPropertyNamesFromNode(modelNode) + writableProperties;
|
return writableProperties;
|
||||||
}
|
}
|
||||||
|
return { };
|
||||||
return dynamicPropertyNamesFromNode(modelNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelNode getNodeByIdOrParent(AbstractView *view, const QString &id, const ModelNode &targetNode)
|
ModelNode getNodeByIdOrParent(AbstractView *view, const QString &id, const ModelNode &targetNode)
|
||||||
@@ -278,64 +309,13 @@ ModelNode getNodeByIdOrParent(AbstractView *view, const QString &id, const Model
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool metaInfoIsCompatible(const NodeMetaInfo& sourceType, const PropertyMetaInfo& metaInfo)
|
|
||||||
{
|
|
||||||
if (sourceType.isVariant())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
NodeMetaInfo targetType = metaInfo.propertyType();
|
|
||||||
if (sourceType.isBool() && targetType.isBool())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (sourceType == targetType)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (sourceType.isNumber() && targetType.isNumber())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (sourceType.isString() && targetType.isString())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (sourceType.isUrl() && targetType.isUrl())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (sourceType.isColor() && targetType.isColor())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList availableSourceProperties(const BindingProperty &bindingProperty, AbstractView *view)
|
QStringList availableSourceProperties(const BindingProperty &bindingProperty, AbstractView *view)
|
||||||
{
|
{
|
||||||
const QString expression = bindingProperty.expression();
|
const QString expression = bindingProperty.expression();
|
||||||
const QStringList stringlist = expression.split(QLatin1String("."));
|
const QStringList stringlist = expression.split(QLatin1String("."));
|
||||||
QStringList possibleProperties;
|
|
||||||
|
|
||||||
const QString &id = stringlist.constFirst();
|
const QString &id = stringlist.constFirst();
|
||||||
ModelNode modelNode = getNodeByIdOrParent(view, id, bindingProperty.parentModelNode());
|
ModelNode modelNode = getNodeByIdOrParent(view, id, bindingProperty.parentModelNode());
|
||||||
if (!modelNode.isValid()) {
|
|
||||||
//if it's not a valid model node, maybe it's a singleton
|
|
||||||
if (RewriterView *rv = view->rewriterView()) {
|
|
||||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
|
||||||
if (!data.typeName.isEmpty() && data.typeName == id) {
|
|
||||||
NodeMetaInfo metaInfo = view->model()->metaInfo(data.typeName.toUtf8());
|
|
||||||
|
|
||||||
if (metaInfo.isValid()) {
|
|
||||||
for (const auto &property : metaInfo.properties()) {
|
|
||||||
//without check for now
|
|
||||||
possibleProperties.push_back(QString::fromUtf8(property.name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return possibleProperties;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qWarning() << __FUNCTION__ << " invalid model node";
|
|
||||||
return QStringList();
|
|
||||||
}
|
|
||||||
|
|
||||||
possibleProperties = possibleProperties + dynamicPropertyNamesFromNode(modelNode);
|
|
||||||
|
|
||||||
NodeMetaInfo type;
|
NodeMetaInfo type;
|
||||||
if (bindingProperty.isDynamic()) {
|
if (bindingProperty.isDynamic()) {
|
||||||
@@ -345,6 +325,39 @@ QStringList availableSourceProperties(const BindingProperty &bindingProperty, Ab
|
|||||||
} else
|
} else
|
||||||
qWarning() << __FUNCTION__ << " no meta info for target node";
|
qWarning() << __FUNCTION__ << " no meta info for target node";
|
||||||
|
|
||||||
|
QStringList possibleProperties;
|
||||||
|
if (!modelNode.isValid()) {
|
||||||
|
QStringList singletons = singletonsFromView(view);
|
||||||
|
if (singletons.contains(id)) {
|
||||||
|
Model *model = view->model();
|
||||||
|
QTC_ASSERT(model, return {});
|
||||||
|
if (NodeMetaInfo metaInfo = model->metaInfo(id.toUtf8()); metaInfo.isValid()) {
|
||||||
|
for (const auto &property : metaInfo.properties()) {
|
||||||
|
if (metaInfoIsCompatible(type, property))
|
||||||
|
possibleProperties.push_back(QString::fromUtf8(property.name()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return possibleProperties;
|
||||||
|
}
|
||||||
|
qWarning() << __FUNCTION__ << " invalid model node";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto isCompatible = [type](const AbstractProperty& other) {
|
||||||
|
auto otherType = dynamicTypeMetaInfo(other);
|
||||||
|
return metaInfoIsCompatibleUnsafe(type, otherType);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const VariantProperty &variantProperty : modelNode.variantProperties()) {
|
||||||
|
if (variantProperty.isDynamic() && isCompatible(variantProperty))
|
||||||
|
possibleProperties << QString::fromUtf8(variantProperty.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const BindingProperty &bindingProperty : modelNode.bindingProperties()) {
|
||||||
|
if (bindingProperty.isDynamic() && isCompatible(bindingProperty))
|
||||||
|
possibleProperties << QString::fromUtf8((bindingProperty.name()));
|
||||||
|
}
|
||||||
|
|
||||||
NodeMetaInfo metaInfo = modelNode.metaInfo();
|
NodeMetaInfo metaInfo = modelNode.metaInfo();
|
||||||
if (metaInfo.isValid()) {
|
if (metaInfo.isValid()) {
|
||||||
for (const auto &property : metaInfo.properties()) {
|
for (const auto &property : metaInfo.properties()) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ bool isDynamicVariantPropertyType(const TypeName &type);
|
|||||||
QVariant defaultValueForType(const TypeName &type);
|
QVariant defaultValueForType(const TypeName &type);
|
||||||
QString defaultExpressionForType(const TypeName &type);
|
QString defaultExpressionForType(const TypeName &type);
|
||||||
|
|
||||||
QStringList availableModelNodes(AbstractView *view);
|
QStringList availableSources(AbstractView *view);
|
||||||
QStringList availableTargetProperties(const BindingProperty &bindingProperty);
|
QStringList availableTargetProperties(const BindingProperty &bindingProperty);
|
||||||
QStringList availableSourceProperties(const BindingProperty &bindingProperty, AbstractView *view);
|
QStringList availableSourceProperties(const BindingProperty &bindingProperty, AbstractView *view);
|
||||||
QList<AbstractProperty> dynamicPropertiesFromNode(const ModelNode &node);
|
QList<AbstractProperty> dynamicPropertiesFromNode(const ModelNode &node);
|
||||||
|
|||||||
@@ -168,7 +168,6 @@ void DynamicPropertiesModel::removeItem(const AbstractProperty &property)
|
|||||||
static_cast<void>(removeRow(*index));
|
static_cast<void>(removeRow(*index));
|
||||||
|
|
||||||
setCurrentProperty(current);
|
setCurrentProperty(current);
|
||||||
emit currentIndexChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> DynamicPropertiesModel::roleNames() const
|
QHash<int, QByteArray> DynamicPropertiesModel::roleNames() const
|
||||||
|
|||||||
Reference in New Issue
Block a user