forked from qt-creator/qt-creator
QmlDesigner Action Editor for Connections View
Task: QDS-1261 Change-Id: I81e6687e31a0f987ba15dc81dd52f240e4ea9689 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -526,6 +526,7 @@ extend_qtc_plugin(QmlDesigner
|
||||
extend_qtc_plugin(QmlDesigner
|
||||
SOURCES_PREFIX components/bindingeditor
|
||||
SOURCES bindingeditor.cpp bindingeditor.h
|
||||
actioneditor.cpp actioneditor.h
|
||||
bindingeditordialog.cpp bindingeditordialog.h
|
||||
bindingeditorwidget.cpp bindingeditorwidget.h
|
||||
)
|
||||
|
@@ -0,0 +1,131 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "actioneditor.h"
|
||||
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
|
||||
#include <metainfo.h>
|
||||
#include <qmlmodelnodeproxy.h>
|
||||
#include <nodeabstractproperty.h>
|
||||
#include <nodelistproperty.h>
|
||||
#include <propertyeditorvalue.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static ActionEditor *s_lastActionEditor = nullptr;
|
||||
|
||||
ActionEditor::ActionEditor(QObject *)
|
||||
: m_index(QModelIndex())
|
||||
{
|
||||
}
|
||||
|
||||
ActionEditor::~ActionEditor()
|
||||
{
|
||||
hideWidget();
|
||||
}
|
||||
|
||||
void ActionEditor::registerDeclarativeType()
|
||||
{
|
||||
qmlRegisterType<ActionEditor>("HelperWidgets", 2, 0, "ActionEditor");
|
||||
}
|
||||
|
||||
void ActionEditor::showWidget(int x, int y)
|
||||
{
|
||||
if (s_lastActionEditor)
|
||||
s_lastActionEditor->hideWidget();
|
||||
s_lastActionEditor = this;
|
||||
|
||||
m_dialog = new BindingEditorDialog(Core::ICore::dialogParent(),
|
||||
BindingEditorDialog::DialogType::ActionDialog);
|
||||
|
||||
|
||||
QObject::connect(m_dialog, &BindingEditorDialog::accepted,
|
||||
this, &ActionEditor::accepted);
|
||||
QObject::connect(m_dialog, &BindingEditorDialog::rejected,
|
||||
this, &ActionEditor::rejected);
|
||||
|
||||
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_dialog->showWidget(x, y);
|
||||
m_dialog->activateWindow();
|
||||
}
|
||||
|
||||
void ActionEditor::hideWidget()
|
||||
{
|
||||
if (s_lastActionEditor == this)
|
||||
s_lastActionEditor = nullptr;
|
||||
if (m_dialog)
|
||||
{
|
||||
m_dialog->unregisterAutoCompletion(); //we have to do it separately, otherwise we have an autocompletion action override
|
||||
m_dialog->close();
|
||||
}
|
||||
}
|
||||
|
||||
QString ActionEditor::bindingValue() const
|
||||
{
|
||||
if (!m_dialog)
|
||||
return {};
|
||||
|
||||
return m_dialog->editorValue();
|
||||
}
|
||||
|
||||
void ActionEditor::setBindingValue(const QString &text)
|
||||
{
|
||||
if (m_dialog)
|
||||
m_dialog->setEditorValue(text);
|
||||
}
|
||||
|
||||
bool ActionEditor::hasModelIndex() const
|
||||
{
|
||||
return m_index.isValid();
|
||||
}
|
||||
|
||||
void ActionEditor::resetModelIndex()
|
||||
{
|
||||
m_index = QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex ActionEditor::modelIndex() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
void ActionEditor::setModelIndex(const QModelIndex &index)
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
void ActionEditor::updateWindowName()
|
||||
{
|
||||
if (!m_dialog.isNull())
|
||||
{
|
||||
m_dialog->setWindowTitle(tr("Action Editor"));
|
||||
m_dialog->raise();
|
||||
}
|
||||
}
|
||||
|
||||
} // QmlDesigner namespace
|
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ACTIONEDITOR_H
|
||||
#define ACTIONEDITOR_H
|
||||
|
||||
#include <bindingeditor/bindingeditordialog.h>
|
||||
#include <qmldesignercorelib_global.h>
|
||||
#include <modelnode.h>
|
||||
|
||||
#include <QtQml>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class ActionEditor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString text READ bindingValue WRITE setBindingValue)
|
||||
|
||||
public:
|
||||
ActionEditor(QObject *parent = nullptr);
|
||||
~ActionEditor();
|
||||
|
||||
static void registerDeclarativeType();
|
||||
|
||||
Q_INVOKABLE void showWidget(int x, int y);
|
||||
Q_INVOKABLE void hideWidget();
|
||||
|
||||
QString bindingValue() const;
|
||||
void setBindingValue(const QString &text);
|
||||
|
||||
bool hasModelIndex() const;
|
||||
void resetModelIndex();
|
||||
QModelIndex modelIndex() const;
|
||||
void setModelIndex(const QModelIndex &index);
|
||||
|
||||
Q_INVOKABLE void updateWindowName();
|
||||
|
||||
signals:
|
||||
void accepted();
|
||||
void rejected();
|
||||
|
||||
private:
|
||||
QVariant backendValue() const;
|
||||
QVariant modelNodeBackend() const;
|
||||
QVariant stateModelNode() const;
|
||||
|
||||
private:
|
||||
QPointer<BindingEditorDialog> m_dialog;
|
||||
QModelIndex m_index;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QML_DECLARE_TYPE(QmlDesigner::ActionEditor)
|
||||
|
||||
#endif //ACTIONEDITOR_H
|
@@ -1,7 +1,9 @@
|
||||
HEADERS += $$PWD/bindingeditor.h
|
||||
HEADERS += $$PWD/actioneditor.h
|
||||
HEADERS += $$PWD/bindingeditordialog.h
|
||||
HEADERS += $$PWD/bindingeditorwidget.h
|
||||
|
||||
SOURCES += $$PWD/bindingeditor.cpp
|
||||
SOURCES += $$PWD/actioneditor.cpp
|
||||
SOURCES += $$PWD/bindingeditordialog.cpp
|
||||
SOURCES += $$PWD/bindingeditorwidget.cpp
|
||||
|
@@ -41,8 +41,9 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
BindingEditorDialog::BindingEditorDialog(QWidget *parent)
|
||||
BindingEditorDialog::BindingEditorDialog(QWidget *parent, DialogType type)
|
||||
: QDialog(parent)
|
||||
, m_dialogType(type)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setWindowFlag(Qt::Tool, true);
|
||||
@@ -59,6 +60,7 @@ BindingEditorDialog::BindingEditorDialog(QWidget *parent)
|
||||
QObject::connect(m_editorWidget, &BindingEditorWidget::returnKeyClicked,
|
||||
this, &BindingEditorDialog::accepted);
|
||||
|
||||
if (m_dialogType == DialogType::BindingDialog) {
|
||||
QObject::connect(m_comboBoxItem, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &BindingEditorDialog::itemIDChanged);
|
||||
QObject::connect(m_comboBoxProperty, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
@@ -66,6 +68,7 @@ BindingEditorDialog::BindingEditorDialog(QWidget *parent)
|
||||
QObject::connect(m_editorWidget, &QPlainTextEdit::textChanged,
|
||||
this, &BindingEditorDialog::textChanged);
|
||||
}
|
||||
}
|
||||
|
||||
BindingEditorDialog::~BindingEditorDialog()
|
||||
{
|
||||
@@ -186,10 +189,12 @@ void BindingEditorDialog::setupJSEditor()
|
||||
void BindingEditorDialog::setupUIComponents()
|
||||
{
|
||||
m_verticalLayout = new QVBoxLayout(this);
|
||||
m_comboBoxLayout = new QHBoxLayout;
|
||||
|
||||
if (m_dialogType == DialogType::BindingDialog) {
|
||||
m_comboBoxLayout = new QHBoxLayout;
|
||||
m_comboBoxItem = new QComboBox(this);
|
||||
m_comboBoxProperty = new QComboBox(this);
|
||||
}
|
||||
|
||||
m_editorWidget->setParent(this);
|
||||
m_editorWidget->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
|
||||
@@ -200,11 +205,11 @@ void BindingEditorDialog::setupUIComponents()
|
||||
m_buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
|
||||
|
||||
if (m_dialogType == DialogType::BindingDialog) {
|
||||
m_comboBoxLayout->addWidget(m_comboBoxItem);
|
||||
m_comboBoxLayout->addWidget(m_comboBoxProperty);
|
||||
|
||||
m_verticalLayout->addLayout(m_comboBoxLayout);
|
||||
}
|
||||
m_verticalLayout->addWidget(m_editorWidget);
|
||||
m_verticalLayout->addWidget(m_buttonBox);
|
||||
|
||||
|
@@ -57,8 +57,14 @@ public:
|
||||
QStringList properties;
|
||||
};
|
||||
|
||||
enum DialogType {
|
||||
Unknown = 0,
|
||||
BindingDialog = 1,
|
||||
ActionDialog = 2
|
||||
};
|
||||
|
||||
public:
|
||||
BindingEditorDialog(QWidget *parent = nullptr);
|
||||
BindingEditorDialog(QWidget *parent = nullptr, DialogType type = DialogType::BindingDialog);
|
||||
~BindingEditorDialog() override;
|
||||
|
||||
void showWidget(int x, int y);
|
||||
@@ -84,6 +90,7 @@ public slots:
|
||||
void textChanged();
|
||||
|
||||
private:
|
||||
DialogType m_dialogType = DialogType::BindingDialog;
|
||||
TextEditor::BaseTextEditor *m_editor = nullptr;
|
||||
BindingEditorWidget *m_editorWidget = nullptr;
|
||||
QVBoxLayout *m_verticalLayout = nullptr;
|
||||
|
@@ -47,6 +47,7 @@ QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &pr
|
||||
foreach (QmlDesigner::PropertyName propertyName, propertyNameList) {
|
||||
stringList << QString::fromUtf8(propertyName);
|
||||
}
|
||||
stringList.removeDuplicates();
|
||||
return stringList;
|
||||
}
|
||||
|
||||
@@ -281,6 +282,12 @@ void ConnectionModel::variantPropertyChanged(const VariantProperty &variantPrope
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void ConnectionModel::abstractPropertyChanged(const AbstractProperty &abstractProperty)
|
||||
{
|
||||
if (isConnection(abstractProperty.parentModelNode()))
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void ConnectionModel::deleteConnectionByRow(int currentRow)
|
||||
{
|
||||
signalHandlerPropertyForRow(currentRow).parentModelNode().destroy();
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class AbstractProperty;
|
||||
class ModelNode;
|
||||
class BindingProperty;
|
||||
class SignalHandlerProperty;
|
||||
@@ -59,6 +60,7 @@ public:
|
||||
|
||||
void bindingPropertyChanged(const BindingProperty &bindingProperty);
|
||||
void variantPropertyChanged(const VariantProperty &variantProperty);
|
||||
void abstractPropertyChanged(const AbstractProperty &abstractProperty);
|
||||
|
||||
void deleteConnectionByRow(int currentRow);
|
||||
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include <bindingproperty.h>
|
||||
#include <nodeabstractproperty.h>
|
||||
#include <variantproperty.h>
|
||||
#include <signalhandlerproperty.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -139,6 +140,13 @@ void ConnectionView::bindingPropertiesChanged(const QList<BindingProperty> &prop
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionView::signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &propertyList,
|
||||
AbstractView::PropertyChangeFlags /*propertyChange*/)
|
||||
{
|
||||
for (const SignalHandlerProperty &signalHandlerProperty : propertyList)
|
||||
connectionModel()->abstractPropertyChanged(signalHandlerProperty);
|
||||
}
|
||||
|
||||
void ConnectionView::selectedNodesChanged(const QList<ModelNode> & selectedNodeList,
|
||||
const QList<ModelNode> & /*lastSelectedNodeList*/)
|
||||
{
|
||||
|
@@ -65,6 +65,7 @@ public:
|
||||
void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList) override;
|
||||
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange) override;
|
||||
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange) override;
|
||||
void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty>& propertyList, PropertyChangeFlags propertyChange) override;
|
||||
|
||||
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
||||
const QList<ModelNode> &lastSelectedNodeList) override;
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "connectionmodel.h"
|
||||
#include "dynamicpropertiesmodel.h"
|
||||
#include "theme.h"
|
||||
#include "signalhandlerproperty.h"
|
||||
|
||||
#include <designersettings.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
@@ -43,6 +44,9 @@
|
||||
|
||||
#include <QToolButton>
|
||||
#include <QStyleFactory>
|
||||
#include <QMenu>
|
||||
|
||||
#include <bindingeditor/actioneditor.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -52,6 +56,27 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::ConnectionViewWidget)
|
||||
{
|
||||
m_actionEditor = new QmlDesigner::ActionEditor(this);
|
||||
QObject::connect(m_actionEditor, &QmlDesigner::ActionEditor::accepted,
|
||||
[&]() {
|
||||
if (m_actionEditor->hasModelIndex()) {
|
||||
ConnectionModel *connectionModel = qobject_cast<ConnectionModel *>(ui->connectionView->model());
|
||||
if (connectionModel->rowCount() > m_actionEditor->modelIndex().row())
|
||||
{
|
||||
SignalHandlerProperty signalHandler =
|
||||
connectionModel->signalHandlerPropertyForRow(m_actionEditor->modelIndex().row());
|
||||
signalHandler.setSource(m_actionEditor->bindingValue());
|
||||
}
|
||||
m_actionEditor->resetModelIndex();
|
||||
}
|
||||
|
||||
m_actionEditor->hideWidget();
|
||||
});
|
||||
QObject::connect(m_actionEditor, &QmlDesigner::ActionEditor::rejected,
|
||||
[&]() {
|
||||
m_actionEditor->resetModelIndex();
|
||||
m_actionEditor->hideWidget();
|
||||
});
|
||||
|
||||
setWindowTitle(tr("Connections", "Title of connection view"));
|
||||
ui->setupUi(this);
|
||||
@@ -96,6 +121,7 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) :
|
||||
|
||||
ConnectionViewWidget::~ConnectionViewWidget()
|
||||
{
|
||||
delete m_actionEditor;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@@ -116,9 +142,37 @@ void ConnectionViewWidget::setConnectionModel(ConnectionModel *model)
|
||||
ui->connectionView->horizontalHeader()->setDefaultSectionSize(160);
|
||||
ui->connectionView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
ui->connectionView->setItemDelegate(new ConnectionDelegate);
|
||||
|
||||
connect(ui->connectionView->selectionModel(), &QItemSelectionModel::currentRowChanged,
|
||||
this, &ConnectionViewWidget::connectionTableViewSelectionChanged);
|
||||
}
|
||||
|
||||
void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
if (currentTab() != ConnectionTab || ui->connectionView == nullptr)
|
||||
return;
|
||||
|
||||
//adjusting qpoint to the qtableview entrances:
|
||||
QPoint posInTable(ui->connectionView->mapFromGlobal(mapToGlobal(event->pos())));
|
||||
posInTable = QPoint(posInTable.x(), posInTable.y() - ui->connectionView->horizontalHeader()->height());
|
||||
|
||||
//making sure that we have source column in our hands:
|
||||
QModelIndex index = ui->connectionView->indexAt(posInTable).siblingAtColumn(ConnectionModel::SourceRow);
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
QMenu menu(this);
|
||||
|
||||
menu.addAction(tr("Open Action Editor"), [&]() {
|
||||
if (index.isValid()) {
|
||||
m_actionEditor->showWidget(mapToGlobal(event->pos()).x(), mapToGlobal(event->pos()).y());
|
||||
m_actionEditor->setBindingValue(index.data().toString());
|
||||
m_actionEditor->setModelIndex(index);
|
||||
m_actionEditor->updateWindowName();
|
||||
}
|
||||
});
|
||||
|
||||
menu.exec(event->globalPos());
|
||||
}
|
||||
|
||||
void ConnectionViewWidget::setDynamicPropertiesModel(DynamicPropertiesModel *model)
|
||||
|
@@ -38,6 +38,8 @@ namespace QmlDesigner {
|
||||
|
||||
namespace Ui { class ConnectionViewWidget; }
|
||||
|
||||
class ActionEditor;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class BindingModel;
|
||||
@@ -88,6 +90,9 @@ signals:
|
||||
void setEnabledAddButton(bool enabled);
|
||||
void setEnabledRemoveButton(bool enabled);
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
|
||||
private:
|
||||
void handleTabChanged(int i);
|
||||
void removeButtonClicked();
|
||||
@@ -95,6 +100,7 @@ private:
|
||||
|
||||
private:
|
||||
Ui::ConnectionViewWidget *ui;
|
||||
QmlDesigner::ActionEditor *m_actionEditor;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "itemfiltermodel.h"
|
||||
#include "simplecolorpalettemodel.h"
|
||||
#include "bindingeditor/bindingeditor.h"
|
||||
#include "bindingeditor/actioneditor.h"
|
||||
#include "qmlanchorbindingproxy.h"
|
||||
#include "theme.h"
|
||||
#include "aligndistribute.h"
|
||||
@@ -60,6 +61,7 @@ void Quick2PropertyEditorView::registerQmlTypes()
|
||||
SimpleColorPaletteModel::registerDeclarativeType();
|
||||
Internal::QmlAnchorBindingProxy::registerDeclarativeType();
|
||||
BindingEditor::registerDeclarativeType();
|
||||
ActionEditor::registerDeclarativeType();
|
||||
AlignDistribute::registerDeclarativeType();
|
||||
}
|
||||
}
|
||||
|
@@ -634,6 +634,8 @@ Project {
|
||||
files: [
|
||||
"bindingeditor/bindingeditor.cpp",
|
||||
"bindingeditor/bindingeditor.h",
|
||||
"bindingeditor/actioneditor.cpp",
|
||||
"bindingeditor/actioneditor.h",
|
||||
"bindingeditor/bindingeditordialog.cpp",
|
||||
"bindingeditor/bindingeditordialog.h",
|
||||
"bindingeditor/bindingeditorwidget.cpp",
|
||||
|
Reference in New Issue
Block a user