src/main.cpp

changeset 354
91053052bb28
parent 353
c229d38f04c6
child 355
e81f4ad53efd
--- a/src/main.cpp	Sat Apr 08 16:12:12 2023 +0300
+++ b/src/main.cpp	Sat Apr 08 16:41:40 2023 +0300
@@ -8,12 +8,12 @@
 #include <QStackedWidget>
 #include <QTranslator>
 #include <ui_about.h>
-#include <ui_mainwindow.h>
 #include "src/gl/partrenderer.h"
 #include "src/layers/axeslayer.h"
 #include "src/layers/edittools.h"
 #include "src/layers/gridlayer.h"
 #include "src/ldrawalgorithm.h"
+#include "src/mainwindow.h"
 #include "src/messagelog.h"
 #include "src/settings.h"
 #include "src/settingseditor/settingseditor.h"
@@ -90,24 +90,6 @@
 #endif
 }
 
-template<typename BaseType, typename MemberType, typename DataType>
-struct MemberData
-{
-	std::size_t member;
-	DataType payload;
-	constexpr MemberType memberInstance(BaseType* instance) const
-	{
-		return *reinterpret_cast<MemberType*>(reinterpret_cast<char*>(instance) + this->member);
-	}
-};
-
-static constexpr MemberData<Ui_MainWindow, QAction*, gl::RenderStyle> renderStyleButtons[] = {
-	{ offsetof(Ui_MainWindow, actionRenderStyleNormal), gl::RenderStyle::Normal },
-	{ offsetof(Ui_MainWindow, actionRenderStyleBfc), gl::RenderStyle::BfcRedGreen },
-	{ offsetof(Ui_MainWindow, actionRenderStyleRandom), gl::RenderStyle::RandomColors },
-	{ offsetof(Ui_MainWindow, actionRenderStylePickScene), gl::RenderStyle::PickScene },
-};
-
 static std::optional<ModelId> openModelFromPath(
 	const QString& path,
 	const LibrariesModel* libraries,
@@ -153,13 +135,13 @@
 	return documents->findPayload<ModelData>(modelId);
 }
 
-static ModelSubWindow* currentModelSubWindow(Ui_MainWindow* ui)
+static ModelSubWindow* currentModelSubWindow(MainWindow* ui)
 {
 	auto* w = ui->mdiArea->activeSubWindow();
 	return qobject_cast<ModelSubWindow*>(w);
 }
 
-static ModelData* currentModelData(Ui_MainWindow* ui, const DocumentManager* documents)
+static ModelData* currentModelData(MainWindow* ui, const DocumentManager* documents)
 {
 	if (auto* const activeSubWindow = currentModelSubWindow(ui)) {
 		return findModelData(documents, activeSubWindow->modelId);
@@ -169,7 +151,7 @@
 	}
 }
 
-static std::optional<ModelId> findCurrentModelId(Ui_MainWindow* ui)
+static std::optional<ModelId> findCurrentModelId(MainWindow* ui)
 {
 	ModelSubWindow* activeSubWindow = qobject_cast<ModelSubWindow*>(ui->mdiArea->activeSubWindow());
 	if (activeSubWindow != nullptr) {
@@ -180,7 +162,7 @@
 	}
 }
 
-static QString title(Ui_MainWindow* ui)
+static QString title(MainWindow* ui)
 {
 	QMdiSubWindow* subWindow = ui->mdiArea->activeSubWindow();
 	QString titlestring;
@@ -238,7 +220,7 @@
 }
 
 static void updateRenderPreferences(
-	Ui_MainWindow* ui,
+	MainWindow* ui,
 	const gl::RenderPreferences* renderPreferences,
 	const DocumentManager* documents)
 {
@@ -248,10 +230,7 @@
 			data->canvas->setLayerEnabled(data->axesLayer.get(), renderPreferences->drawAxes);
 		}
 	});
-	for (auto data : ::renderStyleButtons) {
-		QAction* action = data.memberInstance(ui);
-		action->setChecked(renderPreferences->style == data.payload);
-	}
+	ui->setRenderStyle(renderPreferences->style);
 	ui->actionDrawAxes->setChecked(renderPreferences->drawAxes);
 	ui->actionWireframe->setChecked(renderPreferences->wireframe);
 }
@@ -275,7 +254,7 @@
 	CircleToolOptionsWidget* circleToolOptions;
 };
 
