src/main.cpp

changeset 214
8e1fe64ce4e3
parent 212
27259810da6d
child 215
34c6e7bc4ee1
--- a/src/main.cpp	Sat Jun 11 15:20:24 2022 +0300
+++ b/src/main.cpp	Sun Jun 12 20:47:04 2022 +0300
@@ -3,15 +3,34 @@
 #include <QMessageBox>
 #include <QMdiSubWindow>
 #include <QStackedWidget>
+#include <QCloseEvent>
 #include "mainwindow.h"
 #include "ui_mainwindow.h"
 #include "version.h"
+#include "ui/canvas.h"
 #include "document.h"
 #include "settingseditor/settingseditor.h"
 #include "widgets/colorselectdialog.h"
 
 static const QDir LOCALE_DIR {":/locale"};
 
+class ModelSubWindow : public QMdiSubWindow
+{
+	Q_OBJECT
+public:
+	const ModelId modelId;
+	ModelSubWindow(ModelId modelId, QWidget* widget) :
+		QMdiSubWindow{widget},
+		modelId{modelId}
+	{
+	}
+protected:
+	void closeEvent(QCloseEvent* event) override
+	{
+		event->ignore();
+	}
+};
+
 static void doQtRegistrations()
 {
 	QCoreApplication::setApplicationName(::appName);
@@ -32,6 +51,18 @@
 	}
 };
 
+class ModelData : public QObject
+{
+	Q_OBJECT
+public:
+	ModelData(QObject* parent) : QObject {parent} {}
+	std::unique_ptr<Canvas> canvas;
+	std::unique_ptr<QItemSelectionModel> itemSelectionModel;
+	std::unique_ptr<EditTools> tools;
+	Model* model;
+};
+#include "main.moc"
+
 static constexpr MemberData<Ui_MainWindow, QAction*, gl::RenderStyle> renderStyleButtons[] = {
 	{ offsetof(Ui_MainWindow, actionRenderStyleNormal), gl::RenderStyle::Normal },
 	{ offsetof(Ui_MainWindow, actionRenderStyleBfc), gl::RenderStyle::BfcRedGreen },
@@ -107,52 +138,41 @@
 	}
 }
 
-/*
-void MainWindow::handleDocumentSplitterChange()
+ModelData* findModelData(DocumentManager* documents, ModelId modelId)
+{
+	return documents->findPayload<ModelData>(modelId);
+}
+
+static ModelSubWindow* currentModelSubWindow(Ui_MainWindow* ui)
 {
-	EditorTabWidget* currentDocument = this->currentDocument();
-	if (currentDocument != nullptr)
-	{
-		this->documentSplitterState = currentDocument->saveSplitterState();
-		for (int i = 0; i < this->ui->tabs->count(); i += 1)
-		{
-			EditorTabWidget* document = qobject_cast<EditorTabWidget*>(this->ui->tabs->widget(i));
-			if (document != nullptr and document != currentDocument)
-			{
-				document->restoreSplitterState(this->documentSplitterState);
-			}
-		}
-		this->settings.setMainSplitterState(this->documentSplitterState);
-	}
+	return qobject_cast<ModelSubWindow*>(ui->mdiArea->activeSubWindow());
 }
-*/
 
