src/mainwindow.cpp

changeset 201
5d201ee4a9c3
parent 200
ca23936b455b
child 354
91053052bb28
--- a/src/mainwindow.cpp	Mon Jun 06 22:01:22 2022 +0300
+++ b/src/mainwindow.cpp	Tue Jun 07 01:37:26 2022 +0300
@@ -15,564 +15,3 @@
  *  You should have received a copy of the GNU General Public License
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
-#include <QLabel>
-#include <QVBoxLayout>
-#include <QCloseEvent>
-#include <QFileDialog>
-#include <QMessageBox>
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-#include "settingseditor/settingseditor.h"
-#include "version.h"
-#include "document.h"
-#include "uiutilities.h"
-#include "widgets/colorselectdialog.h"
-
-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 },
-};
-
-class A : public QSettings
-{
-	using QSettings::QSettings;
-};
-
-MainWindow::MainWindow(QWidget *parent) :
-	QMainWindow{parent},
-	ui{std::make_unique<Ui_MainWindow>()},
-	documents{this},
-	settings{},
-	libraries{this}
-{
-	this->ui->setupUi(this);
-	defaultKeyboardShortcuts = uiutilities::makeKeySequenceMap(uiutilities::collectActions(this));
-	connect(ui->actionNew, &QAction::triggered, this, &MainWindow::newModel);
-	connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openModel);
-	connect(ui->actionQuit, &QAction::triggered, this, &QMainWindow::close);
-	connect(ui->actionSettingsEditor, &QAction::triggered, this, &MainWindow::runSettingsEditor);
-	connect(ui->actionAdjustGridToView, &QAction::triggered, [&]()
-	{
-		if (this->currentDocument() != nullptr)
-		{
-			adjustGridToView(this->currentDocument()->canvas);
-		}
-	});
-	connect(this->ui->actionSave, &QAction::triggered,
-		this, &MainWindow::actionSave);
-	connect(this->ui->actionSaveAs, &QAction::triggered,
-		this, &MainWindow::actionSaveAs);
-	connect(this->ui->actionClose, &QAction::triggered, this, &MainWindow::actionClose);
-	connect(this->ui->actionDelete, &QAction::triggered, this, &MainWindow::actionDelete);
-	connect(this->ui->actionInvert, &QAction::triggered, this, &MainWindow::actionInvert);
-	connect(this->ui->tabs, &QTabWidget::tabCloseRequested, this, &MainWindow::handleTabCloseButton);
-	for (auto data : ::renderStyleButtons)
-	{
-		QAction* action = data.memberInstance(this->ui.get());
-		connect(action, &QAction::triggered, [this, data]()
-		{
-			this->setRenderStyle(data.payload);
-		});
-	}
-	connect(this->ui->actionDrawAxes, &QAction::triggered, this, &MainWindow::setDrawAxes);
-	this->updateTitle();
-	this->restoreStartupSettings();
-	this->restoreSettings();
-	this->updateRenderPreferences();
-	this->newModel();
-}
-
-// MainWindow needs a destructor even if it is empty because otherwise the destructor of the
-// std::unique_ptr is resolved in the header file, where it will complain about Ui_MainWindow
-// being incomplete.
-MainWindow::~MainWindow()
-{
-}
-
-void MainWindow::newModel()
-{
-	this->openModelForEditing(documents.newModel());
-}
-
-void MainWindow::openModel()
-{
-	const QString path = QFileDialog::getOpenFileName(
-		this,
-		tr("Open model"),
-		"",
-		tr("LDraw models (*.ldr *.dat)"));
-	if (not path.isEmpty())
-	{
-		this->openModelFromPath(path);
-	}
-}
-
-void MainWindow::openModelFromPath(const QString& path)
-{
-	QString errorString;
-	QTextStream errorStream{&errorString};
-	std::optional<ModelId> modelIdOpt = this->documents.openModel(
-		path,
-		errorStream,
-		DocumentManager::OpenType::ManuallyOpened);
-	if (modelIdOpt.has_value())
-	{
-		const ModelId modelId = modelIdOpt.value();
-		this->documents.loadDependenciesForModel(modelId, path, this->libraries, errorStream);
-		if (not errorString.isEmpty())
-		{
-			QMessageBox::warning(
-				this,
-				tr("Problem loading references"),
-				errorString);
-		}
-		this->openModelForEditing(modelId);
-		this->addRecentlyOpenedFile(path);
-	}
-	else
-	{
-		QMessageBox::critical(
-			this,
-			tr("Problem opening file"),
-			utility::format(
-				tr("Could not open %1: %2"),
-				path,
-				errorString));
-	}
-}
-
-/**
- * @brief Changes the application language to the specified language
- * @param localeCode Code of the locale to translate to
- */
-void MainWindow::changeLanguage(QString localeCode)
-{
-	if (not localeCode.isEmpty() and localeCode != this->currentLanguage)
-	{
-		this->currentLanguage = localeCode;
-		if (localeCode == "system")
-		{
-			localeCode = QLocale::system().name();
-		}
-		QLocale::setDefault({localeCode});
-		qApp->removeTranslator(&this->translator);
-		const bool loadSuccessful = this->translator.load(pathToTranslation(localeCode));
-		if (loadSuccessful)
-		{
-			qApp->installTranslator(&this->translator);
-		}
-	}
-}
-
-void MainWindow::addRecentlyOpenedFile(const QString& path)
-{
-	this->recentlyOpenedFiles.removeAll(path);
-	this->recentlyOpenedFiles.insert(0, path);
-	while (this->recentlyOpenedFiles.size() > maxRecentlyOpenedFiles)
-	{
-		this->recentlyOpenedFiles.removeLast();
-	}
-	this->saveSettings();
-	this->updateRecentlyOpenedDocumentsMenu();
-}
-
-void MainWindow::openModelForEditing(const ModelId modelId)
-{
-	EditorTabWidget* document = new EditorTabWidget{
-		this->documents.getModelById(modelId),
-		&this->documents,
-		this->colorTable,
-	};
-	document->canvas->setRenderPreferences(this->renderPreferences);
-	connect(document, &EditorTabWidget::newStatusText, [&](const QString& newStatusText)
-	{
-		this->statusBar()->showMessage(newStatusText);
-	});
-	const QFileInfo fileInfo{*this->documents.modelPath(modelId)};
-	QString tabName = fileInfo.baseName();
-	if (tabName.isEmpty())
-	{
-		tabName = tr("<unnamed>");
-	}
-	this->ui->tabs->addTab(document, tabName);
-	this->ui->tabs->setCurrentWidget(document);
-	document->restoreSplitterState(this->documentSplitterState);
-}
-
-void MainWindow::runSettingsEditor()
-{
-	SettingsEditor settingsEditor{&this->settings, this->defaultKeyboardShortcuts, this};
-	const int result = settingsEditor.exec();
-	if (result == QDialog::Accepted)
-	{
-		this->restoreSettings();
-	}
-}
-
-EditorTabWidget* MainWindow::currentDocument()
-{
-	return qobject_cast<EditorTabWidget*>(this->ui->tabs->currentWidget());
-}
-
-const EditorTabWidget* MainWindow::currentDocument() const
-{
-	return qobject_cast<const EditorTabWidget*>(this->ui->tabs->currentWidget());
-}
-
-void MainWindow::handleDocumentSplitterChange()
-{
-	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);
-	}
-}
-
-void MainWindow::updateRecentlyOpenedDocumentsMenu()
-{
-	this->ui->menuRecentFiles->clear();
-	for (const QString& path : this->recentlyOpenedFiles)
-	{
-		QAction* action = new QAction{path, this};
-		action->setData(path);
-		this->ui->menuRecentFiles->addAction(action);
-		connect(action, &QAction::triggered, this, &MainWindow::openRecentFile);
-	}
-}
-
-void MainWindow::openRecentFile()
-{
-	QAction* action = qobject_cast<QAction*>(this->sender());
-	if (action != nullptr)
-	{
-		const QString path = action->data().toString();
-		this->openModelFromPath(path);
-	}
-}
-
-void MainWindow::setRenderStyle(gl::RenderStyle renderStyle)
-{
-	this->renderPreferences.style = renderStyle;
-	this->saveSettings();
-	this->updateRenderPreferences();
-}
-
-void MainWindow::setDrawAxes(bool drawAxes)
-{
-	this->renderPreferences.drawAxes = drawAxes;
-	this->saveSettings();
-	this->updateRenderPreferences();
-}
-
-/**
- * @brief Handles the "Save" (Ctrl+S) action
- */
-void MainWindow::actionSave()
-{
-	if (this->currentDocument() != nullptr)
-	{
-		const std::optional<ModelId> modelId = this->findCurrentModelId();
-		if (modelId.has_value())
-		{
-			const QString* path = this->documents.modelPath(*modelId);
-			if (path == nullptr or path->isEmpty())
-			{
-				this->actionSaveAs();
-			}
-			else
-			{
-				QString error;
-				QTextStream errorStream{&error};
-				const bool succeeded = this->documents.saveModel(*modelId, errorStream);
-				if (not succeeded)
-				{
-					QMessageBox::critical(this, tr("Save error"), error);
-				}
-				else
-				{
-					this->addRecentlyOpenedFile(*path);
-				}
-			}
-		}
-	}
-}
-
-/**
- * @brief Handles the "Save as…" (Ctrl+Shift+S) action
- */
-void MainWindow::actionSaveAs()
-{
-	if (this->currentDocument() != nullptr)
-	{
-		const std::optional<ModelId> modelId = this->findCurrentModelId();
-		if (modelId.has_value())
-		{
-			const QString* pathPtr = this->documents.modelPath(*modelId);
-			QString defaultPath = (pathPtr != nullptr) ? *pathPtr : "";
-			const QString newPath = QFileDialog::getSaveFileName(
-				this,
-				tr("Save as…"),
-				QFileInfo{defaultPath}.absoluteDir().path(), 
-				tr("LDraw files (*.ldr *dat);;All files (*)")
-			);
-			if (not newPath.isEmpty())
-			{
-				QString error;
-				QTextStream errorStream{&error};
-				this->documents.setModelPath(*modelId, newPath, this->libraries, errorStream);
-				this->ui->tabs->setTabText(this->ui->tabs->currentIndex(), QFileInfo{newPath}.fileName());
-				this->actionSave();
-			}
-		}
-	}
-}
-
-/**
- * @brief Handles the "Close" (Ctrl+W) action
- */
-void MainWindow::actionClose()
-{
-	if (this->currentDocument() != nullptr)
-	{
-		this->closeDocument(this->currentDocument());
-	}
-}
-
-/**
- * @brief Handles the "Delete" (Del) action
- */
-void MainWindow::actionDelete()
-{
-	/*
-	EditorTabWidget* document = this->currentDocument();
-	if (document != nullptr)
-	{
-		std::unique_ptr<ModelEditor> modelEditor = document->editModel();
-		QSet<ldraw::id_t> ids = document->selectedObjects(); // copy
-		for (const ldraw::id_t id : ids)
-		{
-			const QModelIndex index = modelEditor->model().find(id);
-			if (index.isValid())
-			{
-				modelEditor->remove(index.row());
-			}
-		}
-	}
-	*/
-}
-
-/**
- * @brief Handles the "Invert" action
- */
-void MainWindow::actionInvert()
-{
-	/*
-	EditorTabWidget* document = this->currentDocument();
-	if (document != nullptr)
-	{
-		// TODO: simplify
-		std::unique_ptr<ModelEditor> modelEditor = document->editModel();
-		const std::optional<ModelId> modelId = this->documents.findIdForModel(&modelEditor->model());
-		if (modelId.has_value())
-		{
-			ldraw::GetPolygonsContext context = {
-				.modelId = modelId.value(),
-				.documents = &this->documents,
-			};
-			for (const ldraw::id_t id : document->selectedObjects())
-			{
-				modelEditor->modifyObject(id, [&context](ldraw::Object* object)
-				{
-					object->invert(&context);
-				});
-			}
-		}
-	}
-	*/
-}
-
-/**
- * @brief Removes the document at the specified tab index
- * @param index
- */
-void MainWindow::handleTabCloseButton(int tabIndex)
-{
-	if (tabIndex >= 0 and tabIndex < this->ui->tabs->count())
-	{
-		EditorTabWidget* document = qobject_cast<EditorTabWidget*>(this->ui->tabs->widget(tabIndex));
-		if (document != nullptr)
-		{
-			this->closeDocument(document);
-		}
-	}
-}
-
-/**
- * @brief Closes the specified document
- * @param document
- */
-void MainWindow::closeDocument(EditorTabWidget *document)
-{
-	std::optional<ModelId> modelId = this->documents.findIdForModel(document->model);
-	if (modelId.has_value())
-	{
-		this->documents.closeDocument(modelId.value());
-		delete document;
-	}
-}
-
-std::optional<ModelId> MainWindow::findCurrentModelId() const
-{
-	const EditorTabWidget* document = this->currentDocument();
-	if (document != nullptr)
-	{
-		return this->documents.findIdForModel(document->model);
-	}
-	else
-	{
-		return {};
-	}
-}
-
-void MainWindow::changeEvent(QEvent* event)
-{
-	if (event != nullptr)
-	{
-		switch (event->type())
-		{
-		case QEvent::LanguageChange:
-			this->ui->retranslateUi(this);
-			break;
-		default:
-			break;
-		}
-	}
-	QMainWindow::changeEvent(event);
-}
-
-/**
- * @brief Handles closing the main window
- * @param event Event information
- */
-void MainWindow::closeEvent(QCloseEvent* event)
-{
-	saveSettings();
-	event->accept();
-}
-
-/**
- * @brief Updates the title of the main window so to contain the app's name
- * and version as well as the open document name.
- */
-void MainWindow::updateTitle()
-{
-	QString title = ::appName;
-	title += " ";
-	title += fullVersionString();
-	setWindowTitle(title);
-}
-
-void MainWindow::updateRenderPreferences()
-{
-	for (int i = 0; i < this->ui->tabs->count(); i += 1)
-	{
-		EditorTabWidget* document = qobject_cast<EditorTabWidget*>(this->ui->tabs->widget(i));
-		if (document != nullptr)
-		{
-			document->canvas->setRenderPreferences(this->renderPreferences);
-		}
-	}
-	for (auto data : ::renderStyleButtons)
-	{
-		QAction* action = data.memberInstance(this->ui.get());
-		action->setChecked(this->renderPreferences.style == data.payload);
-	}
-	this->ui->actionDrawAxes->setChecked(this->renderPreferences.drawAxes);
-}
-
-/**
- * @brief Stores the settings of the main window, storing geometry, etc
- */
-void MainWindow::saveSettings()
-{
-	this->settings.setMainWindowGeometry(this->saveGeometry());
-	this->settings.setRecentFiles(this->recentlyOpenedFiles);
-	this->settings.setMainSplitterState(this->documentSplitterState);
-	this->settings.setRenderStyle(static_cast<int>(this->renderPreferences.style));
-	this->settings.setDrawAxes(this->renderPreferences.drawAxes);
-	this->libraries.storeToSettings(&this->settings);
-}
-
-void MainWindow::restoreStartupSettings()
-{
-	this->restoreGeometry(this->settings.mainWindowGeometry());
-}
-
-/**
- * @brief Restores saved settings relating to the main window
- */
-void MainWindow::restoreSettings()
-{
-	this->recentlyOpenedFiles = this->settings.recentFiles();
-	this->documentSplitterState = this->settings.mainSplitterState();
-	this->renderPreferences.style = static_cast<gl::RenderStyle>(this->settings.renderStyle());
-	this->renderPreferences.mainColor = this->settings.mainColor();
-	this->renderPreferences.backgroundColor = this->settings.backgroundColor();
-	this->renderPreferences.lineThickness = this->settings.lineThickness();
-	this->renderPreferences.lineAntiAliasing = this->settings.lineAntiAliasing();
-	this->renderPreferences.selectedColor = this->settings.selectedColor();
-	this->renderPreferences.drawAxes = this->settings.drawAxes();
-	const QString systemLocale = QLocale::system().name();
-	const QVariant defaultLocale = this->settings.locale();
-	this->changeLanguage(defaultLocale.toString());
-	this->libraries.restoreFromSettings(&this->settings);
-	this->updateRecentlyOpenedDocumentsMenu();
-	this->loadColors();
-	this->updateRenderPreferences();
-}
-
-QString MainWindow::pathToTranslation(const QString& localeCode)
-{
-	QDir dir {":/locale"};
-	return dir.filePath(localeCode + ".qm");
-}
-
-void MainWindow::loadColors()
-{
-	QTextStream errors;
-	this->colorTable = this->libraries.loadColorTable(errors);
-}
-
-void MainWindow::keyReleaseEvent(QKeyEvent* /*event*/)
-{
-	/*
-	Document* document = this->currentDocument();
-	if (document != nullptr)
-	{
-		document->handleKeyPress(event);
-	}
-	*/
-}

mercurial