diff options
author | Marco Bubke <marco.bubke@qt.io> | 2020-07-02 19:19:52 +0200 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2020-07-08 09:17:41 +0000 |
commit | b73ce9eccfc5f3e06fa92efb53bd8c341c13f3e7 (patch) | |
tree | 97a669c36de59d330faefb7840c0ccd79b875978 | |
parent | 7504c966bf64a4b38b8e9ff200c93b2e8470acad (diff) | |
download | qt-creator-b73ce9eccfc5f3e06fa92efb53bd8c341c13f3e7.tar.gz |
QmlDesigner: Add row move up and move down buttons
Task-number: QDS-2294
Change-Id: Ia1e64d0811f55151dfe529db4868821840a8fba9
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
5 files changed, 301 insertions, 0 deletions
diff --git a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.cpp b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.cpp index 968c719af0..0cf73976a8 100644 --- a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.cpp +++ b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.cpp @@ -27,6 +27,7 @@ #include "listmodeleditormodel.h" #include <theme.h> +#include <qmldesignericons.h> #include <coreplugin/icore.h> #include <utils/algorithm.h> @@ -71,6 +72,10 @@ ListModelEditorDialog::ListModelEditorDialog(QWidget *parent) m_addColumnAction = toolBar->addAction(getIcon(Theme::Icon::addColumnAfter), tr("Add Column")); m_removeColumnsAction = toolBar->addAction(getIcon(Theme::Icon::deleteColumn), tr("Remove Columns")); + m_moveDownAction = toolBar->addAction(Icons::ARROW_DOWN.icon(), tr("Move down (CTRL + Down).")); + m_moveDownAction->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL)); + m_moveUpAction = toolBar->addAction(Icons::ARROW_UP.icon(), tr("Move up (CTRL + Up).")); + m_moveDownAction->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL)); } ListModelEditorDialog::~ListModelEditorDialog() = default; @@ -83,6 +88,8 @@ void ListModelEditorDialog::setModel(ListModelEditorModel *model) connect(m_addColumnAction, &QAction::triggered, this, &ListModelEditorDialog::openColumnDialog); connect(m_removeRowsAction, &QAction::triggered, this, &ListModelEditorDialog::removeRows); connect(m_removeColumnsAction, &QAction::triggered, this, &ListModelEditorDialog::removeColumns); + connect(m_moveDownAction, &QAction::triggered, this, &ListModelEditorDialog::moveRowsDown); + connect(m_moveUpAction, &QAction::triggered, this, &ListModelEditorDialog::moveRowsUp); connect(m_tableView->horizontalHeader(), &QHeaderView::sectionDoubleClicked, this, @@ -134,4 +141,16 @@ void ListModelEditorDialog::changeHeader(int column) m_model->renameColumn(column, newPropertyName); } +void ListModelEditorDialog::moveRowsDown() +{ + QItemSelection selection = m_model->moveRowsDown(m_tableView->selectionModel()->selectedRows()); + m_tableView->selectionModel()->select(selection, QItemSelectionModel::Select); +} + +void ListModelEditorDialog::moveRowsUp() +{ + QItemSelection selection = m_model->moveRowsUp(m_tableView->selectionModel()->selectedRows()); + m_tableView->selectionModel()->select(selection, QItemSelectionModel::Select); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.h b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.h index 519d0869fa..24e19c8ff9 100644 --- a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.h +++ b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditordialog.h @@ -59,6 +59,8 @@ private: void removeRows(); void removeColumns(); void changeHeader(int column); + void moveRowsDown(); + void moveRowsUp(); private: ListModelEditorModel *m_model{}; @@ -66,6 +68,8 @@ private: QAction *m_removeRowsAction{}; QAction *m_addColumnAction{}; QAction *m_removeColumnsAction{}; + QAction *m_moveUpAction{}; + QAction *m_moveDownAction{}; QTableView *m_tableView{}; }; diff --git a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp index 066af6e345..0aeabb8b89 100644 --- a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp +++ b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp @@ -319,6 +319,42 @@ void ListModelEditorModel::renameColumn(int oldColumn, const QString &newColumnN setHorizontalHeaderLabels(convertToStringList(m_propertyNames)); } +QItemSelection ListModelEditorModel::moveRowsUp(const QList<QModelIndex> &indices) +{ + std::vector<int> rows = filterRows(indices); + + if (rows.empty() || rows.front() < 1) + return {}; + + auto nodeListProperty = m_listModelNode.defaultNodeListProperty(); + + for (int row : rows) { + insertRow(row - 1, takeRow(row)); + nodeListProperty.slide(row, row - 1); + } + + return {index(rows.front() - 1, 0), index(rows.back() - 1, columnCount() - 1)}; +} + +QItemSelection ListModelEditorModel::moveRowsDown(const QList<QModelIndex> &indices) +{ + std::vector<int> rows = filterRows(indices); + + if (rows.empty() || rows.back() >= (rowCount() - 1)) + return {}; + + auto nodeListProperty = m_listModelNode.defaultNodeListProperty(); + + std::reverse(rows.begin(), rows.end()); + + for (int row : rows) { + insertRow(row + 1, takeRow(row)); + nodeListProperty.slide(row, row + 1); + } + + return {index(rows.front() + 1, 0), index(rows.back() + 1, columnCount() - 1)}; +} + std::vector<int> ListModelEditorModel::filterColumns(const QList<QModelIndex> &indices) { std::vector<int> columns; diff --git a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h index 3976b34a9d..3056d32dbb 100644 --- a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h +++ b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h @@ -27,6 +27,7 @@ #include <modelnode.h> +#include <QItemSelection> #include <QStandardItemModel> namespace QmlDesigner { @@ -53,6 +54,8 @@ public: void removeColumns(const QList<QModelIndex> &indices); void removeRows(const QList<QModelIndex> &indices); void renameColumn(int column, const QString &newColumnName); + QItemSelection moveRowsUp(const QList<QModelIndex> &indices); + QItemSelection moveRowsDown(const QList<QModelIndex> &indices); static std::vector<int> filterColumns(const QList<QModelIndex> &indices); static std::vector<int> filterRows(const QList<QModelIndex> &indices); diff --git a/tests/unit/unittest/listmodeleditor-test.cpp b/tests/unit/unittest/listmodeleditor-test.cpp index 1dcd54c286..af4009ae9b 100644 --- a/tests/unit/unittest/listmodeleditor-test.cpp +++ b/tests/unit/unittest/listmodeleditor-test.cpp @@ -175,6 +175,11 @@ public: QModelIndex index(int row, int column) const { return model.index(row, column); } + QList<ModelNode> elements(const ModelNode &node) const + { + return node.defaultNodeListProperty().toModelNodeList(); + } + protected: std::unique_ptr<QmlDesigner::Model> designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)}; NiceMock<MockListModelEditorView> mockView; @@ -1033,4 +1038,238 @@ TEST_F(ListModelEditor, FilterRowsEmptyInput) ASSERT_THAT(rows, IsEmpty()); } +TEST_F(ListModelEditor, CannotMoveEmptyRowsUp) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(-1, 1)}; + + model.moveRowsUp(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3)); +} + +TEST_F(ListModelEditor, MoveRowUp) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(1, 2), index(1, 0)}; + + model.moveRowsUp(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element2, element1, element3)); +} + +TEST_F(ListModelEditor, MoveRowsUp) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)}; + + model.moveRowsUp(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element2, element3, element1)); +} + +TEST_F(ListModelEditor, CannotMoveFirstRowsUp) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)}; + + model.moveRowsUp(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3)); +} + +TEST_F(ListModelEditor, CannotMoveEmptyRowsUpDisplayValues) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(-1, 1)}; + + model.moveRowsUp(indices); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, CannotMoveFirstRowUpDisplayValues) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)}; + + model.moveRowsUp(indices); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, MoveRowsUpDisplayValues) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)}; + + model.moveRowsUp(indices); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()), + ElementsAre(IsInvalid(), "foo", 1, 42))); +} + +TEST_F(ListModelEditor, NoSelectionAfterCannotMoveLastRowsDown) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)}; + + auto selection = model.moveRowsUp(indices); + + ASSERT_THAT(selection.indexes(), IsEmpty()); +} + +TEST_F(ListModelEditor, NoSelectionAfterMoveEmptyRowsDown) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(-1, 1)}; + + auto selection = model.moveRowsUp(indices); + + ASSERT_THAT(selection.indexes(), IsEmpty()); +} + +TEST_F(ListModelEditor, SelectionAfterMoveRowsDown) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)}; + + auto selection = model.moveRowsUp(indices); + + ASSERT_THAT(selection.indexes(), + ElementsAre(index(0, 0), + index(0, 1), + index(0, 2), + index(0, 3), + index(1, 0), + index(1, 1), + index(1, 2), + index(1, 3))); +} + +TEST_F(ListModelEditor, CannotMoveEmptyRowsDown) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(-1, 1)}; + + model.moveRowsDown(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3)); +} + +TEST_F(ListModelEditor, MoveRowDown) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(1, 2), index(1, 0)}; + + model.moveRowsDown(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element3, element2)); +} + +TEST_F(ListModelEditor, MoveRowsDown) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)}; + + model.moveRowsDown(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element3, element1, element2)); +} + +TEST_F(ListModelEditor, CannotMoveLastRowsDown) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)}; + + model.moveRowsDown(indices); + + ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3)); +} + +TEST_F(ListModelEditor, CannotMoveEmptyRowsDownDisplayValues) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(-1, 1)}; + + model.moveRowsDown(indices); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, CannotMoveLastRowDownDisplayValues) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)}; + + model.moveRowsDown(indices); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, MoveRowsDownDisplayValues) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)}; + + model.moveRowsDown(indices); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre("pic.png", "poo", 111, IsInvalid()), + ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()))); +} + +TEST_F(ListModelEditor, NoSelectionAfterCannotMoveLastRowsUp) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)}; + + auto selection = model.moveRowsDown(indices); + + ASSERT_THAT(selection.indexes(), IsEmpty()); +} + +TEST_F(ListModelEditor, NoSelectionAfterMoveEmptyRowsUp) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(-1, 1)}; + + auto selection = model.moveRowsDown(indices); + + ASSERT_THAT(selection.indexes(), IsEmpty()); +} + +TEST_F(ListModelEditor, SelectionAfterMoveRowsUp) +{ + model.setListModel(listModelNode); + QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)}; + + auto selection = model.moveRowsDown(indices); + + ASSERT_THAT(selection.indexes(), + ElementsAre(index(1, 0), + index(1, 1), + index(1, 2), + index(1, 3), + index(2, 0), + index(2, 1), + index(2, 2), + index(2, 3))); +} + } // namespace |