-static EditorTabWidget* currentTabWidget(Ui_MainWindow* ui)
+static ModelData* currentModelData(Ui_MainWindow* ui, DocumentManager* documents)
 {
-	QMdiSubWindow* activeSubWindow = ui->mdiArea->activeSubWindow();
-	if (activeSubWindow == nullptr) {
-		return nullptr;
+	if (auto* const activeSubWindow = currentModelSubWindow(ui)) {
+		return findModelData(documents, activeSubWindow->modelId);
 	}
 	else {
-		return qobject_cast<EditorTabWidget*>(activeSubWindow->widget());
-	}
-};
-
-
-static void closeDocument(DocumentManager* documents, EditorTabWidget *document)
-{
-	std::optional<ModelId> modelId = documents->findIdForModel(document->model);
-	if (modelId.has_value()) {
-		documents->closeDocument(modelId.value());
-		delete document;
+		return nullptr;
 	}
 }
 
-static std::optional<ModelId> findCurrentModelId(Ui_MainWindow* ui, DocumentManager* documents)
+static Model* currentModelBody(Ui_MainWindow* ui, DocumentManager* documents)
 {
-	const EditorTabWidget* tab = currentTabWidget(ui);
-	if (tab != nullptr) {
-		return documents->findIdForModel(tab->model);
+	if (auto* const activeSubWindow = currentModelSubWindow(ui)) {
+		return documents->getModelById(activeSubWindow->modelId);
+	}
+	else {
+		return nullptr;
+	}
+}
+
+static std::optional<ModelId> findCurrentModelId(Ui_MainWindow* ui)
+{
+	ModelSubWindow* activeSubWindow = qobject_cast<ModelSubWindow*>(ui->mdiArea->activeSubWindow());
+	if (activeSubWindow != nullptr) {
+		return activeSubWindow->modelId;
 	}
 	else {
 		return {};
@@ -196,16 +216,28 @@
 	}
 }
 
+template<typename Fn>
+static void forModel(const DocumentManager* documents, Fn&& fn)
+{
+	forValueInMap(*documents, [&fn](const DocumentManager::ModelInfo& info)
+	{
+		ModelData* modelSpecificData = qobject_cast<ModelData*>(info.payload);
+		if (modelSpecificData != nullptr) {
+			fn(&info, modelSpecificData);
+		}
+	});
+}
+
 static void updateRenderPreferences(
 	Ui_MainWindow* ui,
-	const gl::RenderPreferences* renderPreferences)
+	const gl::RenderPreferences* renderPreferences,
+	const DocumentManager* documents)
 {
-	for (QMdiSubWindow* subWindow : ui->mdiArea->subWindowList()) {
-		EditorTabWidget* tab = qobject_cast<EditorTabWidget*>(subWindow->widget());
-		if (tab != nullptr) {
-			tab->canvas->setRenderPreferences(*renderPreferences);
+	forModel(documents, [&renderPreferences](const void*, const ModelData* data){
+		if (data->canvas != nullptr) {
+			data->canvas->setRenderPreferences(*renderPreferences);
 		}
-	}
+	});
 	for (auto data : ::renderStyleButtons) {
 		QAction* action = data.memberInstance(ui);
 		action->setChecked(renderPreferences->style == data.payload);
@@ -295,7 +327,6 @@
 	QStringList recentlyOpenedFiles;
 	ColorTable colorTable;
 	gl::RenderPreferences renderPreferences;
-	QMap<Model*, QItemSelectionModel*> itemSelectionModels;
 	ui.setupUi(&mainWindow);
 	const uiutilities::KeySequenceMap defaultKeyboardShortcuts =
 		uiutilities::makeKeySequenceMap(uiutilities::collectActions(&mainWindow));
@@ -340,7 +371,7 @@
 		libraries.restoreFromSettings(&settings);
 		updateRecentlyOpenedDocumentsMenu();
 		colorTable = loadColors(&libraries);
-		updateRenderPreferences(&ui, &renderPreferences);
+		updateRenderPreferences(&ui, &renderPreferences, &documents);
 		ui.mdiArea->setViewMode(static_cast<QMdiArea::ViewMode>(settings.viewMode()));
 		ui.retranslateUi(&mainWindow);
 	};
@@ -357,36 +388,45 @@
 	};
 	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,
-			[model, document](const QItemSelection& selected, const QItemSelection& deselected)
-		{
-			auto resolveIndex = [&model](const QModelIndex& index){
-				return model->idAt(index.row());
-			};
-			auto resolve = [&resolveIndex](const QItemSelection& selection)
+		if (model != nullptr) {
+			ModelData* data = new ModelData(&documents);
+			data->tools = std::make_unique<EditTools>(model, colorTable);
+			data->canvas = std::make_unique<Canvas>(model, data->tools.get(), &documents, colorTable);
+			data->itemSelectionModel = std::make_unique<QItemSelectionModel>(model);
+			data->model = model;
+			QObject::connect(
+				data->tools.get(),
+				&EditTools::modelAction,
+				std::bind(executeAction, model, std::placeholders::_1));
+			QObject::connect(data->itemSelectionModel.get(), &QItemSelectionModel::selectionChanged,
+				[modelId, &documents](
+				const QItemSelection& selected,
+				const QItemSelection& deselected)
 			{
-				return fn::map<QSet<ModelId>>(selection.indexes(), resolveIndex);
-			};
-			document->canvas->handleSelectionChange(resolve(selected), resolve(deselected));
-		});
-		document->canvas->setRenderPreferences(renderPreferences);
-		QObject::connect(
-			document,
-			&EditorTabWidget::newStatusText,
-			[&](const QString& newStatusText) {
-				mainWindow.statusBar()->showMessage(newStatusText);
+				ModelData* data = findModelData(&documents, modelId);
+				if (data != nullptr) {
+					auto resolveIndex = [&data](const QModelIndex& index){
+						return data->model->idAt(index.row());
+					};
+					auto resolve = [&resolveIndex](const QItemSelection& selection)
+					{
+						return fn::map<QSet<ModelId>>(selection.indexes(), resolveIndex);
+					};
+					data->canvas->handleSelectionChange(resolve(selected), resolve(deselected));
+				}
 			});
-		const QFileInfo fileInfo{*documents.modelPath(modelId)};
-		QMdiSubWindow* subWindow = ui.mdiArea->addSubWindow(document);
-		subWindow->setWindowTitle(tabName(fileInfo));
-		subWindow->show();
+			data->canvas->setRenderPreferences(renderPreferences);
+			QObject::connect(
+				data->tools.get(),
+				&EditTools::newStatusText,
+				[&](const QString& newStatusText) {
+					mainWindow.statusBar()->showMessage(newStatusText);
+				});
+			const QFileInfo fileInfo{*documents.modelPath(modelId)};
+			QMdiSubWindow* subWindow = ui.mdiArea->addSubWindow(data->canvas.get());
+			subWindow->setWindowTitle(tabName(fileInfo));
+			subWindow->show();
+		}
 	};
 	QObject::connect(ui.actionNew, &QAction::triggered, [&]{
 		openModelForEditing(documents.newModel());
@@ -411,18 +451,14 @@
 		}
 	});
 	QObject::connect(ui.actionQuit, &QAction::triggered, &mainWindow, &QMainWindow::close);
