# HG changeset patch # User Teemu Piippo # Date 1654705980 -10800 # Node ID 52e10e8d88cc391e9dd3fd4ab9ef0433e58bcd73 # Parent 1909a0123c72da07ecbcba2096f6887cca712f3e Concentrate model editing into one coroutine inside main() diff -r 1909a0123c72 -r 52e10e8d88cc src/document.cpp --- a/src/document.cpp Tue Jun 07 21:35:29 2022 +0300 +++ b/src/document.cpp Wed Jun 08 19:33:00 2022 +0300 @@ -32,7 +32,6 @@ colorTable{colorTable}, canvas{new Canvas{model, this, documents, colorTable, this}}, model{model}, - documents{documents}, vertexMap{model} { this->setMouseTracking(true); @@ -183,31 +182,40 @@ switch (this->drawState.polygon.size()) { case 2: - this->model->append(Colored{ - LineSegment{ - .p1 = this->drawState.polygon[0], - .p2 = this->drawState.polygon[1], - }, - ldraw::EDGE_COLOR}); + Q_EMIT this->modelAction(AppendToModel{ + .newElement = Colored{ + LineSegment{ + .p1 = this->drawState.polygon[0], + .p2 = this->drawState.polygon[1], + }, + ldraw::EDGE_COLOR, + } + }); break; case 3: - this->model->append(Colored{ - Triangle{ - .p1 = this->drawState.polygon[0], - .p2 = this->drawState.polygon[1], - .p3 = this->drawState.polygon[2], - }, - ldraw::MAIN_COLOR}); + Q_EMIT this->modelAction(AppendToModel{ + .newElement = Colored{ + Triangle{ + .p1 = this->drawState.polygon[0], + .p2 = this->drawState.polygon[1], + .p3 = this->drawState.polygon[2], + }, + ldraw::MAIN_COLOR, + } + }); break; case 4: - this->model->append(Colored{ - Quadrilateral{ - .p1 = this->drawState.polygon[0], - .p2 = this->drawState.polygon[1], - .p3 = this->drawState.polygon[2], - .p4 = this->drawState.polygon[3], - }, - ldraw::MAIN_COLOR}); + Q_EMIT this->modelAction(AppendToModel{ + .newElement = Colored{ + Quadrilateral{ + .p1 = this->drawState.polygon[0], + .p2 = this->drawState.polygon[1], + .p3 = this->drawState.polygon[2], + .p4 = this->drawState.polygon[3], + }, + ldraw::MAIN_COLOR, + } + }); break; } } diff -r 1909a0123c72 -r 52e10e8d88cc src/document.h --- a/src/document.h Tue Jun 07 21:35:29 2022 +0300 +++ b/src/document.h Wed Jun 08 19:33:00 2022 +0300 @@ -24,6 +24,20 @@ #include "model.h" #include "vertexmap.h" +struct AppendToModel +{ + ModelElement newElement; +}; + +struct DeleteFromModel +{ + int position; +}; + +using ModelAction = std::variant; + +Q_DECLARE_METATYPE(ModelAction) + class EditorTabWidget : public QWidget { Q_OBJECT @@ -46,9 +60,9 @@ Q_SIGNALS: void newStatusText(const QString& newStatusText); void splitterChanged(); + void modelAction(const ModelAction& action); private: void closeShape(); DrawState drawState; - DocumentManager* const documents; VertexMap vertexMap; }; diff -r 1909a0123c72 -r 52e10e8d88cc src/main.cpp --- a/src/main.cpp Tue Jun 07 21:35:29 2022 +0300 +++ b/src/main.cpp Wed Jun 08 19:33:00 2022 +0300 @@ -263,6 +263,22 @@ } } +constexpr bool sortModelIndexesByRow(const QModelIndex& a, const QModelIndex& b) +{ + return a.row() < b.row(); +} + +std::vector rows(const QModelIndexList& indexList) +{ + std::vector result; + result.reserve(indexList.size()); + for (const QModelIndex& index : indexList) + { + result.push_back(index.row()); + } + return result; +} + int main(int argc, char *argv[]) { doQtRegistrations(); @@ -303,6 +319,18 @@ ); } }; + static constexpr auto executeAction = [&]( + Model* model, const ModelAction& action + ) { + std::visit(overloaded{ + [model](const AppendToModel& action){ + model->append(action.newElement); + }, + [model](const DeleteFromModel& action){ + model->remove(action.position); + }, + }, action); + }; const auto restoreSettings = [&]{ recentlyOpenedFiles = settings.recentFiles(); documentSplitterState = settings.mainSplitterState(); @@ -329,6 +357,10 @@ const auto openModelForEditing = [&](const ModelId modelId){ Model* model = documents.getModelById(modelId); EditorTabWidget* document = new EditorTabWidget{model, &documents, colorTable}; + QObject::connect( + document, + &EditorTabWidget::modelAction, + std::bind(executeAction, model, std::placeholders::_1)); QItemSelectionModel* selectionModel = new QItemSelectionModel{model}; itemSelectionModels[model] = selectionModel; QObject::connect(selectionModel, &QItemSelectionModel::selectionChanged, @@ -447,6 +479,16 @@ } } }); + QObject::connect(ui.actionDelete, &QAction::triggered, [&]{ + EditorTabWidget* tab = currentTabWidget(&ui); + if (tab != nullptr) { + std::vector selectedRows = rows(ui.modelListView->selectionModel()->selectedRows()); + std::sort(selectedRows.begin(), selectedRows.end(), std::greater{}); + for (int row : selectedRows) { + executeAction(tab->model, DeleteFromModel{.position = row}); + } + } + }); QObject::connect(ui.actionDrawAxes, &QAction::triggered, [&](bool drawAxes){ renderPreferences.drawAxes = drawAxes; saveSettings(); @@ -477,14 +519,16 @@ }); } QObject::connect(ui.mdiArea, &QMdiArea::subWindowActivated, - [&](QMdiSubWindow* subWindow){ - EditorTabWidget* tab = qobject_cast(subWindow->widget()); - if (tab != nullptr) { - checkEditingModeAction(tab->currentEditingMode()); - QItemSelectionModel* selectionModel = itemSelectionModels.value(tab->model); - if (selectionModel != nullptr) { - ui.modelListView->setModel(tab->model); - ui.modelListView->setSelectionModel(selectionModel); + [&](QMdiSubWindow* subWindow) { + if (subWindow != nullptr) { + EditorTabWidget* tab = qobject_cast(subWindow->widget()); + if (tab != nullptr) { + checkEditingModeAction(tab->currentEditingMode()); + QItemSelectionModel* selectionModel = itemSelectionModels.value(tab->model); + if (selectionModel != nullptr) { + ui.modelListView->setModel(tab->model); + ui.modelListView->setSelectionModel(selectionModel); + } } } }); diff -r 1909a0123c72 -r 52e10e8d88cc src/mainwindow.ui --- a/src/mainwindow.ui Tue Jun 07 21:35:29 2022 +0300 +++ b/src/mainwindow.ui Wed Jun 08 19:33:00 2022 +0300 @@ -39,7 +39,7 @@ 0 0 800 - 22 + 28 @@ -172,7 +172,23 @@ - + + + true + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + true + + + true + + diff -r 1909a0123c72 -r 52e10e8d88cc src/model.cpp --- a/src/model.cpp Tue Jun 07 21:35:29 2022 +0300 +++ b/src/model.cpp Wed Jun 08 19:33:00 2022 +0300 @@ -111,11 +111,24 @@ return pointerToOptional(findInMap(this->positions, id)); } +template +void removeFromMap(std::map& map, const K& key) +{ + const auto it = map.find(key); + if (it != map.end()) { + map.erase(it); + } +} + void Model::remove(int index) { if (index >= 0 and index < this->size()) { Q_EMIT this->beginRemoveRows({}, index, index); + removeFromMap(this->positions, this->body[index].id); this->body.erase(this->body.begin() + index); + for (int i = index; i < this->size(); ++i) { + this->positions[this->body[i].id] = i; + } Q_EMIT this->endRemoveRows(); } }