Sun, 19 Jan 2020 14:25:43 +0200
added license
/* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 - 2020 Teemu Piippo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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" 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); this->updateTitle(); this->restoreSettings(); this->newModel(); } 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}; QString modelName = this->documents.openModel(path, errorStream); if (not modelName.isEmpty()) { this->documents.loadDependenciesForModel(modelName, path, this->libraries, errorStream); if (not errorString.isEmpty()) { QMessageBox::warning( this, tr("Problem loading references"), errorString); } this->openModelForEditing(modelName); 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 QString& modelName) { Document* document = new Document{this->documents.findModelByName(modelName), &this->documents}; this->ui->tabs->addTab(document, modelName); this->ui->tabs->setCurrentWidget(document); document->restoreSplitterState(this->documentSplitterState); connect(document, &Document::splitterChanged, this, &MainWindow::handleDocumentSplitterChange); } void MainWindow::runSettingsEditor() { SettingsEditor settingsEditor{&this->settings, this->defaultKeyboardShortcuts, this}; const int result = settingsEditor.exec(); if (result == QDialog::Accepted) { this->restoreSettings(); } } void MainWindow::handleDocumentSplitterChange() { Document* currentDocument = qobject_cast<Document*>(this->ui->tabs->currentWidget()); if (currentDocument != nullptr) { this->documentSplitterState = currentDocument->saveSplitterState(); for (int i = 0; i < this->ui->tabs->count(); i += 1) { Document* document = qobject_cast<Document*>(this->ui->tabs->widget(i)); if (document != nullptr and document != currentDocument) { document->restoreSplitterState(this->documentSplitterState); } } this->settings.setValue("MainWindow/DocumentSplitterState", 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::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); } /** * @brief Stores the settings of the main window, storing geometry, etc */ void MainWindow::saveSettings() { this->settings.setValue("MainWindow/Geometry", this->saveGeometry()); this->settings.setValue("MainWindow/RecentlyOpened", this->recentlyOpenedFiles); this->settings.setValue("MainWindow/DocumentSplitterState", this->documentSplitterState); this->libraries.storeToSettings(&this->settings); } /** * @brief Restores saved settings relating to the main window */ void MainWindow::restoreSettings() { this->restoreGeometry(this->settings.value("MainWindow/Geometry").toByteArray()); this->recentlyOpenedFiles = this->settings.value("MainWindow/RecentlyOpened").toStringList(); this->documentSplitterState = this->settings.value("MainWindow/DocumentSplitterState").toByteArray(); const QString systemLocale = QLocale::system().name(); const QVariant defaultLocale = this->settings.value("locale", systemLocale); changeLanguage(defaultLocale.toString()); this->libraries.restoreFromSettings(&this->settings); this->updateRecentlyOpenedDocumentsMenu(); } QString MainWindow::pathToTranslation(const QString& localeCode) { QDir dir {":/locale"}; return dir.filePath(localeCode + ".qm"); }