-	QObject::connect(ui.actionAdjustGridToView, &QAction::triggered, [&ui]{
-		EditorTabWidget* tab = currentTabWidget(&ui);
-		if (tab != nullptr)
-		{
-			adjustGridToView(tab->canvas);
+	QObject::connect(ui.actionAdjustGridToView, &QAction::triggered, [&]{
+		if (ModelData* data = currentModelData(&ui, &documents)) {
+			adjustGridToView(data->canvas.get());
 		}
 	});
 	QObject::connect(ui.actionClose, &QAction::triggered, [&ui, &documents]{
-		EditorTabWidget* tab = currentTabWidget(&ui);
-		if (tab != nullptr)
-		{
-			closeDocument(&documents, tab);
+		if (ModelData* data = currentModelData(&ui, &documents)) {
+			// TODO
 		}
 	});
 	const auto save = [&](ModelId modelId){
@@ -442,7 +478,7 @@
 		}
 	};
 	const auto actionSaveAs = [&]{
-		const std::optional<ModelId> modelId = findCurrentModelId(&ui, &documents);
+		const std::optional<ModelId> modelId = findCurrentModelId(&ui);
 		if (modelId.has_value())
 		{
 			const QString* pathPtr = documents.modelPath(*modelId);
@@ -467,40 +503,37 @@
 	};
 	QObject::connect(ui.actionSaveAs, &QAction::triggered, actionSaveAs);
 	QObject::connect(ui.actionSave, &QAction::triggered, [&]{
-		if (currentTabWidget(&ui) != nullptr) {
-			const std::optional<ModelId> modelId = findCurrentModelId(&ui, &documents);
-			if (modelId.has_value()) {
-				const QString* path = documents.modelPath(*modelId);
-				if (path == nullptr or path->isEmpty()) {
-					actionSaveAs();
-				}
-				else {
-					save(*modelId);
-				}
+		const std::optional<ModelId> modelId = findCurrentModelId(&ui);
+		if (modelId.has_value()) {
+			const QString* path = documents.modelPath(*modelId);
+			if (path == nullptr or path->isEmpty()) {
+				actionSaveAs();
+			}
+			else {
+				save(*modelId);
 			}
 		}
 	});
 	QObject::connect(ui.actionDelete, &QAction::triggered, [&]{
-		EditorTabWidget* tab = currentTabWidget(&ui);
-		if (tab != nullptr) {
+		if (Model* model = currentModelBody(&ui, &documents)) {
 			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});
+				executeAction(model, DeleteFromModel{.position = row});
 			}
 		}
 	});
 	QObject::connect(ui.actionDrawAxes, &QAction::triggered, [&](bool drawAxes){
 		renderPreferences.drawAxes = drawAxes;
 		saveSettings();
-		updateRenderPreferences(&ui, &renderPreferences);
+		updateRenderPreferences(&ui, &renderPreferences, &documents);
 	});
 	for (auto data : ::renderStyleButtons) {
 		QAction* action = data.memberInstance(&ui);
 		QObject::connect(action, &QAction::triggered, [&, data]{
 			renderPreferences.style = data.payload;
 			saveSettings();
-			updateRenderPreferences(&ui, &renderPreferences);
+			updateRenderPreferences(&ui, &renderPreferences, &documents);
 		});
 	}
 	const auto checkEditingModeAction = [&ui](EditingMode mode) {
@@ -511,24 +544,22 @@
 	initializeTools(&ui, &mainWindow);
 	for (QAction* action : ui.editingModesToolBar->actions()) {
 		QObject::connect(action, &QAction::triggered, [&, action]{
-			EditorTabWidget* tab = currentTabWidget(&ui);
-			if (tab != nullptr) {
+			if (ModelData* data = currentModelData(&ui, &documents)) {
 				const EditingMode mode = action->data().value<EditingMode>();
-				tab->setEditMode(mode);
+				data->tools->setEditMode(mode);
 				checkEditingModeAction(mode);
 			}
 		});
 	}
 	QObject::connect(ui.mdiArea, &QMdiArea::subWindowActivated,
 	[&](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);
+		ModelSubWindow* modelSubWindow = qobject_cast<ModelSubWindow*>(subWindow);
+		if (modelSubWindow != nullptr) {
+			if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) {
+				checkEditingModeAction(data->tools->currentEditingMode());
+				if (data->itemSelectionModel != nullptr) {
+					ui.modelListView->setModel(data->model);
+					ui.modelListView->setSelectionModel(data->itemSelectionModel.get());
 				}
 			}
 		}
@@ -536,7 +567,7 @@
 	mainWindow.setWindowTitle(title());
 	mainWindow.restoreGeometry(settings.mainWindowGeometry());
 	restoreSettings();
-	updateRenderPreferences(&ui, &renderPreferences);
+	updateRenderPreferences(&ui, &renderPreferences, &documents);
 	mainWindow.show();
 	const int result = app.exec();
 	saveSettings();

mercurial