QmlDesigner: Support aliases in Connection View

- Allows user to select aliases in connections view
 - Seeks signals for aliases

Task: QDS-2411

Change-Id: I69eb875eb99cbf8cd6a842d5f7e166d9990bb255
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Aleksei German
2020-06-17 18:51:56 +02:00
parent 6e6c771fa5
commit e9e1e797c7
8 changed files with 73 additions and 16 deletions

View File

@@ -54,7 +54,7 @@ void ActionEditor::registerDeclarativeType()
qmlRegisterType<ActionEditor>("HelperWidgets", 2, 0, "ActionEditor");
}
void ActionEditor::showWidget(int x, int y)
void ActionEditor::prepareDialog()
{
if (s_lastActionEditor)
s_lastActionEditor->hideWidget();
@@ -70,8 +70,18 @@ void ActionEditor::showWidget(int x, int y)
this, &ActionEditor::rejected);
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
}
void ActionEditor::showWidget()
{
prepareDialog();
m_dialog->showWidget();
}
void ActionEditor::showWidget(int x, int y)
{
prepareDialog();
m_dialog->showWidget(x, y);
m_dialog->activateWindow();
}
void ActionEditor::hideWidget()

View File

@@ -48,6 +48,7 @@ public:
static void registerDeclarativeType();
Q_INVOKABLE void showWidget();
Q_INVOKABLE void showWidget(int x, int y);
Q_INVOKABLE void hideWidget();
@@ -69,6 +70,7 @@ private:
QVariant backendValue() const;
QVariant modelNodeBackend() const;
QVariant stateModelNode() const;
void prepareDialog();
private:
QPointer<BindingEditorDialog> m_dialog;

View File

@@ -45,7 +45,7 @@ namespace {
QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &propertyNameList)
{
QStringList stringList;
foreach (QmlDesigner::PropertyName propertyName, propertyNameList) {
for (const QmlDesigner::PropertyName propertyName : propertyNameList) {
stringList << QString::fromUtf8(propertyName);
}
stringList.removeDuplicates();
@@ -58,7 +58,6 @@ bool isConnection(const QmlDesigner::ModelNode &modelNode)
|| modelNode.type() == "QtQuick.Connections"
|| modelNode.type() == "Qt.Connections"
|| modelNode.type() == "QtQml.Connections");
}
} //namespace
@@ -81,7 +80,7 @@ void ConnectionModel::resetModel()
setHorizontalHeaderLabels(QStringList({ tr("Target"), tr("Signal Handler"), tr("Action") }));
if (connectionView()->isAttached()) {
foreach (const ModelNode modelNode, connectionView()->allModelNodes())
for (const ModelNode modelNode : connectionView()->allModelNodes())
addModelNode(modelNode);
}
@@ -96,8 +95,7 @@ SignalHandlerProperty ConnectionModel::signalHandlerPropertyForRow(int rowNumber
const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
if (modelNode.isValid())
return modelNode.signalHandlerProperty(targetPropertyName.toUtf8());
@@ -112,7 +110,7 @@ void ConnectionModel::addModelNode(const ModelNode &modelNode)
void ConnectionModel::addConnection(const ModelNode &modelNode)
{
foreach (const AbstractProperty &property, modelNode.properties()) {
for (const AbstractProperty &property : modelNode.properties()) {
if (property.isSignalHandlerProperty() && property.name() != "target") {
addSignalHandler(property.toSignalHandlerProperty());
}
@@ -179,7 +177,6 @@ void ConnectionModel::updateSource(int row)
m_exceptionError = e.description();
QTimer::singleShot(200, this, &ConnectionModel::handleException);
}
}
void ConnectionModel::updateSignalName(int rowNumber)
@@ -211,8 +208,14 @@ void ConnectionModel::updateTargetNode(int rowNumber)
const QString newTarget = data(index(rowNumber, TargetModelNodeRow)).toString();
ModelNode connectionNode = signalHandlerProperty.parentModelNode();
const bool isAlias = newTarget.contains(".");
if (!newTarget.isEmpty()) {
const ModelNode parent = connectionView()->modelNodeForId(newTarget);
//if it's an alias, then let's reparent connections to alias property owner:
const ModelNode parent = connectionView()->modelNodeForId(isAlias
? newTarget.split(".").constFirst()
: newTarget);
if (parent.isValid() && QmlItemNode::isValidQmlItemNode(parent))
parent.nodeListProperty("data").reparentHere(connectionNode);
@@ -236,8 +239,28 @@ ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connectio
BindingProperty bindingProperty = connection.bindingProperty("target");
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 (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;
}
}
}
}
}
return connectionView()->modelNodeForId(bindingProperty.expression());
}
@@ -376,9 +399,8 @@ QStringList ConnectionModel::getSignalsForRow(int row) const
QStringList stringList;
SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(row);
if (signalHandlerProperty.isValid()) {
if (signalHandlerProperty.isValid())
stringList.append(getPossibleSignalsForConnection(signalHandlerProperty.parentModelNode()));
}
return stringList;
}

View File

@@ -161,7 +161,7 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
menu.addAction(tr("Open Connection Editor"), [&]() {
if (index.isValid()) {
m_connectonEditor->showWidget(mapToGlobal(event->pos()).x(), mapToGlobal(event->pos()).y());
m_connectonEditor->showWidget();
m_connectonEditor->setBindingValue(index.data().toString());
m_connectonEditor->setModelIndex(index);
m_connectonEditor->updateWindowName();

View File

@@ -46,7 +46,7 @@ namespace Internal {
QStringList prependOnForSignalHandler(const QStringList &signalNames)
{
QStringList signalHandlerNames;
foreach (const QString &signalName, signalNames) {
for (const QString &signalName : signalNames) {
QString signalHandlerName = signalName;
if (!signalHandlerName.isEmpty()) {
QChar firstChar = signalHandlerName.at(0).toUpper();
@@ -284,9 +284,19 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie
switch (index.column()) {
case ConnectionModel::TargetModelNodeRow: {
foreach (const ModelNode &modelNode, connectionModel->connectionView()->allModelNodes()) {
for (const ModelNode &modelNode : connectionModel->connectionView()->allModelNodes()) {
if (!modelNode.id().isEmpty()) {
connectionComboBox->addItem(modelNode.id());
for (const BindingProperty &property : modelNode.bindingProperties()) {
if (property.isValid()) {
if (property.isAlias()) {
connectionComboBox->addItem(modelNode.id()
+ "."
+ QString::fromUtf8(property.name()));
}
}
}
}
}
} break;

View File

@@ -399,7 +399,6 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper
if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
possibleProperties << QString::fromUtf8(propertyName);
}
return possibleProperties;
} else {
qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node";

View File

@@ -56,8 +56,10 @@ public:
static void deleteAllReferencesTo(const ModelNode &modelNode);
bool isAlias() const;
bool isAliasExport() const;
protected:
BindingProperty(const PropertyName &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
};

View File

@@ -277,6 +277,18 @@ void BindingProperty::deleteAllReferencesTo(const ModelNode &modelNode)
}
}
bool BindingProperty::isAlias() const
{
if (!isValid())
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
return isDynamic()
&& dynamicTypeName() == "alias"
&& !expression().isNull()
&& !expression().isEmpty()
&& parentModelNode().view()->modelNodeForId(expression()).isValid();
}
bool BindingProperty::isAliasExport() const
{
if (!isValid())