forked from qt-creator/qt-creator
QmlDesigner: Extend Connections view support
- Connection view support to components - Connection view support to singletons - Minor reparenting improvements Task: QDS-2411 Change-Id: I337535012dbb3d3a1722d75d89156463eabb8a4c Reviewed-by: Vikas Pachdha <vikas.pachdha@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
3e1d204c32
commit
66122492a6
@@ -221,6 +221,13 @@ void ConnectionModel::updateTargetNode(int rowNumber)
|
||||
isSingleton = true;
|
||||
break;
|
||||
}
|
||||
} else if (isAlias) {
|
||||
if (data.typeName == newTarget.split(".").constFirst()) {
|
||||
if (connectionView()->model()->metaInfo(data.typeName.toUtf8()).isValid()) {
|
||||
isSingleton = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,7 +236,7 @@ void ConnectionModel::updateTargetNode(int rowNumber)
|
||||
if (!newTarget.isEmpty()) {
|
||||
//if it's a singleton, then let's reparent connections to rootNode,
|
||||
//if it's an alias, then reparent to alias property owner:
|
||||
const ModelNode parent = connectionView()->modelNodeForId(isSingleton
|
||||
const ModelNode parent = connectionView()->modelNodeForId((isSingleton || (isSingleton && isAlias))
|
||||
? connectionView()->rootModelNode().id()
|
||||
: isAlias
|
||||
? newTarget.split(".").constFirst()
|
||||
@@ -255,35 +262,36 @@ void ConnectionModel::updateCustomData(QStandardItem *item, const SignalHandlerP
|
||||
|
||||
ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connection) const
|
||||
{
|
||||
BindingProperty bindingProperty = connection.bindingProperty("target");
|
||||
ModelNode result;
|
||||
|
||||
const BindingProperty bindingProperty = connection.bindingProperty("target");
|
||||
const QString bindExpression = bindingProperty.expression();
|
||||
|
||||
if (bindingProperty.isValid()) {
|
||||
bool isAlias = bindingProperty.expression().contains(".");
|
||||
|
||||
if (bindingProperty.expression() == QLatin1String("parent"))
|
||||
return connection.parentProperty().parentModelNode();
|
||||
else if (isAlias) {
|
||||
QStringList substr = bindingProperty.expression().split(".");
|
||||
if (bindExpression == QLatin1String("parent")) {
|
||||
result = connection.parentProperty().parentModelNode();
|
||||
} else if (bindExpression.contains(".")) {
|
||||
QStringList substr = bindExpression.split(".");
|
||||
const QString itemId = substr.constFirst();
|
||||
if (substr.size() > 1) {
|
||||
ModelNode aliasParent = connectionView()->modelNodeForId(substr.constFirst());
|
||||
QString aliasBody = substr.at(1);
|
||||
if (aliasParent.hasProperty(aliasBody.toUtf8())) {
|
||||
AbstractProperty abstractProp = aliasParent.property(aliasBody.toUtf8());
|
||||
if (abstractProp.isBindingProperty()) {
|
||||
BindingProperty binding = abstractProp.toBindingProperty();
|
||||
if (connectionView()->hasId(binding.expression())) {
|
||||
ModelNode resolve = connectionView()->modelNodeForId(binding.expression());
|
||||
if (resolve.isValid())
|
||||
return resolve;
|
||||
}
|
||||
const ModelNode aliasParent = (itemId == QLatin1String("parent")
|
||||
? connection.parentProperty().parentModelNode()
|
||||
: connectionView()->modelNodeForId(itemId));
|
||||
substr.removeFirst(); //remove id, only alias pieces left
|
||||
const QString aliasBody = substr.join(".");
|
||||
if (aliasParent.isValid() && aliasParent.hasBindingProperty(aliasBody.toUtf8())) {
|
||||
const BindingProperty binding = aliasParent.bindingProperty(aliasBody.toUtf8());
|
||||
if (binding.isValid() && connectionView()->hasId(binding.expression())) {
|
||||
result = connectionView()->modelNodeForId(binding.expression());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = connectionView()->modelNodeForId(bindExpression);
|
||||
}
|
||||
return connectionView()->modelNodeForId(bindingProperty.expression());
|
||||
}
|
||||
|
||||
return ModelNode();
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConnectionModel::addConnection()
|
||||
@@ -355,8 +363,7 @@ void ConnectionModel::deleteConnectionByRow(int currentRow)
|
||||
if (allSignals.size() > 1) {
|
||||
if (allSignals.contains(targetSignal))
|
||||
node.removeProperty(targetSignal.name());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
node.destroy();
|
||||
}
|
||||
}
|
||||
@@ -448,21 +455,44 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co
|
||||
{
|
||||
QStringList stringList;
|
||||
|
||||
if (connection.isValid()) {
|
||||
auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) {
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) {
|
||||
NodeMetaInfo propertyMetaInfo = connectionView()->model()->metaInfo(
|
||||
metaInfo.propertyTypeName(aliasPart.toUtf8()));
|
||||
if (propertyMetaInfo.isValid()) {
|
||||
return propertyNameListToStringList(propertyMetaInfo.signalNames());
|
||||
}
|
||||
}
|
||||
return QStringList();
|
||||
};
|
||||
|
||||
if (connection.isValid()) {
|
||||
//separate check for singletons
|
||||
if (connection.hasBindingProperty("target")) {
|
||||
BindingProperty bp = connection.bindingProperty("target");
|
||||
const BindingProperty bp = connection.bindingProperty("target");
|
||||
|
||||
if (bp.isValid()) {
|
||||
if (RewriterView *rv = connectionView()->rewriterView()) {
|
||||
const QString bindExpression = bp.expression();
|
||||
|
||||
if (const RewriterView * const rv = connectionView()->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
if (data.typeName == bp.expression()) {
|
||||
if (data.typeName == bindExpression) {
|
||||
NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
||||
if (metaInfo.isValid()) {
|
||||
stringList.append(propertyNameListToStringList(metaInfo.signalNames()));
|
||||
return stringList;
|
||||
stringList << propertyNameListToStringList(metaInfo.signalNames());
|
||||
break;
|
||||
}
|
||||
} else if (bindExpression.contains(".")) {
|
||||
//if it doesn't fit the same name, maybe it's an alias?
|
||||
QStringList expression = bindExpression.split(".");
|
||||
if ((expression.size() > 1) && (expression.constFirst() == data.typeName)) {
|
||||
expression.removeFirst();
|
||||
|
||||
stringList << getAliasMetaSignals(
|
||||
expression.join("."),
|
||||
connectionView()->model()->metaInfo(data.typeName.toUtf8()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,6 +504,30 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co
|
||||
ModelNode targetNode = getTargetNodeForConnection(connection);
|
||||
if (targetNode.isValid() && targetNode.metaInfo().isValid()) {
|
||||
stringList.append(propertyNameListToStringList(targetNode.metaInfo().signalNames()));
|
||||
} else {
|
||||
//most likely it's component's internal alias:
|
||||
|
||||
if (connection.hasBindingProperty("target")) {
|
||||
const BindingProperty bp = connection.bindingProperty("target");
|
||||
|
||||
if (bp.isValid()) {
|
||||
const QString bindExpression = bp.expression();
|
||||
QStringList expression = bp.expression().split(".");
|
||||
if (expression.size() > 1) {
|
||||
const QString itemId = expression.constFirst();
|
||||
if (connectionView()->hasId(itemId)) {
|
||||
ModelNode parentItem = connectionView()->modelNodeForId(itemId);
|
||||
if (parentItem.isValid()
|
||||
&& parentItem.hasMetaInfo()
|
||||
&& parentItem.metaInfo().isValid()) {
|
||||
expression.removeFirst();
|
||||
stringList << getAliasMetaSignals(expression.join("."),
|
||||
parentItem.metaInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -295,6 +295,35 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
||||
|
||||
switch (index.column()) {
|
||||
case ConnectionModel::TargetModelNodeRow: {
|
||||
|
||||
auto addMetaInfoProperties = [&](const NodeMetaInfo& itemMetaInfo, QString itemName){
|
||||
if (itemMetaInfo.isValid()) {
|
||||
for (const PropertyName &propertyName : itemMetaInfo.directPropertyNames()) {
|
||||
TypeName propertyType = itemMetaInfo.propertyTypeName(propertyName);
|
||||
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)) {
|
||||
NodeMetaInfo propertyMetaInfo =
|
||||
connectionModel->connectionView()->model()->metaInfo(propertyType);
|
||||
if (propertyMetaInfo.isValid()) {
|
||||
if (propertyMetaInfo.isQmlItem()) {
|
||||
connectionComboBox->addItem(itemName
|
||||
+ "."
|
||||
+ propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (const ModelNode &modelNode : connectionModel->connectionView()->allModelNodes()) {
|
||||
if (!modelNode.id().isEmpty()) {
|
||||
connectionComboBox->addItem(modelNode.id());
|
||||
@@ -308,25 +337,24 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Components
|
||||
if (modelNode.isComponent()) {
|
||||
NodeMetaInfo componentMetaInfo = modelNode.metaInfo();
|
||||
addMetaInfoProperties(componentMetaInfo, modelNode.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
//singletons:
|
||||
if (RewriterView* rv = connectionModel->connectionView()->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
//singleton itself
|
||||
connectionComboBox->addItem(data.typeName);
|
||||
|
||||
//its properties, mostly looking for aliases:
|
||||
NodeMetaInfo metaInfo = connectionModel->connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
||||
|
||||
if (metaInfo.isValid()) {
|
||||
for (const PropertyName &propertyName : metaInfo.propertyNames()) {
|
||||
if (metaInfo.propertyTypeName(propertyName) == "alias") {
|
||||
connectionComboBox->addItem(data.typeName
|
||||
+ "."
|
||||
+ QString::fromUtf8(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
addMetaInfoProperties(metaInfo, data.typeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -75,6 +75,7 @@ public:
|
||||
bool propertyIsListProperty(const PropertyName &propertyName) const;
|
||||
bool propertyIsEnumType(const PropertyName &propertyName) const;
|
||||
bool propertyIsPrivate(const PropertyName &propertyName) const;
|
||||
bool propertyIsPointer(const PropertyName &propertyName) const;
|
||||
QString propertyEnumScope(const PropertyName &propertyName) const;
|
||||
QStringList propertyKeysForEnum(const PropertyName &propertyName) const;
|
||||
QVariant propertyCastedValue(const PropertyName &propertyName, const QVariant &value) const;
|
||||
@@ -99,6 +100,7 @@ public:
|
||||
bool isSubclassOf(const TypeName &type, int majorVersion = -1, int minorVersion = -1) const;
|
||||
|
||||
bool isGraphicalItem() const;
|
||||
bool isQmlItem() const;
|
||||
bool isLayoutable() const;
|
||||
bool isView() const;
|
||||
bool isTabView() const;
|
||||
|
@@ -427,7 +427,7 @@ QVector<PropertyInfo> getQmlTypes(const CppComponentValue *objectValue, const Co
|
||||
PropertyMemberProcessor processor(context);
|
||||
objectValue->processMembers(&processor);
|
||||
|
||||
foreach (const PropertyInfo &property, processor.properties()) {
|
||||
for (const PropertyInfo &property : processor.properties()) {
|
||||
const PropertyName name = property.first;
|
||||
const QString nameAsString = QString::fromUtf8(name);
|
||||
if (!objectValue->isWritable(nameAsString) && objectValue->isPointer(nameAsString)) {
|
||||
@@ -1500,6 +1500,11 @@ bool NodeMetaInfo::propertyIsPrivate(const PropertyName &propertyName) const
|
||||
return propertyName.startsWith("__");
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::propertyIsPointer(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->isPropertyPointer(propertyName);
|
||||
}
|
||||
|
||||
QString NodeMetaInfo::propertyEnumScope(const PropertyName &propertyName) const
|
||||
{
|
||||
return m_privateData->propertyEnumScope(propertyName);
|
||||
@@ -1660,6 +1665,12 @@ bool NodeMetaInfo::isGraphicalItem() const
|
||||
|| isSubclassOf("QtQuick.Controls.Popup");
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::isQmlItem() const
|
||||
{
|
||||
return isSubclassOf("QtQuick.QtObject")
|
||||
|| isSubclassOf("QtQml.QtObject");
|
||||
}
|
||||
|
||||
void NodeMetaInfo::clearCache()
|
||||
{
|
||||
Internal::NodeMetaInfoPrivate::clearCache();
|
||||
|
Reference in New Issue
Block a user