-static void initializeTools(Ui_MainWindow* ui, ToolWidgets* toolWidgets, QWidget* parent)
+static void initializeTools(MainWindow* ui, ToolWidgets* toolWidgets, QWidget* parent)
 {
 	const struct
 	{
@@ -405,8 +384,7 @@
 	doQtRegistrations();
 	QApplication app{argc, argv};
 	QApplication::setWindowIcon(QIcon{":/icons/appicon.png"});
-	QMainWindow mainWindow;
-	Ui_MainWindow ui;
+	MainWindow mainWindow;
 	DocumentManager documents;
 	QString currentLanguage = "en";
 	QTranslator translator{&mainWindow};
@@ -416,12 +394,11 @@
 	gl::RenderPreferences renderPreferences;
 	MessageLog messageLog;
 	Signal settingsChanged;
-	ui.setupUi(&mainWindow);
 	ToolWidgets toolWidgets{
 		.circleToolOptions = new CircleToolOptionsWidget{&mainWindow},
 	};
-	const auto updateTitle = [&ui, &mainWindow]{
-		mainWindow.setWindowTitle(title(&ui));
+	const auto updateTitle = [&mainWindow]{
+		mainWindow.setWindowTitle(title(&mainWindow));
 	};
 	const uiutilities::KeySequenceMap defaultKeyboardShortcuts =
 		uiutilities::makeKeySequenceMap(uiutilities::collectActions(&mainWindow));
@@ -447,8 +424,7 @@
 		&mainWindow,
 		&messageLog,
 		&renderPreferences,
-		&settingsChanged,
-		&ui]
+		&settingsChanged]
 		(const ModelId modelId)
 	{
 		QTextDocument* model = documents.getModelById(modelId);
@@ -514,7 +490,7 @@
 				&QWidget::setCursor);
 			data->tools->setEditMode(SelectMode);
 			const QFileInfo fileInfo{*documents.modelPath(modelId)};
-			auto* const subWindow = createSubWindow<ModelSubWindow>(ui.mdiArea, modelId);
+			auto* const subWindow = createSubWindow<ModelSubWindow>(mainWindow.mdiArea, modelId);
 			subWindow->setMinimumSize({96, 96});
 			subWindow->resize({320, 200});
 			subWindow->setWidget(data->canvas.get());
@@ -527,11 +503,10 @@
 		&libraries,
 		&mainWindow,
 		&openModelForEditing,
-		&recentlyOpenedFiles,
-		&ui]
+		&recentlyOpenedFiles]
 	{
-		rebuildRecentFilesMenu(ui.menuRecentFiles, recentlyOpenedFiles, &mainWindow);
-		for (QAction* action : ui.menuRecentFiles->actions()) {
+		rebuildRecentFilesMenu(mainWindow.menuRecentFiles, recentlyOpenedFiles, &mainWindow);
+		for (QAction* action : mainWindow.menuRecentFiles->actions()) {
 			QString path = action->data().toString();
 			QObject::connect(
 				action,
@@ -554,7 +529,6 @@
 		&recentlyOpenedFiles,
 		&renderPreferences,
 		&settingsChanged,
-		&ui,
 		&updateRecentlyOpenedDocumentsMenu]
 	{
 		recentlyOpenedFiles = setting<Setting::RecentFiles>();
@@ -562,9 +536,9 @@
 		libraries.restoreFromSettings();
 		updateRecentlyOpenedDocumentsMenu();
 		colorTable = loadColors(&libraries);
-		updateRenderPreferences(&ui, &renderPreferences, &documents);
-		ui.mdiArea->setViewMode(setting<Setting::ViewMode>());
-		ui.retranslateUi(&mainWindow);
+		updateRenderPreferences(&mainWindow, &renderPreferences, &documents);
+		mainWindow.mdiArea->setViewMode(setting<Setting::ViewMode>());
+		mainWindow.retranslateUi(&mainWindow);
 		mainWindow.setToolButtonStyle(setting<Setting::ToolButtonStyle>());
 		settingsChanged.emit();
 	};
@@ -584,12 +558,12 @@
 		saveSettings();
 		updateRecentlyOpenedDocumentsMenu();
 	};
-	QObject::connect(ui.actionNew, &QAction::triggered,
+	QObject::connect(mainWindow.actionNew, &QAction::triggered,
 		[&documents, &openModelForEditing]{
 			openModelForEditing(documents.newModel());
 		}
 	);
-	QObject::connect(ui.actionOpen, &QAction::triggered,
+	QObject::connect(mainWindow.actionOpen, &QAction::triggered,
 		[&addRecentlyOpenedFile, &documents, &libraries, &mainWindow, &openModelForEditing]
 		{
 			const QString path = getOpenModelPath(&mainWindow);
@@ -603,16 +577,16 @@
 			}
 		}
 	);
-	QObject::connect(ui.actionSettingsEditor, &QAction::triggered, [&defaultKeyboardShortcuts, &restoreSettings, &settingsChanged, &ui]{
-		if (ui.mdiArea->findChildren<SettingsEditor*>().isEmpty()) {
-			auto* const settingsEditor = createSubWindow<SettingsEditor>(ui.mdiArea, defaultKeyboardShortcuts);
+	QObject::connect(mainWindow.actionSettingsEditor, &QAction::triggered, [&defaultKeyboardShortcuts, &restoreSettings, &settingsChanged, &mainWindow]{
+		if (mainWindow.mdiArea->findChildren<SettingsEditor*>().isEmpty()) {
+			auto* const settingsEditor = createSubWindow<SettingsEditor>(mainWindow.mdiArea, defaultKeyboardShortcuts);
 			QObject::connect(&settingsChanged, &Signal::triggered, settingsEditor, &SettingsEditor::loadSettings);
 			QObject::connect(settingsEditor, &SettingsEditor::settingsChanged, restoreSettings);
 			settingsEditor->setAttribute(Qt::WA_DeleteOnClose);
 			settingsEditor->show();
 		}
 	});
-	QObject::connect(ui.actionQuit, &QAction::triggered, &mainWindow, &QMainWindow::close);
+	QObject::connect(mainWindow.actionQuit, &QAction::triggered, &mainWindow, &QMainWindow::close);
 #if 0
 	QObject::connect(ui.actionAdjustGridToView, &QAction::triggered, [&]{
 		if (ModelData* data = currentModelData(&ui, &documents)) {
@@ -620,29 +594,29 @@
 		}
 	});
 #endif
-	QObject::connect(ui.actionClose, &QAction::triggered, [&ui, &documents]{
-		if (ModelData* data = currentModelData(&ui, &documents)) {
+	QObject::connect(mainWindow.actionClose, &QAction::triggered, [&mainWindow, &documents]{
+		if (ModelData* data = currentModelData(&mainWindow, &documents)) {
 			// TODO
 		}
 	});
-	const auto save = [&addRecentlyOpenedFile, &documents, &mainWindow](ModelId modelId){
+	const auto save = [&addRecentlyOpenedFile, &mainWindow](DocumentManager* documents, ModelId modelId){
 		QString error;
 		QTextStream errorStream{&error};
-		const bool succeeded = documents.saveModel(modelId, errorStream);
+		const bool succeeded = documents->saveModel(modelId, errorStream);
 		if (not succeeded)
 		{
 			QMessageBox::critical(&mainWindow, QObject::tr("Save error"), error);
 		}
 		else
 		{
-			const QString* pathPtr = documents.modelPath(modelId);
+			const QString* pathPtr = documents->modelPath(modelId);
 			if (pathPtr != nullptr) {
 				addRecentlyOpenedFile(*pathPtr);
 			}
 		}
-	};;
-	const auto actionSaveAs = [&documents, &libraries, &mainWindow, &save, &ui]{
-		const std::optional<ModelId> modelId = findCurrentModelId(&ui);
+	};
+	const auto actionSaveAs = [&documents, &libraries, &mainWindow, &save]{
+		const std::optional<ModelId> modelId = findCurrentModelId(&mainWindow);
 		if (modelId.has_value())
 		{
 			const QString* pathPtr = documents.modelPath(*modelId);
@@ -657,88 +631,91 @@
 				QString error;
 				QTextStream errorStream{&error};
 				documents.setModelPath(*modelId, newPath, libraries, errorStream);
-				QMdiSubWindow* const subWindow = ui.mdiArea->currentSubWindow();
+				QMdiSubWindow* const subWindow = mainWindow.mdiArea->currentSubWindow();
 				if (subWindow != nullptr) {
 					subWindow->setWindowTitle(tabName(QFileInfo{newPath}));
 				}
-				save(*modelId);
+				save(&documents, *modelId);
 			}
 		}
 	};
-	QObject::connect(ui.actionSaveAs, &QAction::triggered, actionSaveAs);
-	QObject::connect(ui.actionSave, &QAction::triggered, [
+	QObject::connect(mainWindow.actionSaveAs, &QAction::triggered, actionSaveAs);
+	QObject::connect(mainWindow.actionSave, &QAction::triggered, [
 		&actionSaveAs,
 		&documents,
 		&save,
-		&ui]
+		&mainWindow]
 	{
-		const std::optional<ModelId> modelId = findCurrentModelId(&ui);
+		const std::optional<ModelId> modelId = findCurrentModelId(&mainWindow);
 		if (modelId.has_value()) {
 			const QString* path = documents.modelPath(*modelId);
 			if (path == nullptr or path->isEmpty()) {
 				actionSaveAs();
 			}
 			else {
-				save(*modelId);
+				save(&documents, *modelId);
 			}
 		}
 	});
-	QObject::connect(ui.actionDrawAxes, &QAction::triggered, [
+	QObject::connect(mainWindow.actionDrawAxes, &QAction::triggered, [
 		&documents,
 		&renderPreferences,
 		&saveSettings,
-		&ui]
+		&mainWindow]
 		(bool drawAxes)
 	{
 		renderPreferences.drawAxes = drawAxes;
 		saveSettings();
-		updateRenderPreferences(&ui, &renderPreferences, &documents);
+		updateRenderPreferences(&mainWindow, &renderPreferences, &documents);
 	});
-	QObject::connect(ui.actionWireframe, &QAction::triggered, [
+	QObject::connect(mainWindow.actionWireframe, &QAction::triggered, [
 		&documents,
 		&renderPreferences,
 		&saveSettings,
-		&ui]
+		&mainWindow]
 		(bool enabled)
 	{
 		renderPreferences.wireframe = enabled;
 		saveSettings();
-		updateRenderPreferences(&ui, &renderPreferences, &documents);
+		updateRenderPreferences(&mainWindow, &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, &documents);
-		});
-	}
-	const auto checkEditingModeAction = [&ui, &documents](EditingMode mode) {
-		const bool hasDocument = currentModelData(&ui, &documents) != nullptr;
-		for (QAction* action : ui.editingModesToolBar->actions()) {
+	QObject::connect(&mainWindow, &MainWindow::renderStyleSelected, [
+		&documents,
+		&mainWindow,
+		&renderPreferences,
+		&saveSettings]
+		(gl::RenderStyle newStyle)
+	{
+		renderPreferences.style = newStyle;
+		saveSettings();
+		updateRenderPreferences(&mainWindow, &renderPreferences, &documents);
+	});
+	const auto checkEditingModeAction = [&mainWindow, &documents](EditingMode mode) {
+		const bool hasDocument = currentModelData(&mainWindow, &documents) != nullptr;
+		for (QAction* action : mainWindow.editingModesToolBar->actions()) {
 			action->setEnabled(hasDocument);
 			action->setChecked(hasDocument and action->data().value<EditingMode>() == mode);
 		}
 	};
-	initializeTools(&ui, &toolWidgets, &mainWindow);
-	for (QAction* action : ui.editingModesToolBar->actions()) {
+	initializeTools(&mainWindow, &toolWidgets, &mainWindow);
+	for (QAction* action : mainWindow.editingModesToolBar->actions()) {
 		QObject::connect(action, &QAction::triggered, [
 			action,
 			&checkEditingModeAction,
 			&documents,
-			&ui]
+			&mainWindow]
 		{
-			if (ModelData* data = currentModelData(&ui, &documents)) {
+			if (ModelData* data = currentModelData(&mainWindow, &documents)) {
 				const EditingMode mode = action->data().value<EditingMode>();
 				data->tools->setEditMode(mode);
 				checkEditingModeAction(mode);
 			}
 		});
 	}
-	QObject::connect(ui.mdiArea, &QMdiArea::subWindowActivated, [
+	QObject::connect(mainWindow.mdiArea, &QMdiArea::subWindowActivated, [
 		&checkEditingModeAction,
 		&documents,
-		&ui,
+		&mainWindow,
 		&updateTitle]
 		(QMdiSubWindow* subWindow)
 	{
@@ -746,42 +723,42 @@
 		if (modelSubWindow != nullptr) {
 			if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) {
 				checkEditingModeAction(data->tools->currentEditingMode());
-				ui.modelEdit->setDocument(data->model);
-				ui.modelEdit->setTextCursor(*data->textcursor);
+				mainWindow.modelEdit->setDocument(data->model);
+				mainWindow.modelEdit->setTextCursor(*data->textcursor);
 			}
 		}
 		else {
 			checkEditingModeAction(EditingMode::SelectMode);
 		}
-		ui.modelEdit->setEnabled(modelSubWindow != nullptr);
+		mainWindow.modelEdit->setEnabled(modelSubWindow != nullptr);
 		updateTitle();
 	});
-	ui.messageLog->setModel(&messageLog);
-	QObject::connect(ui.actionAboutQt, &QAction::triggered, &app, &QApplication::aboutQt);
+	mainWindow.messageLog->setModel(&messageLog);
+	QObject::connect(mainWindow.actionAboutQt, &QAction::triggered, &app, &QApplication::aboutQt);
 	QObject::connect(&documents, &DocumentManager::message, &messageLog, &MessageLog::addMessage);
-	QObject::connect(&messageLog, &MessageLog::rowsAboutToBeInserted, [&ui]{
-		const auto bar = ui.messageLog->verticalScrollBar();
-		ui.messageLog->setProperty("shouldAutoScroll", bar->value() == bar->maximum());
+	QObject::connect(&messageLog, &MessageLog::rowsAboutToBeInserted, [&mainWindow]{
+		const auto bar = mainWindow.messageLog->verticalScrollBar();
+		mainWindow.messageLog->setProperty("shouldAutoScroll", bar->value() == bar->maximum());
 	});
-	QObject::connect(&messageLog, &MessageLog::rowsInserted, [&ui]{
-		ui.messageLog->resizeRowsToContents();
-		if (ui.messageLog->property("shouldAutoScroll").toBool()) {
-			ui.messageLog->scrollToBottom();
+	QObject::connect(&messageLog, &MessageLog::rowsInserted, [&mainWindow]{
+		mainWindow.messageLog->resizeRowsToContents();
+		if (mainWindow.messageLog->property("shouldAutoScroll").toBool()) {
+			mainWindow.messageLog->scrollToBottom();
 		}
 	});
 	QObject::connect(
 		toolWidgets.circleToolOptions,
 		&CircleToolOptionsWidget::optionsChanged,
-		[&ui, &documents](const CircleToolOptions& options) {
-			if (ModelData* data = currentModelData(&ui, &documents)) {
+		[&mainWindow, &documents](const CircleToolOptions& options) {
+			if (ModelData* data = currentModelData(&mainWindow, &documents)) {
 				data->tools->setCircleToolOptions(options);
 			}
 		});
 	QObject::connect(
-		ui.actionMakeUnofficial,
+		mainWindow.actionMakeUnofficial,
 		&QAction::triggered,
-		[&documents, &ui]{
-			if (ModelData* data = currentModelData(&ui, &documents)) {
+		[&documents, &mainWindow]{
+			if (ModelData* data = currentModelData(&mainWindow, &documents)) {
 				QTextDocument* const model = data->model;
 				for (const ModelAction& action : ldraw::makeUnofficial(model)) {
 					executeAction(model, action);
@@ -789,27 +766,27 @@
 			}
 		});
 	QObject::connect(
-		ui.actionAbout,
+		mainWindow.actionAbout,
 		&QAction::triggered,
-		[&mainWindow, &ui]{
+		[&mainWindow]{
 			// Make sure that there's an OpenGL context active, otherwise
 			// we cannot obtain OpenGL information
-			if (ui.mdiArea->findChildren<ModelSubWindow*>().empty()) {
-				ui.actionNew->trigger();
+			if (mainWindow.mdiArea->findChildren<ModelSubWindow*>().empty()) {
+				mainWindow.actionNew->trigger();
 			}
 			about(&mainWindow);
 		}
 	);
 	QObject::connect(
-		ui.modelEdit,
+		mainWindow.modelEdit,
 		&QPlainTextEdit::textChanged,
-		[&documents, &libraries, &ui]{
-			if (ModelData* data = currentModelData(&ui, &documents)) {
+		[&documents, &libraries, &mainWindow]{
+			if (ModelData* data = currentModelData(&mainWindow, &documents)) {
 				documents.loadDependenciesForAllModels(libraries);
 				data->canvas->update();
 			}
 		});
-	mainWindow.tabifyDockWidget(ui.messageLogDock, ui.toolOptionsDock);
+	mainWindow.tabifyDockWidget(mainWindow.messageLogDock, mainWindow.toolOptionsDock);
 	mainWindow.restoreGeometry(setting<Setting::MainWindowGeometry>());
 	mainWindow.restoreState(setting<Setting::MainWindowState>());
 	// If a dock is made floating and the app is closed, the dock becomes invisible
@@ -818,8 +795,8 @@
 		dock->setVisible(true);
 	}
 	restoreSettings();
-	updateRenderPreferences(&ui, &renderPreferences, &documents);
-	ui.actionAbout->setText(ui.actionAbout->text().arg(CMAKE_PROJECT_NAME));
+	updateRenderPreferences(&mainWindow, &renderPreferences, &documents);
+	mainWindow.actionAbout->setText(mainWindow.actionAbout->text().arg(CMAKE_PROJECT_NAME));
 	updateTitle();
 	mainWindow.show();
 	const int result = app.exec();

mercurial