From 5d06f6bc210a4032bc7dcacd6c6dd8ea102c139d Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 16 Oct 2023 22:29:35 -0500 Subject: [PATCH] Implement layer move functionality using buttons --- scwx-qt/source/scwx/qt/model/layer_model.cpp | 56 +++++++ scwx-qt/source/scwx/qt/model/layer_model.hpp | 5 + scwx-qt/source/scwx/qt/ui/layer_dialog.cpp | 168 ++++++++++++++----- 3 files changed, 190 insertions(+), 39 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/layer_model.cpp b/scwx-qt/source/scwx/qt/model/layer_model.cpp index 8ced1199..6966baf0 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.cpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.cpp @@ -529,6 +529,62 @@ bool LayerModel::removeRows(int row, int count, const QModelIndex& parent) return true; } +bool LayerModel::moveRows(const QModelIndex& sourceParent, + int sourceRow, + int count, + const QModelIndex& destinationParent, + int destinationChild) +{ + bool moved = false; + + if (sourceParent != destinationParent || // Only accept internal moves + count < 1 || // Minimum selection size of 1 + sourceRow < 0 || // Valid source row (start) + sourceRow + count > p->layers_.size() || // Valid source row (end) + destinationChild < 0 || // Valid destination row + destinationChild > p->layers_.size()) + { + return false; + } + + if (destinationChild < sourceRow) + { + // Move up + auto first = p->layers_.begin() + destinationChild; + auto middle = p->layers_.begin() + sourceRow; + auto last = middle + count; + + beginMoveRows(sourceParent, + sourceRow, + sourceRow + count - 1, + destinationParent, + destinationChild); + std::rotate(first, middle, last); + endMoveRows(); + + moved = true; + } + else if (sourceRow + count < destinationChild) + { + // Move down + auto first = p->layers_.begin() + sourceRow; + auto middle = first + count; + auto last = p->layers_.begin() + destinationChild; + + beginMoveRows(sourceParent, + sourceRow, + sourceRow + count - 1, + destinationParent, + destinationChild); + std::rotate(first, middle, last); + endMoveRows(); + + moved = true; + } + + return moved; +} + void LayerModel::HandlePlacefileRemoved(const std::string& name) { auto it = diff --git a/scwx-qt/source/scwx/qt/model/layer_model.hpp b/scwx-qt/source/scwx/qt/model/layer_model.hpp index b63a6f9c..55b51b2b 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.hpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.hpp @@ -66,6 +66,11 @@ public: bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + bool moveRows(const QModelIndex& sourceParent, + int sourceRow, + int count, + const QModelIndex& destinationParent, + int destinationChild) override; public slots: void HandlePlacefileRemoved(const std::string& name); diff --git a/scwx-qt/source/scwx/qt/ui/layer_dialog.cpp b/scwx-qt/source/scwx/qt/ui/layer_dialog.cpp index 71783e36..00f49a80 100644 --- a/scwx-qt/source/scwx/qt/ui/layer_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/layer_dialog.cpp @@ -24,6 +24,9 @@ public: ~LayerDialogImpl() = default; void ConnectSignals(); + void UpdateMoveButtonsEnabled(); + + std::vector GetSelectedRows(); LayerDialog* self_; model::LayerModel* layerModel_; @@ -69,53 +72,140 @@ LayerDialog::~LayerDialog() void LayerDialogImpl::ConnectSignals() { + QObject::connect(self_->ui->layerTreeView->selectionModel(), + &QItemSelectionModel::selectionChanged, + self_, + [this](const QItemSelection& /* selected */, + const QItemSelection& /* deselected */) + { UpdateMoveButtonsEnabled(); }); + + QObject::connect(layerModel_, + &QAbstractItemModel::rowsMoved, + self_, + [this]() + { + UpdateMoveButtonsEnabled(); + + auto selectedRows = GetSelectedRows(); + if (!selectedRows.empty()) + { + self_->ui->layerTreeView->scrollTo( + layerModel_->index(selectedRows.front(), 0)); + } + }); + QObject::connect( - self_->ui->layerTreeView->selectionModel(), - &QItemSelectionModel::selectionChanged, + self_->ui->moveTopButton, + &QAbstractButton::clicked, self_, - [this](const QItemSelection& /* selected */, - const QItemSelection& /* deselected */) + [this]() { - QModelIndexList selectedRows = - self_->ui->layerTreeView->selectionModel()->selectedRows(); + auto selectedRows = GetSelectedRows(); + int sourceRow = selectedRows.front(); + int count = static_cast(selectedRows.size()); + int destinationChild = 0; - bool itemsSelected = selectedRows.size() > 0; - bool itemsMovableUp = itemsSelected; - bool itemsMovableDown = itemsSelected; - int rowCount = layerModel_->rowCount(); + layerModel_->moveRows( + QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); + }); + QObject::connect( + self_->ui->moveUpButton, + &QAbstractButton::clicked, + self_, + [this]() + { + auto selectedRows = GetSelectedRows(); + int sourceRow = selectedRows.front(); + int count = static_cast(selectedRows.size()); + int destinationChild = sourceRow - 1; - for (auto& rowIndex : selectedRows) + layerModel_->moveRows( + QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); + }); + QObject::connect( + self_->ui->moveDownButton, + &QAbstractButton::clicked, + self_, + [this]() + { + auto selectedRows = GetSelectedRows(); + int sourceRow = selectedRows.front(); + int count = static_cast(selectedRows.size()); + int destinationChild = selectedRows.back() + 2; + + layerModel_->moveRows( + QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); + }); + QObject::connect( + self_->ui->moveBottomButton, + &QAbstractButton::clicked, + self_, + [this]() + { + auto selectedRows = GetSelectedRows(); + int sourceRow = selectedRows.front(); + int count = static_cast(selectedRows.size()); + int destinationChild = layerModel_->rowCount(); + + layerModel_->moveRows( + QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); + }); +} + +std::vector LayerDialogImpl::GetSelectedRows() +{ + QModelIndexList selectedRows = + self_->ui->layerTreeView->selectionModel()->selectedRows(); + std::vector rows {}; + for (auto& selectedRow : selectedRows) + { + rows.push_back(selectedRow.row()); + } + std::sort(rows.begin(), rows.end()); + return rows; +} + +void LayerDialogImpl::UpdateMoveButtonsEnabled() +{ + QModelIndexList selectedRows = + self_->ui->layerTreeView->selectionModel()->selectedRows(); + + bool itemsSelected = selectedRows.size() > 0; + bool itemsMovableUp = itemsSelected; + bool itemsMovableDown = itemsSelected; + int rowCount = layerModel_->rowCount(); + + for (auto& rowIndex : selectedRows) + { + int row = rowIndex.row(); + if (!layerModel_->IsMovable(row)) + { + // If an item in the selection is not movable, disable all moves + itemsMovableUp = false; + itemsMovableDown = false; + break; + } + else + { + // If the first row is selected, items cannot be moved up + if (row == 0) { - int row = rowIndex.row(); - if (!layerModel_->IsMovable(row)) - { - // If an item in the selection is not movable, disable all moves - itemsMovableUp = false; - itemsMovableDown = false; - break; - } - else - { - // If the first row is selected, items cannot be moved up - if (row == 0) - { - itemsMovableUp = false; - } - - // If the last row is selected, items cannot be moved down - if (row == rowCount - 1) - { - itemsMovableDown = false; - } - } + itemsMovableUp = false; } - // Enable move buttons according to selection - self_->ui->moveTopButton->setEnabled(itemsMovableUp); - self_->ui->moveUpButton->setEnabled(itemsMovableUp); - self_->ui->moveDownButton->setEnabled(itemsMovableDown); - self_->ui->moveBottomButton->setEnabled(itemsMovableDown); - }); + // If the last row is selected, items cannot be moved down + if (row == rowCount - 1) + { + itemsMovableDown = false; + } + } + } + + // Enable move buttons according to selection + self_->ui->moveTopButton->setEnabled(itemsMovableUp); + self_->ui->moveUpButton->setEnabled(itemsMovableUp); + self_->ui->moveDownButton->setEnabled(itemsMovableDown); + self_->ui->moveBottomButton->setEnabled(itemsMovableDown); } } // namespace ui