forked from qt-creator/qt-creator
QmlDesigner: Fix for Binding Editor
- Makes Binding Editor modal - Fixes Binding Editors hotkeys and actions - Adds Target item, property and expected type into title Task-numbers: QDS-2819, QDS-4878 Change-Id: Ib5c5f73e6552f58828776043f9b793a24c48a1f8 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -164,6 +164,7 @@ Item {
|
||||
bindingEditor.showWidget()
|
||||
bindingEditor.text = backendValue.expression
|
||||
bindingEditor.prepareBindings()
|
||||
bindingEditor.updateWindowName()
|
||||
}
|
||||
|
||||
BindingEditor {
|
||||
|
@@ -110,6 +110,7 @@ Rectangle {
|
||||
bindingEditor.showWidget()
|
||||
bindingEditor.text = delegateWhenConditionString
|
||||
bindingEditor.prepareBindings()
|
||||
bindingEditor.updateWindowName()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,6 +310,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
stateModelNodeProperty: statesEditorModel.stateModelNode()
|
||||
stateNameProperty: myRoot.delegateStateName
|
||||
|
||||
onRejected: {
|
||||
hideWidget()
|
||||
|
@@ -46,7 +46,7 @@ AbstractEditorDialog::AbstractEditorDialog(QWidget *parent, const QString &title
|
||||
{
|
||||
setWindowFlag(Qt::Tool, true);
|
||||
setWindowTitle(defaultTitle());
|
||||
setModal(false);
|
||||
setModal(true);
|
||||
|
||||
setupJSEditor();
|
||||
setupUIComponents();
|
||||
@@ -111,11 +111,10 @@ void AbstractEditorDialog::setupJSEditor()
|
||||
{
|
||||
static BindingEditorFactory f;
|
||||
m_editor = qobject_cast<TextEditor::BaseTextEditor*>(f.createEditor());
|
||||
m_editorWidget = qobject_cast<BindingEditorWidget*>(m_editor->editorWidget());
|
||||
Q_ASSERT(m_editor);
|
||||
|
||||
Core::Context context = m_editor->context();
|
||||
context.prepend(BINDINGEDITOR_CONTEXT_ID);
|
||||
m_editorWidget->m_context->setContext(context);
|
||||
m_editorWidget = qobject_cast<BindingEditorWidget*>(m_editor->editorWidget());
|
||||
Q_ASSERT(m_editorWidget);
|
||||
|
||||
auto qmlDesignerEditor = QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor();
|
||||
|
||||
|
@@ -26,9 +26,10 @@
|
||||
#ifndef ABSTRACTEDITORDIALOG_H
|
||||
#define ABSTRACTEDITORDIALOG_H
|
||||
|
||||
#include <bindingeditor/bindingeditorwidget.h>
|
||||
#include <qmldesignercorelib_global.h>
|
||||
|
||||
#include <texteditor/texteditor.h>
|
||||
#include <bindingeditor/bindingeditorwidget.h>
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
|
@@ -286,10 +286,13 @@ void ActionEditor::prepareConnections()
|
||||
m_dialog->setAllConnections(connections, singletons, states);
|
||||
}
|
||||
|
||||
void ActionEditor::updateWindowName()
|
||||
void ActionEditor::updateWindowName(const QString &targetName)
|
||||
{
|
||||
if (!m_dialog.isNull()) {
|
||||
m_dialog->setWindowTitle(m_dialog->defaultTitle());
|
||||
if (targetName.isEmpty())
|
||||
m_dialog->setWindowTitle(m_dialog->defaultTitle());
|
||||
else
|
||||
m_dialog->setWindowTitle(m_dialog->defaultTitle() + " [" + targetName + "]");
|
||||
m_dialog->raise();
|
||||
}
|
||||
}
|
||||
|
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
void prepareConnections();
|
||||
|
||||
Q_INVOKABLE void updateWindowName();
|
||||
Q_INVOKABLE void updateWindowName(const QString &targetName = {});
|
||||
|
||||
signals:
|
||||
void accepted();
|
||||
|
@@ -42,8 +42,6 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static BindingEditor *s_lastBindingEditor = nullptr;
|
||||
|
||||
BindingEditor::BindingEditor(QObject *)
|
||||
{
|
||||
}
|
||||
@@ -62,11 +60,6 @@ void BindingEditor::prepareDialog()
|
||||
{
|
||||
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_BINDINGEDITOR_OPENED);
|
||||
|
||||
if (s_lastBindingEditor)
|
||||
s_lastBindingEditor->hideWidget();
|
||||
|
||||
s_lastBindingEditor = this;
|
||||
|
||||
m_dialog = new BindingEditorDialog(Core::ICore::dialogParent());
|
||||
|
||||
QObject::connect(m_dialog, &AbstractEditorDialog::accepted,
|
||||
@@ -91,9 +84,6 @@ void BindingEditor::showWidget(int x, int y)
|
||||
|
||||
void BindingEditor::hideWidget()
|
||||
{
|
||||
if (s_lastBindingEditor == this)
|
||||
s_lastBindingEditor = nullptr;
|
||||
|
||||
if (m_dialog) {
|
||||
m_dialog->unregisterAutoCompletion(); //we have to do it separately, otherwise we have an autocompletion action override
|
||||
m_dialog->close();
|
||||
@@ -125,6 +115,12 @@ void BindingEditor::setBackendValue(const QVariant &backendValue)
|
||||
if (node.isValid()) {
|
||||
m_backendValueTypeName = node.metaInfo().propertyTypeName(propertyEditorValue->name());
|
||||
|
||||
QString nodeId = node.id();
|
||||
if (nodeId.isEmpty())
|
||||
nodeId = node.simplifiedTypeName();
|
||||
|
||||
m_targetName = nodeId + "." + propertyEditorValue->name();
|
||||
|
||||
if (m_backendValueTypeName == "alias" || m_backendValueTypeName == "unknown")
|
||||
if (QmlObjectNode::isValidQmlObjectNode(node))
|
||||
m_backendValueTypeName = QmlObjectNode(node).instanceType(propertyEditorValue->name());
|
||||
@@ -164,6 +160,12 @@ void BindingEditor::setStateModelNode(const QVariant &stateModelNode)
|
||||
}
|
||||
}
|
||||
|
||||
void BindingEditor::setStateName(const QString &name)
|
||||
{
|
||||
m_targetName = name;
|
||||
m_targetName += ".when";
|
||||
}
|
||||
|
||||
void BindingEditor::setModelNode(const ModelNode &modelNode)
|
||||
{
|
||||
if (modelNode.isValid())
|
||||
@@ -177,6 +179,11 @@ void BindingEditor::setBackendValueTypeName(const TypeName &backendValueTypeName
|
||||
emit backendValueChanged();
|
||||
}
|
||||
|
||||
void BindingEditor::setTargetName(const QString &target)
|
||||
{
|
||||
m_targetName = target;
|
||||
}
|
||||
|
||||
void BindingEditor::prepareBindings()
|
||||
{
|
||||
if (!m_modelNode.isValid() || m_backendValueTypeName.isEmpty())
|
||||
@@ -279,8 +286,13 @@ void BindingEditor::prepareBindings()
|
||||
|
||||
void BindingEditor::updateWindowName()
|
||||
{
|
||||
if (!m_dialog.isNull() && !m_backendValueTypeName.isEmpty())
|
||||
m_dialog->setWindowTitle(m_dialog->defaultTitle() + " [" + m_backendValueTypeName + "]");
|
||||
if (!m_dialog.isNull() && !m_backendValueTypeName.isEmpty()) {
|
||||
const QString targetString = " ["
|
||||
+ (m_targetName.isEmpty() ? QString() : (m_targetName + ": "))
|
||||
+ QString::fromUtf8(m_backendValueTypeName) + "]";
|
||||
|
||||
m_dialog->setWindowTitle(m_dialog->defaultTitle() + targetString);
|
||||
}
|
||||
}
|
||||
|
||||
QVariant BindingEditor::backendValue() const
|
||||
|
@@ -44,6 +44,7 @@ class BindingEditor : public QObject
|
||||
Q_PROPERTY(QVariant backendValueProperty READ backendValue WRITE setBackendValue NOTIFY backendValueChanged)
|
||||
Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
|
||||
Q_PROPERTY(QVariant stateModelNodeProperty READ stateModelNode WRITE setStateModelNode NOTIFY stateModelNodeChanged)
|
||||
Q_PROPERTY(QString stateNameProperty WRITE setStateName)
|
||||
|
||||
public:
|
||||
BindingEditor(QObject *parent = nullptr);
|
||||
@@ -64,11 +65,14 @@ public:
|
||||
void setModelNodeBackend(const QVariant &modelNodeBackend);
|
||||
|
||||
//2. modelnode (this one also sets backend value type name to bool)
|
||||
//State Name is not mandatory, but used in bindingEditor dialog name
|
||||
void setStateModelNode(const QVariant &stateModelNode);
|
||||
void setStateName(const QString &name);
|
||||
|
||||
//3. modelnode + backend value type name
|
||||
//3. modelnode + backend value type name + optional target name
|
||||
void setModelNode(const ModelNode &modelNode);
|
||||
void setBackendValueTypeName(const TypeName &backendValueTypeName);
|
||||
void setTargetName(const QString &target);
|
||||
|
||||
Q_INVOKABLE void prepareBindings();
|
||||
Q_INVOKABLE void updateWindowName();
|
||||
@@ -93,6 +97,7 @@ private:
|
||||
QVariant m_stateModelNode;
|
||||
QmlDesigner::ModelNode m_modelNode;
|
||||
TypeName m_backendValueTypeName;
|
||||
QString m_targetName;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -35,6 +35,10 @@
|
||||
#include <qmljseditor/qmljseditordocument.h>
|
||||
#include <qmljseditor/qmljssemantichighlighter.h>
|
||||
#include <qmljstools/qmljsindenter.h>
|
||||
#include <qmljstools/qmljstoolsconstants.h>
|
||||
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <utils/fancylineedit.h>
|
||||
|
||||
#include <QAction>
|
||||
|
||||
@@ -43,17 +47,19 @@ namespace QmlDesigner {
|
||||
BindingEditorWidget::BindingEditorWidget()
|
||||
: m_context(new Core::IContext(this))
|
||||
{
|
||||
m_context->setWidget(this);
|
||||
Core::ICore::addContextObject(m_context);
|
||||
Core::Context context(BINDINGEDITOR_CONTEXT_ID,
|
||||
ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
|
||||
|
||||
const Core::Context context(BINDINGEDITOR_CONTEXT_ID);
|
||||
m_context->setWidget(this);
|
||||
m_context->setContext(context);
|
||||
Core::ICore::addContextObject(m_context);
|
||||
|
||||
/*
|
||||
* We have to register our own active auto completion shortcut, because the original short cut will
|
||||
* use the cursor position of the original editor in the editor manager.
|
||||
*/
|
||||
|
||||
m_completionAction = new QAction(tr("Trigger Completion"), this);
|
||||
|
||||
Core::Command *command = Core::ActionManager::registerAction(
|
||||
m_completionAction, TextEditor::Constants::COMPLETE_THIS, context);
|
||||
command->setDefaultKeySequence(QKeySequence(
|
||||
@@ -84,11 +90,9 @@ bool BindingEditorWidget::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
|
||||
if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && !keyEvent->modifiers()) {
|
||||
emit returnKeyClicked();
|
||||
return true;
|
||||
} else {
|
||||
return QmlJSEditor::QmlJSEditorWidget::event(event);
|
||||
}
|
||||
}
|
||||
return QmlJSEditor::QmlJSEditorWidget::event(event);
|
||||
@@ -133,8 +137,12 @@ void BindingDocument::triggerPendingUpdates()
|
||||
BindingEditorFactory::BindingEditorFactory()
|
||||
{
|
||||
setId(BINDINGEDITOR_CONTEXT_ID);
|
||||
setDisplayName(QCoreApplication::translate("OpenWith::Editors", QmlDesigner::BINDINGEDITOR_CONTEXT_ID));
|
||||
setDisplayName(QCoreApplication::translate("OpenWith::Editors", BINDINGEDITOR_CONTEXT_ID));
|
||||
setEditorActionHandlers(0);
|
||||
addMimeType(BINDINGEDITOR_CONTEXT_ID);
|
||||
addMimeType(QmlJSTools::Constants::QML_MIMETYPE);
|
||||
addMimeType(QmlJSTools::Constants::QMLTYPES_MIMETYPE);
|
||||
addMimeType(QmlJSTools::Constants::JS_MIMETYPE);
|
||||
|
||||
setDocumentCreator([]() { return new BindingDocument; });
|
||||
setEditorWidgetCreator([]() { return new BindingEditorWidget; });
|
||||
|
@@ -159,17 +159,20 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
|
||||
QMenu menu(this);
|
||||
|
||||
menu.addAction(tr("Open Connection Editor"), [&]() {
|
||||
menu.addAction(tr("Open Connection Editor"), this, [&]() {
|
||||
auto *connectionModel = qobject_cast<ConnectionModel *>(targetView->model());
|
||||
const SignalHandlerProperty property = connectionModel->signalHandlerPropertyForRow(index.row());
|
||||
const ModelNode node = property.parentModelNode();
|
||||
|
||||
const QString targetName = index.siblingAtColumn(ConnectionModel::TargetModelNodeRow).data().toString()
|
||||
+ "." + property.name();
|
||||
|
||||
m_connectionEditor->showWidget();
|
||||
m_connectionEditor->setConnectionValue(index.data().toString());
|
||||
m_connectionEditor->setModelIndex(index);
|
||||
m_connectionEditor->setModelNode(node);
|
||||
m_connectionEditor->prepareConnections();
|
||||
m_connectionEditor->updateWindowName();
|
||||
m_connectionEditor->updateWindowName(targetName);
|
||||
});
|
||||
|
||||
QMap<QString, QVariant> data;
|
||||
@@ -179,7 +182,7 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
const auto actions = designerActionManager.actionsForTargetView(
|
||||
ActionInterface::TargetView::ConnectionEditor);
|
||||
|
||||
for (auto actionInterface : actions) {
|
||||
for (const auto &actionInterface : actions) {
|
||||
auto *action = actionInterface->action();
|
||||
action->setData(data);
|
||||
menu.addAction(action);
|
||||
@@ -198,7 +201,7 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
|
||||
QMenu menu(this);
|
||||
|
||||
menu.addAction(tr("Open Binding Editor"), [&]() {
|
||||
menu.addAction(tr("Open Binding Editor"), this, [&]() {
|
||||
BindingModel *bindingModel = qobject_cast<BindingModel*>(targetView->model());
|
||||
const BindingProperty property = bindingModel->bindingPropertyForRow(index.row());
|
||||
|
||||
@@ -209,10 +212,13 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
const TypeName typeName = property.isDynamic() ? property.dynamicTypeName()
|
||||
: node.metaInfo().propertyTypeName(property.name());
|
||||
|
||||
const QString targetName = node.displayName() + "." + property.name();
|
||||
|
||||
m_bindingEditor->showWidget();
|
||||
m_bindingEditor->setBindingValue(property.expression());
|
||||
m_bindingEditor->setModelNode(node);
|
||||
m_bindingEditor->setBackendValueTypeName(typeName);
|
||||
m_bindingEditor->setTargetName(targetName);
|
||||
m_bindingEditor->prepareBindings();
|
||||
m_bindingEditor->updateWindowName();
|
||||
|
||||
@@ -232,7 +238,7 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
DynamicPropertiesModel *propertiesModel = qobject_cast<DynamicPropertiesModel *>(targetView->model());
|
||||
QMenu menu(this);
|
||||
|
||||
menu.addAction(tr("Open Binding Editor"), [&]() {
|
||||
menu.addAction(tr("Open Binding Editor"), this, [&]() {
|
||||
AbstractProperty abstractProperty = propertiesModel->abstractPropertyForRow(index.row());
|
||||
if (!abstractProperty.isValid())
|
||||
return;
|
||||
@@ -247,17 +253,20 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
else
|
||||
return;
|
||||
|
||||
const QString targetName = node.displayName() + "." + abstractProperty.name();
|
||||
|
||||
m_dynamicEditor->showWidget();
|
||||
m_dynamicEditor->setBindingValue(newExpression);
|
||||
m_dynamicEditor->setModelNode(node);
|
||||
m_dynamicEditor->setBackendValueTypeName(abstractProperty.dynamicTypeName());
|
||||
m_dynamicEditor->setTargetName(targetName);
|
||||
m_dynamicEditor->prepareBindings();
|
||||
m_dynamicEditor->updateWindowName();
|
||||
|
||||
m_dynamicIndex = index;
|
||||
});
|
||||
|
||||
menu.addAction(tr("Reset Property"), [&]() {
|
||||
menu.addAction(tr("Reset Property"), this, [&]() {
|
||||
propertiesModel->resetProperty(propertiesModel->abstractPropertyForRow(index.row()).name());
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user