Sun, 09 Apr 2023 16:27:22 +0300
Also connect up "Select all"
#include "src/mainwindow.h" #include "src/modelsubwindow.h" #include "src/version.h" #include <QTextBrowser> #include <QOpenGLWidget> #include <ui_about.h> #include "src/settings.h" static constexpr MemberData<MainWindow, QAction*, gl::RenderStyle> renderStyleButtons[] = { { offsetof(MainWindow, actionRenderStyleNormal), gl::RenderStyle::Normal }, { offsetof(MainWindow, actionRenderStyleBfc), gl::RenderStyle::BfcRedGreen }, { offsetof(MainWindow, actionRenderStyleRandom), gl::RenderStyle::RandomColors }, { offsetof(MainWindow, actionRenderStylePickScene), gl::RenderStyle::PickScene }, }; MainWindow::MainWindow(QWidget *parent) : QMainWindow{parent} { this->setupUi(this); for (const auto& memberData : ::renderStyleButtons) { QAction* action = memberData.memberInstance(this); const gl::RenderStyle newStyle = memberData.payload; QObject::connect(action, &QAction::triggered, [this, newStyle]{ Q_EMIT this->renderStyleSelected(newStyle); this->setRenderStyle(newStyle); }); } this->connect(this->actionAbout, &QAction::triggered, this, &MainWindow::showAboutDialog); this->connect(this->mdiArea, &QMdiArea::subWindowActivated, this, &MainWindow::updateTitle); this->gridMatrix->setValue(DEFAULT_GRID_MATRIX); this->tabifyDockWidget(this->messageLogDock, this->toolOptionsDock); this->restoreGeometry(setting<Setting::MainWindowGeometry>()); this->restoreState(setting<Setting::MainWindowState>()); // If a dock is made floating and the app is closed, the dock becomes invisible // after the restoreState call. So we make them visible again here. for (QDockWidget* dock : this->findChildren<QDockWidget*>()) { dock->setVisible(true); } this->actionAbout->setText(this->actionAbout->text().arg(CMAKE_PROJECT_NAME)); this->updateTitle(); this->show(); } void MainWindow::setRenderStyle(gl::RenderStyle style) { for (const auto& memberData : ::renderStyleButtons) { QAction* const action = memberData.memberInstance(this); const gl::RenderStyle buttonRenderStyle = memberData.payload; action->setChecked(style == buttonRenderStyle); } } static QStringList getGLExtensions(QWidget* parent) { // We need to have GL activated at least once in order to able to retrieve // GL extensions properly. To make sure this is the case, we create a // temporary, plain OpenGL widget. While it is active, we call glewInit(). // If this is not done, this function will crash. QOpenGLWidget glWidget{parent}; glWidget.show(); glewInit(); GLint numExtensions; glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); QStringList extensionsList; for (GLint i = 0; i < numExtensions; i++) { const GLubyte* ext = glGetStringi(GL_EXTENSIONS, i); extensionsList.push_back(reinterpret_cast<const char*>(ext)); } glWidget.hide(); return extensionsList; } void MainWindow::showAboutDialog() { QDialog dialog{this}; Ui_About ui; ui.setupUi(&dialog); const char* glVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION)); const QString extensions = getGLExtensions(this).join(" "); for (QTextBrowser* browser : dialog.findChildren<QTextBrowser*>()) { browser->setHtml( browser->toHtml() .replace("%APPNAME%", CMAKE_PROJECT_NAME) .replace("%COPYRIGHT%", COPYRIGHT) .replace("%QTVERSION%", qVersion()) .replace("%VERSION%", detailedVersionString(QLocale::LongFormat)) .replace("%REVDATE%", revisionDateString(QLocale::LongFormat)) .replace("%BUILDTYPE%", CMAKE_BUILD_TYPE) .replace("%COMPILER_ID%", CMAKE_CXX_COMPILER_ID) .replace("%COMPILER_VERSION%", CMAKE_CXX_COMPILER_VERSION) .replace("%COMPILER_FLAGS%", CMAKE_CXX_FLAGS) .replace("%COMPILER_CPU%", CMAKE_SYSTEM_PROCESSOR) .replace("%COMPILER_SYSTEM%", CMAKE_SYSTEM) .replace("%GLMVERSIONSTRING%", GLM_VERSION_MESSAGE) .replace("%GL_VERSION%", glVersion) .replace("%GL_EXTENSIONS%", extensions) ); } dialog.setWindowTitle(QObject::tr("About %1").arg(CMAKE_PROJECT_NAME)); dialog.exec(); } void MainWindow::rebuildRecentFilesMenu(const QStringList& strings) { this->menuRecentFiles->clear(); for (const QString& path : strings) { QAction* action = new QAction{path, this}; this->menuRecentFiles->addAction(action); connect(action, &QAction::triggered, [&, path]{ Q_EMIT this->recentFileSelected(path); }); } } static QString title(MainWindow* ui) { QMdiSubWindow* subWindow = ui->mdiArea->activeSubWindow(); QString titlestring; const QString versionString = fullVersionString(QLocale::ShortFormat); if (subWindow != nullptr) { titlestring = QObject::tr("%1 - %2").arg(subWindow->windowTitle(), versionString); } else { titlestring = versionString; } if (/* DISABLES CODE */ (true) and std::strcmp(CMAKE_BUILD_TYPE, "Release") != 0 and std::strcmp(CMAKE_BUILD_TYPE, "MinSizeRel") != 0 ) { titlestring += QObject::tr(" [%1]").arg(CMAKE_BUILD_TYPE); } return titlestring; } void MainWindow::updateTitle() { this->setWindowTitle(title(this)); }