#include "layer_dialog.hpp" #include "ui_layer_dialog.h" #include #include #include #include #include namespace scwx { namespace qt { namespace ui { static const std::string logPrefix_ = "scwx::qt::ui::layer_dialog"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class LayerDialogImpl { public: explicit LayerDialogImpl(LayerDialog* self) : self_ {self}, layerModel_ {model::LayerModel::Instance()}, layerProxyModel_ {new QSortFilterProxyModel(self_)} { layerProxyModel_->setSourceModel(layerModel_.get()); layerProxyModel_->setFilterCaseSensitivity( Qt::CaseSensitivity::CaseInsensitive); layerProxyModel_->setFilterKeyColumn(-1); } ~LayerDialogImpl() = default; void ConnectSignals(); void UpdateMapDisplayColumns(); void UpdateMoveButtonsEnabled(); std::vector GetSelectedRows(); std::vector> GetContiguousRows(); LayerDialog* self_; std::shared_ptr layerModel_; QSortFilterProxyModel* layerProxyModel_; }; LayerDialog::LayerDialog(QWidget* parent) : QDialog(parent), p {std::make_unique(this)}, ui(new Ui::LayerDialog) { ui->setupUi(this); ui->layerTreeView->setModel(p->layerProxyModel_); auto layerViewHeader = ui->layerTreeView->header(); layerViewHeader->setMinimumSectionSize(10); // Give small columns a fixed size for (auto column : model::LayerModel::ColumnIterator()) { if (column != model::LayerModel::Column::Description) { layerViewHeader->setSectionResizeMode( static_cast(column), QHeaderView::ResizeMode::ResizeToContents); } } // Disable move buttons ui->moveTopButton->setEnabled(false); ui->moveUpButton->setEnabled(false); ui->moveDownButton->setEnabled(false); ui->moveBottomButton->setEnabled(false); p->UpdateMapDisplayColumns(); p->ConnectSignals(); } LayerDialog::~LayerDialog() { delete ui; } void LayerDialogImpl::UpdateMapDisplayColumns() { auto& generalSettings = settings::GeneralSettings::Instance(); std::int64_t gridWidth = generalSettings.grid_width().GetValue(); std::int64_t gridHeight = generalSettings.grid_height().GetValue(); int mapCount = static_cast(gridWidth * gridHeight); int displayMap1Column = static_cast(model::LayerModel::Column::DisplayMap1); // For each 0-based map index, 1-3 (excluding 0, always displayed) for (int mapIndex = 1; mapIndex < 4; ++mapIndex) { const int column = displayMap1Column + mapIndex; const bool hide = mapIndex >= mapCount; self_->ui->layerTreeView->setColumnHidden(column, hide); } } void LayerDialogImpl::ConnectSignals() { QObject::connect( self_->ui->buttonBox->button(QDialogButtonBox::StandardButton::Reset), &QAbstractButton::clicked, self_, [this]() { layerModel_->ResetLayers(); }); QObject::connect(self_->ui->layerFilter, &QLineEdit::textChanged, layerProxyModel_, &QSortFilterProxyModel::setFilterWildcard); QObject::connect(self_->ui->layerTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, self_, [this](const QItemSelection& /* selected */, const QItemSelection& /* deselected */) { UpdateMoveButtonsEnabled(); }); QObject::connect(layerModel_.get(), &QAbstractItemModel::rowsMoved, self_, [this]() { UpdateMoveButtonsEnabled(); auto selectedRows = GetSelectedRows(); if (!selectedRows.empty()) { self_->ui->layerTreeView->scrollTo( layerModel_->index(selectedRows.front(), 0)); } }); QObject::connect( // self_->ui->moveTopButton, &QAbstractButton::clicked, self_, [this]() { auto contiguousRows = GetContiguousRows(); int destinationChild = 0; for (auto& selectedRows : contiguousRows) { int sourceRow = selectedRows.front(); int count = static_cast(selectedRows.size()); layerModel_->moveRows(QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); // Next set of rows should follow rows just added destinationChild += count; } }); QObject::connect( // self_->ui->moveUpButton, &QAbstractButton::clicked, self_, [this]() { auto contiguousRows = GetContiguousRows(); int destinationChild = -1; for (auto& selectedRows : contiguousRows) { int sourceRow = selectedRows.front(); int count = static_cast(selectedRows.size()); if (destinationChild == -1) { destinationChild = sourceRow - 1; } layerModel_->moveRows(QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); // Next set of rows should follow rows just added destinationChild += count; } }); QObject::connect( // self_->ui->moveDownButton, &QAbstractButton::clicked, self_, [this]() { auto contiguousRows = GetContiguousRows(); int destinationChild = 0; int offset = 0; if (!contiguousRows.empty()) { destinationChild = contiguousRows.back().back() + 2; } for (auto& selectedRows : contiguousRows) { int sourceRow = selectedRows.front() - offset; int count = static_cast(selectedRows.size()); layerModel_->moveRows(QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); // Next set of rows should be offset offset += count; } }); QObject::connect( // self_->ui->moveBottomButton, &QAbstractButton::clicked, self_, [this]() { auto contiguousRows = GetContiguousRows(); int destinationChild = layerModel_->rowCount(); int offset = 0; for (auto& selectedRows : contiguousRows) { int sourceRow = selectedRows.front() - offset; int count = static_cast(selectedRows.size()); layerModel_->moveRows(QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); // Next set of rows should be offset offset += count; } }); } std::vector LayerDialogImpl::GetSelectedRows() { QModelIndexList selectedRows = self_->ui->layerTreeView->selectionModel()->selectedRows(); std::vector rows {}; for (auto& selectedRow : selectedRows) { rows.push_back(layerProxyModel_->mapToSource(selectedRow).row()); } std::sort(rows.begin(), rows.end()); return rows; } std::vector> LayerDialogImpl::GetContiguousRows() { std::vector> contiguousRows {}; std::vector currentContiguousRows {}; auto rows = GetSelectedRows(); for (auto& row : rows) { // Next row is not contiguous with current row set if (!currentContiguousRows.empty() && currentContiguousRows.back() + 1 < row) { // Add current row set to contiguous rows, and reset current set contiguousRows.emplace_back(std::move(currentContiguousRows)); currentContiguousRows.clear(); } // Add row to current row set currentContiguousRows.push_back(row); } if (!currentContiguousRows.empty()) { // Add remaining rows to contiguous rows contiguousRows.emplace_back(currentContiguousRows); } return contiguousRows; } 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 = layerProxyModel_->mapToSource(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; } } } // 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 } // namespace qt } // namespace scwx