Wed, 08 Jun 2022 19:33:00 +0300
Concentrate model editing into one coroutine inside main()
src/document.cpp | file | annotate | diff | comparison | revisions | |
src/document.h | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions | |
src/mainwindow.ui | file | annotate | diff | comparison | revisions | |
src/model.cpp | file | annotate | diff | comparison | revisions |
--- 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>{ - LineSegment{ - .p1 = this->drawState.polygon[0], - .p2 = this->drawState.polygon[1], - }, - ldraw::EDGE_COLOR}); + Q_EMIT this->modelAction(AppendToModel{ + .newElement = Colored<LineSegment>{ + LineSegment{ + .p1 = this->drawState.polygon[0], + .p2 = this->drawState.polygon[1], + }, + ldraw::EDGE_COLOR, + } + }); break; case 3: - this->model->append(Colored<Triangle>{ - 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>{ + 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>{ - 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>{ + 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; } }
--- 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<AppendToModel, DeleteFromModel>; + +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; };
--- 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<int> rows(const QModelIndexList& indexList) +{ + std::vector<int> 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<int> selectedRows = rows(ui.modelListView->selectionModel()->selectedRows()); + std::sort(selectedRows.begin(), selectedRows.end(), std::greater<int>{}); + 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<EditorTabWidget*>(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<EditorTabWidget*>(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); + } } } });
--- 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 @@ <x>0</x> <y>0</y> <width>800</width> - <height>22</height> + <height>28</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -172,7 +172,23 @@ <widget class="QWidget" name="dockWidgetContents_3"> <layout class="QVBoxLayout" name="verticalLayout_4"> <item> - <widget class="QListView" name="modelListView"/> + <widget class="QListView" name="modelListView"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="selectionRectVisible"> + <bool>true</bool> + </property> + </widget> </item> </layout> </widget>
--- 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<typename K, typename V> +void removeFromMap(std::map<K, V>& 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(); } }