forked from qt-creator/qt-creator
QmlDesigner: Add "NOT" option to binding editor
* Add "NOT" CheckBox in binding editor if boolean target * Fix wrong node assignment in binding editor context menu call * Fix connection editor state iteration source * Cleanup redundant code Task-number: QDS-2872 Change-Id: I8780bb1507f991b52aacfb011b889896d74ccb4f Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Henning Gründl
parent
6d5e302157
commit
d3ab7a89f9
@@ -279,10 +279,9 @@ void ActionEditor::prepareConnections()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// States
|
// States
|
||||||
for (const QmlModelState &state : QmlItemNode(m_modelNode).states().allStates())
|
for (const QmlModelState &state : QmlItemNode(m_modelNode.view()->rootModelNode()).states().allStates())
|
||||||
states.append(state.name());
|
states.append(state.name());
|
||||||
|
|
||||||
|
|
||||||
if (!connections.isEmpty() && !m_dialog.isNull())
|
if (!connections.isEmpty() && !m_dialog.isNull())
|
||||||
m_dialog->setAllConnections(connections, singletons, states);
|
m_dialog->setAllConnections(connections, singletons, states);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,9 +271,7 @@ void BindingEditor::prepareBindings()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bindings.isEmpty() && !m_dialog.isNull())
|
if (!bindings.isEmpty() && !m_dialog.isNull())
|
||||||
m_dialog->setAllBindings(bindings);
|
m_dialog->setAllBindings(bindings, m_backendValueTypeName);
|
||||||
|
|
||||||
updateWindowName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindingEditor::updateWindowName()
|
void BindingEditor::updateWindowName()
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -50,6 +51,8 @@ BindingEditorDialog::BindingEditorDialog(QWidget *parent)
|
|||||||
this, &BindingEditorDialog::itemIDChanged);
|
this, &BindingEditorDialog::itemIDChanged);
|
||||||
QObject::connect(m_comboBoxProperty, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
QObject::connect(m_comboBoxProperty, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
this, &BindingEditorDialog::propertyIDChanged);
|
this, &BindingEditorDialog::propertyIDChanged);
|
||||||
|
QObject::connect(m_checkBoxNot, QOverload<int>::of(&QCheckBox::stateChanged),
|
||||||
|
this, &BindingEditorDialog::checkBoxChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindingEditorDialog::~BindingEditorDialog()
|
BindingEditorDialog::~BindingEditorDialog()
|
||||||
@@ -58,7 +61,12 @@ BindingEditorDialog::~BindingEditorDialog()
|
|||||||
|
|
||||||
void BindingEditorDialog::adjustProperties()
|
void BindingEditorDialog::adjustProperties()
|
||||||
{
|
{
|
||||||
const QString expression = editorValue();
|
QString expression = editorValue().trimmed();
|
||||||
|
|
||||||
|
m_checkBoxNot->setChecked(expression.startsWith("!"));
|
||||||
|
if (m_checkBoxNot->isChecked())
|
||||||
|
expression.remove(0, 1);
|
||||||
|
|
||||||
QString item;
|
QString item;
|
||||||
QString property;
|
QString property;
|
||||||
QStringList expressionElements = expression.split(".");
|
QStringList expressionElements = expression.split(".");
|
||||||
@@ -94,12 +102,14 @@ void BindingEditorDialog::adjustProperties()
|
|||||||
m_comboBoxProperty->setCurrentText(property);
|
m_comboBoxProperty->setCurrentText(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindingEditorDialog::setAllBindings(QList<BindingOption> bindings)
|
void BindingEditorDialog::setAllBindings(const QList<BindingOption> &bindings, const TypeName &type)
|
||||||
{
|
{
|
||||||
m_lock = true;
|
m_lock = true;
|
||||||
|
|
||||||
m_bindings = bindings;
|
m_bindings = bindings;
|
||||||
|
m_type = type;
|
||||||
setupComboBoxes();
|
setupComboBoxes();
|
||||||
|
setupCheckBox();
|
||||||
adjustProperties();
|
adjustProperties();
|
||||||
|
|
||||||
m_lock = false;
|
m_lock = false;
|
||||||
@@ -109,11 +119,15 @@ void BindingEditorDialog::setupUIComponents()
|
|||||||
{
|
{
|
||||||
m_comboBoxItem = new QComboBox(this);
|
m_comboBoxItem = new QComboBox(this);
|
||||||
m_comboBoxProperty = new QComboBox(this);
|
m_comboBoxProperty = new QComboBox(this);
|
||||||
|
m_checkBoxNot = new QCheckBox(this);
|
||||||
|
m_checkBoxNot->setText(tr("NOT"));
|
||||||
|
m_checkBoxNot->setVisible(false);
|
||||||
|
m_checkBoxNot->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||||
|
m_checkBoxNot->setToolTip(tr("Invert the boolean expression."));
|
||||||
|
|
||||||
m_comboBoxLayout->addWidget(m_comboBoxItem);
|
m_comboBoxLayout->addWidget(m_comboBoxItem);
|
||||||
m_comboBoxLayout->addWidget(m_comboBoxProperty);
|
m_comboBoxLayout->addWidget(m_comboBoxProperty);
|
||||||
|
m_comboBoxLayout->addWidget(m_checkBoxNot);
|
||||||
//this->resize(660, 240);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindingEditorDialog::setupComboBoxes()
|
void BindingEditorDialog::setupComboBoxes()
|
||||||
@@ -125,6 +139,12 @@ void BindingEditorDialog::setupComboBoxes()
|
|||||||
m_comboBoxItem->addItem(bind.item);
|
m_comboBoxItem->addItem(bind.item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BindingEditorDialog::setupCheckBox()
|
||||||
|
{
|
||||||
|
const bool visible = (m_type == "bool");
|
||||||
|
m_checkBoxNot->setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
void BindingEditorDialog::itemIDChanged(int itemID)
|
void BindingEditorDialog::itemIDChanged(int itemID)
|
||||||
{
|
{
|
||||||
const QString previousProperty = m_comboBoxProperty->currentText();
|
const QString previousProperty = m_comboBoxProperty->currentText();
|
||||||
@@ -148,12 +168,31 @@ void BindingEditorDialog::propertyIDChanged(int propertyID)
|
|||||||
const int itemID = m_comboBoxItem->currentIndex();
|
const int itemID = m_comboBoxItem->currentIndex();
|
||||||
|
|
||||||
if (!m_lock)
|
if (!m_lock)
|
||||||
if (!m_comboBoxProperty->currentText().isEmpty() && (m_comboBoxProperty->currentText() != undefinedString))
|
if (!m_comboBoxProperty->currentText().isEmpty() && (m_comboBoxProperty->currentText() != undefinedString)) {
|
||||||
setEditorValue(m_comboBoxItem->itemText(itemID) + "." + m_comboBoxProperty->itemText(propertyID));
|
QString expression = m_comboBoxItem->itemText(itemID) + "." + m_comboBoxProperty->itemText(propertyID);
|
||||||
|
if (m_checkBoxNot->isChecked())
|
||||||
|
expression.prepend("!");
|
||||||
|
|
||||||
|
setEditorValue(expression);
|
||||||
|
}
|
||||||
|
|
||||||
const int undefinedProperty = m_comboBoxProperty->findText(undefinedString);
|
const int undefinedProperty = m_comboBoxProperty->findText(undefinedString);
|
||||||
if ((undefinedProperty != -1) && (m_comboBoxProperty->itemText(propertyID) != undefinedString))
|
if ((undefinedProperty != -1) && (m_comboBoxProperty->itemText(propertyID) != undefinedString))
|
||||||
m_comboBoxProperty->removeItem(undefinedProperty);
|
m_comboBoxProperty->removeItem(undefinedProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BindingEditorDialog::checkBoxChanged(int state)
|
||||||
|
{
|
||||||
|
if (m_lock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString expression = editorValue().trimmed();
|
||||||
|
if (state == Qt::Checked)
|
||||||
|
expression.prepend("!");
|
||||||
|
else
|
||||||
|
expression.remove(0, 1);
|
||||||
|
|
||||||
|
setEditorValue(expression);
|
||||||
|
}
|
||||||
|
|
||||||
} // QmlDesigner namespace
|
} // QmlDesigner namespace
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
|
class QCheckBox;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -56,21 +57,25 @@ public:
|
|||||||
|
|
||||||
void adjustProperties() override;
|
void adjustProperties() override;
|
||||||
|
|
||||||
void setAllBindings(QList<BindingOption> bindings);
|
void setAllBindings(const QList<BindingOption> &bindings, const TypeName &type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupUIComponents();
|
void setupUIComponents();
|
||||||
void setupComboBoxes();
|
void setupComboBoxes();
|
||||||
|
void setupCheckBox();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void itemIDChanged(int);
|
void itemIDChanged(int);
|
||||||
void propertyIDChanged(int);
|
void propertyIDChanged(int);
|
||||||
|
void checkBoxChanged(int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QComboBox *m_comboBoxItem = nullptr;
|
QComboBox *m_comboBoxItem = nullptr;
|
||||||
QComboBox *m_comboBoxProperty = nullptr;
|
QComboBox *m_comboBoxProperty = nullptr;
|
||||||
|
QCheckBox *m_checkBoxNot = nullptr;
|
||||||
|
|
||||||
QList<BindingOption> m_bindings;
|
QList<BindingOption> m_bindings;
|
||||||
|
TypeName m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,9 +142,9 @@ void ConnectionViewWidget::setConnectionModel(ConnectionModel *model)
|
|||||||
void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||||
{
|
{
|
||||||
auto tablePos = [&](QTableView *targetView) {
|
auto tablePos = [&](QTableView *targetView) {
|
||||||
//adjusting qpoint to the qtableview entrances:
|
// adjusting qpoint to the qtableview entrances:
|
||||||
QPoint posInTable(targetView->mapFromGlobal(mapToGlobal(event->pos())));
|
QPoint posInTable(targetView->mapFromGlobal(mapToGlobal(event->pos())));
|
||||||
posInTable = QPoint(posInTable.x(), posInTable.y() - targetView->horizontalHeader()->height());
|
posInTable.ry() -= targetView->horizontalHeader()->height();
|
||||||
return posInTable;
|
return posInTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,24 +152,24 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
|||||||
case ConnectionTab:
|
case ConnectionTab:
|
||||||
if (ui->connectionView != nullptr) {
|
if (ui->connectionView != nullptr) {
|
||||||
QTableView *targetView = ui->connectionView;
|
QTableView *targetView = ui->connectionView;
|
||||||
//making sure that we have source column in our hands:
|
// making sure that we have source column in our hands:
|
||||||
QModelIndex index = targetView->indexAt(tablePos(targetView)).siblingAtColumn(ConnectionModel::SourceRow);
|
const QModelIndex index = targetView->indexAt(tablePos(targetView)).siblingAtColumn(ConnectionModel::SourceRow);
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
|
|
||||||
menu.addAction(tr("Open Connection Editor"), [&]() {
|
menu.addAction(tr("Open Connection Editor"), [&]() {
|
||||||
if (index.isValid()) {
|
auto *connectionModel = qobject_cast<ConnectionModel *>(targetView->model());
|
||||||
auto *connectionModel = qobject_cast<ConnectionModel *>(targetView->model());
|
const SignalHandlerProperty property = connectionModel->signalHandlerPropertyForRow(index.row());
|
||||||
ModelNode node = connectionModel->connectionView()->rootModelNode();
|
const ModelNode node = property.parentModelNode();
|
||||||
m_connectionEditor->showWidget();
|
|
||||||
m_connectionEditor->setConnectionValue(index.data().toString());
|
m_connectionEditor->showWidget();
|
||||||
m_connectionEditor->setModelIndex(index);
|
m_connectionEditor->setConnectionValue(index.data().toString());
|
||||||
m_connectionEditor->setModelNode(node);
|
m_connectionEditor->setModelIndex(index);
|
||||||
m_connectionEditor->prepareConnections();
|
m_connectionEditor->setModelNode(node);
|
||||||
m_connectionEditor->updateWindowName();
|
m_connectionEditor->prepareConnections();
|
||||||
}
|
m_connectionEditor->updateWindowName();
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.exec(event->globalPos());
|
menu.exec(event->globalPos());
|
||||||
@@ -179,37 +179,31 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
|||||||
case BindingTab:
|
case BindingTab:
|
||||||
if (ui->bindingView != nullptr) {
|
if (ui->bindingView != nullptr) {
|
||||||
QTableView *targetView = bindingTableView();
|
QTableView *targetView = bindingTableView();
|
||||||
QModelIndex index = targetView->indexAt(tablePos(targetView)).siblingAtColumn(BindingModel::SourcePropertyNameRow);
|
const QModelIndex index = targetView->indexAt(tablePos(targetView)).siblingAtColumn(BindingModel::SourcePropertyNameRow);
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
|
|
||||||
menu.addAction(tr("Open Binding Editor"), [&]() {
|
menu.addAction(tr("Open Binding Editor"), [&]() {
|
||||||
if (index.isValid()) {
|
BindingModel *bindingModel = qobject_cast<BindingModel*>(targetView->model());
|
||||||
BindingModel *binModel = qobject_cast<BindingModel*>(targetView->model());
|
const BindingProperty property = bindingModel->bindingPropertyForRow(index.row());
|
||||||
ModelNode node = binModel->connectionView()->rootModelNode();
|
|
||||||
|
|
||||||
BindingProperty property = binModel->bindingPropertyForRow(index.row());
|
if (!property.isValid() || !property.isBindingProperty())
|
||||||
|
return;
|
||||||
|
|
||||||
if (property.isValid()) {
|
const ModelNode node = property.parentModelNode();
|
||||||
if (property.isBindingProperty()) {
|
const TypeName typeName = property.isDynamic() ? property.dynamicTypeName()
|
||||||
m_bindingEditor->showWidget();
|
: node.metaInfo().propertyTypeName(property.name());
|
||||||
m_bindingEditor->setBindingValue(property.expression());
|
|
||||||
m_bindingEditor->setModelNode(node);
|
|
||||||
if (property.isDynamic()) {
|
|
||||||
m_bindingEditor->setBackendValueTypeName(property.dynamicTypeName());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_bindingEditor->setBackendValueTypeName(node.metaInfo().propertyTypeName(property.name()));
|
|
||||||
}
|
|
||||||
m_bindingEditor->prepareBindings();
|
|
||||||
m_bindingEditor->updateWindowName();
|
|
||||||
|
|
||||||
m_bindingIndex = index;
|
m_bindingEditor->showWidget();
|
||||||
}
|
m_bindingEditor->setBindingValue(property.expression());
|
||||||
}
|
m_bindingEditor->setModelNode(node);
|
||||||
}
|
m_bindingEditor->setBackendValueTypeName(typeName);
|
||||||
|
m_bindingEditor->prepareBindings();
|
||||||
|
m_bindingEditor->updateWindowName();
|
||||||
|
|
||||||
|
m_bindingIndex = index;
|
||||||
});
|
});
|
||||||
menu.exec(event->globalPos());
|
menu.exec(event->globalPos());
|
||||||
}
|
}
|
||||||
@@ -218,51 +212,40 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
|||||||
case DynamicPropertiesTab:
|
case DynamicPropertiesTab:
|
||||||
if (ui->dynamicPropertiesView != nullptr) {
|
if (ui->dynamicPropertiesView != nullptr) {
|
||||||
QTableView *targetView = dynamicPropertiesTableView();
|
QTableView *targetView = dynamicPropertiesTableView();
|
||||||
QModelIndex index = targetView->indexAt(tablePos(targetView)).siblingAtColumn(DynamicPropertiesModel::PropertyValueRow);
|
const QModelIndex index = targetView->indexAt(tablePos(targetView)).siblingAtColumn(DynamicPropertiesModel::PropertyValueRow);
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
DynamicPropertiesModel *propertiesModel = qobject_cast<DynamicPropertiesModel *>(targetView->model());
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
|
|
||||||
menu.addAction(tr("Open Binding Editor"), [&]() {
|
menu.addAction(tr("Open Binding Editor"), [&]() {
|
||||||
if (index.isValid()) {
|
AbstractProperty abstractProperty = propertiesModel->abstractPropertyForRow(index.row());
|
||||||
DynamicPropertiesModel *dynPropModel = qobject_cast<DynamicPropertiesModel*>(targetView->model());
|
if (!abstractProperty.isValid())
|
||||||
ModelNode node = dynPropModel->connectionView()->rootModelNode();
|
return;
|
||||||
|
|
||||||
AbstractProperty abProp = dynPropModel->abstractPropertyForRow(index.row());
|
const ModelNode node = abstractProperty.parentModelNode();
|
||||||
|
QString newExpression;
|
||||||
|
|
||||||
QString newExpression;
|
if (abstractProperty.isBindingProperty())
|
||||||
|
newExpression = abstractProperty.toBindingProperty().expression();
|
||||||
|
else if (abstractProperty.isVariantProperty())
|
||||||
|
newExpression = abstractProperty.toVariantProperty().value().toString();
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
if (abProp.isValid()) {
|
m_dynamicEditor->showWidget();
|
||||||
if (abProp.isBindingProperty()) {
|
m_dynamicEditor->setBindingValue(newExpression);
|
||||||
BindingProperty property = abProp.toBindingProperty();
|
m_dynamicEditor->setModelNode(node);
|
||||||
newExpression = property.expression();
|
m_dynamicEditor->setBackendValueTypeName(abstractProperty.dynamicTypeName());
|
||||||
}
|
m_dynamicEditor->prepareBindings();
|
||||||
else if (abProp.isVariantProperty()) {
|
m_dynamicEditor->updateWindowName();
|
||||||
VariantProperty property = abProp.toVariantProperty();
|
|
||||||
newExpression = property.value().toString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_dynamicEditor->showWidget();
|
m_dynamicIndex = index;
|
||||||
m_dynamicEditor->setBindingValue(newExpression);
|
|
||||||
m_dynamicEditor->setModelNode(node);
|
|
||||||
m_dynamicEditor->setBackendValueTypeName(abProp.dynamicTypeName());
|
|
||||||
m_dynamicEditor->prepareBindings();
|
|
||||||
m_dynamicEditor->updateWindowName();
|
|
||||||
|
|
||||||
m_dynamicIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.addAction(tr("Reset Property"), [&]() {
|
menu.addAction(tr("Reset Property"), [&]() {
|
||||||
if (index.isValid()) {
|
propertiesModel->resetProperty(propertiesModel->abstractPropertyForRow(index.row()).name());
|
||||||
DynamicPropertiesModel *propertiesModel = qobject_cast<DynamicPropertiesModel *>(dynamicPropertiesTableView()->model());
|
|
||||||
|
|
||||||
propertiesModel->resetProperty(propertiesModel->abstractPropertyForRow(index.row()).name());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.exec(event->globalPos());
|
menu.exec(event->globalPos());
|
||||||
|
|||||||
Reference in New Issue
Block a user