Enable layer filtering, and update moving to handle the proxy model

This commit is contained in:
Dan Paulat 2023-10-18 21:22:07 -05:00
parent b3d75b10ca
commit ddad68253a
2 changed files with 130 additions and 35 deletions

View file

@ -4,6 +4,8 @@
#include <scwx/qt/model/layer_model.hpp> #include <scwx/qt/model/layer_model.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <QSortFilterProxyModel>
namespace scwx namespace scwx
{ {
namespace qt namespace qt
@ -18,18 +20,26 @@ class LayerDialogImpl
{ {
public: public:
explicit LayerDialogImpl(LayerDialog* self) : explicit LayerDialogImpl(LayerDialog* self) :
self_ {self}, layerModel_ {new model::LayerModel(self)} self_ {self},
layerModel_ {new model::LayerModel(self)},
layerProxyModel_ {new QSortFilterProxyModel(self_)}
{ {
layerProxyModel_->setSourceModel(layerModel_);
layerProxyModel_->setFilterCaseSensitivity(
Qt::CaseSensitivity::CaseInsensitive);
layerProxyModel_->setFilterKeyColumn(-1);
} }
~LayerDialogImpl() = default; ~LayerDialogImpl() = default;
void ConnectSignals(); void ConnectSignals();
void UpdateMoveButtonsEnabled(); void UpdateMoveButtonsEnabled();
std::vector<int> GetSelectedRows(); std::vector<int> GetSelectedRows();
std::vector<std::vector<int>> GetContiguousRows();
LayerDialog* self_; LayerDialog* self_;
model::LayerModel* layerModel_; model::LayerModel* layerModel_;
QSortFilterProxyModel* layerProxyModel_;
}; };
LayerDialog::LayerDialog(QWidget* parent) : LayerDialog::LayerDialog(QWidget* parent) :
@ -39,7 +49,7 @@ LayerDialog::LayerDialog(QWidget* parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
ui->layerTreeView->setModel(p->layerModel_); ui->layerTreeView->setModel(p->layerProxyModel_);
auto layerViewHeader = ui->layerTreeView->header(); auto layerViewHeader = ui->layerTreeView->header();
@ -72,6 +82,11 @@ LayerDialog::~LayerDialog()
void LayerDialogImpl::ConnectSignals() void LayerDialogImpl::ConnectSignals()
{ {
QObject::connect(self_->ui->layerFilter,
&QLineEdit::textChanged,
layerProxyModel_,
&QSortFilterProxyModel::setFilterWildcard);
QObject::connect(self_->ui->layerTreeView->selectionModel(), QObject::connect(self_->ui->layerTreeView->selectionModel(),
&QItemSelectionModel::selectionChanged, &QItemSelectionModel::selectionChanged,
self_, self_,
@ -94,61 +109,111 @@ void LayerDialogImpl::ConnectSignals()
} }
}); });
QObject::connect( QObject::connect( //
self_->ui->moveTopButton, self_->ui->moveTopButton,
&QAbstractButton::clicked, &QAbstractButton::clicked,
self_, self_,
[this]() [this]()
{ {
auto selectedRows = GetSelectedRows(); auto contiguousRows = GetContiguousRows();
int sourceRow = selectedRows.front();
int count = static_cast<int>(selectedRows.size());
int destinationChild = 0; int destinationChild = 0;
layerModel_->moveRows( for (auto& selectedRows : contiguousRows)
QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); {
int sourceRow = selectedRows.front();
int count = static_cast<int>(selectedRows.size());
layerModel_->moveRows(QModelIndex(),
sourceRow,
count,
QModelIndex(),
destinationChild);
// Next set of rows should follow rows just added
destinationChild += count;
}
}); });
QObject::connect( QObject::connect( //
self_->ui->moveUpButton, self_->ui->moveUpButton,
&QAbstractButton::clicked, &QAbstractButton::clicked,
self_, self_,
[this]() [this]()
{ {
auto selectedRows = GetSelectedRows(); auto contiguousRows = GetContiguousRows();
int sourceRow = selectedRows.front(); int destinationChild = -1;
int count = static_cast<int>(selectedRows.size());
int destinationChild = sourceRow - 1;
layerModel_->moveRows( for (auto& selectedRows : contiguousRows)
QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); {
int sourceRow = selectedRows.front();
int count = static_cast<int>(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( QObject::connect( //
self_->ui->moveDownButton, self_->ui->moveDownButton,
&QAbstractButton::clicked, &QAbstractButton::clicked,
self_, self_,
[this]() [this]()
{ {
auto selectedRows = GetSelectedRows(); auto contiguousRows = GetContiguousRows();
int sourceRow = selectedRows.front(); int destinationChild = 0;
int count = static_cast<int>(selectedRows.size()); int offset = 0;
int destinationChild = selectedRows.back() + 2; if (!contiguousRows.empty())
{
destinationChild = contiguousRows.back().back() + 2;
}
layerModel_->moveRows( for (auto& selectedRows : contiguousRows)
QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); {
int sourceRow = selectedRows.front() - offset;
int count = static_cast<int>(selectedRows.size());
layerModel_->moveRows(QModelIndex(),
sourceRow,
count,
QModelIndex(),
destinationChild);
// Next set of rows should be offset
offset += count;
}
}); });
QObject::connect( QObject::connect( //
self_->ui->moveBottomButton, self_->ui->moveBottomButton,
&QAbstractButton::clicked, &QAbstractButton::clicked,
self_, self_,
[this]() [this]()
{ {
auto selectedRows = GetSelectedRows(); auto contiguousRows = GetContiguousRows();
int sourceRow = selectedRows.front();
int count = static_cast<int>(selectedRows.size());
int destinationChild = layerModel_->rowCount(); int destinationChild = layerModel_->rowCount();
int offset = 0;
layerModel_->moveRows( for (auto& selectedRows : contiguousRows)
QModelIndex(), sourceRow, count, QModelIndex(), destinationChild); {
int sourceRow = selectedRows.front() - offset;
int count = static_cast<int>(selectedRows.size());
layerModel_->moveRows(QModelIndex(),
sourceRow,
count,
QModelIndex(),
destinationChild);
// Next set of rows should be offset
offset += count;
}
}); });
} }
@ -159,12 +224,42 @@ std::vector<int> LayerDialogImpl::GetSelectedRows()
std::vector<int> rows {}; std::vector<int> rows {};
for (auto& selectedRow : selectedRows) for (auto& selectedRow : selectedRows)
{ {
rows.push_back(selectedRow.row()); rows.push_back(layerProxyModel_->mapToSource(selectedRow).row());
} }
std::sort(rows.begin(), rows.end()); std::sort(rows.begin(), rows.end());
return rows; return rows;
} }
std::vector<std::vector<int>> LayerDialogImpl::GetContiguousRows()
{
std::vector<std::vector<int>> contiguousRows {};
std::vector<int> 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() void LayerDialogImpl::UpdateMoveButtonsEnabled()
{ {
QModelIndexList selectedRows = QModelIndexList selectedRows =
@ -177,7 +272,7 @@ void LayerDialogImpl::UpdateMoveButtonsEnabled()
for (auto& rowIndex : selectedRows) for (auto& rowIndex : selectedRows)
{ {
int row = rowIndex.row(); int row = layerProxyModel_->mapToSource(rowIndex).row();
if (!layerModel_->IsMovable(row)) if (!layerModel_->IsMovable(row))
{ {
// If an item in the selection is not movable, disable all moves // If an item in the selection is not movable, disable all moves

View file

@ -50,7 +50,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="selectionMode"> <property name="selectionMode">
<enum>QAbstractItemView::ContiguousSelection</enum> <enum>QAbstractItemView::ExtendedSelection</enum>
</property> </property>
<property name="indentation"> <property name="indentation">
<number>0</number> <number>0</number>
@ -176,7 +176,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QLineEdit" name="lineEdit"> <widget class="QLineEdit" name="layerFilter">
<property name="placeholderText"> <property name="placeholderText">
<string>Filter</string> <string>Filter</string>
</property> </property>