pbsa-nix/GLMainWindow.cpp

164 lines
5.2 KiB
C++
Raw Normal View History

2024-04-16 20:34:15 +02:00
#include "GLMainWindow.hpp"
#include "ui_GLMainWindow.h"
#ifdef _WIN32
#include <QWindow>
#include <QtGui/qpa/qplatformwindow_p.h>
#endif
#include <QActionGroup>
#include <QMessageBox>
#include <QShortcut>
GLMainWindow::GLMainWindow(QWidget * parent, Qt::WindowFlags f)
: QMainWindow{parent, f}
, ui{new Ui::GLMainWindow}
{
// set up ui defined in GLMainWindow.ui
this->ui->setupUi(this);
// copy title from application
this->setWindowTitle(QApplication::applicationDisplayName());
// forward signals
this->connect(this->ui->openGLWidget, &OpenGLWidget::loggingEnabledChanged, this, &GLMainWindow::openGLLoggingEnabledChanged);
this->connect(this->ui->openGLWidget, &OpenGLWidget::loggingSynchronousChanged, this, &GLMainWindow::openGLLoggingSynchronousChanged);
// set system-specific shortcuts
this->ui->actionExit->setShortcuts(QKeySequence::Quit);
this->ui->actionFullScreen->setShortcuts(QKeySequence::FullScreen);
// create an exclusive action group
auto fullScreenGroup = new QActionGroup{this};
fullScreenGroup->addAction(this->ui->actionFullScreen);
fullScreenGroup->addAction(this->ui->actionFullScreenOpenGL);
// triggering the selected action in this action group should uncheck it
connect(fullScreenGroup, &QActionGroup::triggered, [lastAction = static_cast<QAction *>(nullptr)] (QAction* action) mutable {
if(action == lastAction)
{
action->setChecked(false);
lastAction = nullptr;
}
else
{
lastAction = action;
}
});
// we hide the menuBar in full screen OpenGL mode, but this disables shortcuts as well, so we clone them
this->fillActionShortcuts(this->menuBar());
// add an additional shortcut (Escape) to leave full screen OpenGL mode
{
auto action = this->ui->actionFullScreenOpenGL;
this->actionShortcuts.emplace_back(new QShortcut{QKeySequence::fromString(tr("Esc")), this});
auto actionShortcut = this->actionShortcuts.back();
actionShortcut->setAutoRepeat(false);
actionShortcut->setEnabled(false);
this->connect(actionShortcut, &QShortcut::activated, action, [action] { if(action->isEnabled()) action->trigger(); });
}
}
GLMainWindow::~GLMainWindow() = default;
void GLMainWindow::setRendererFactory(std::function<OpenGLRenderer * (QObject * parent)> rendererFactory)
{
this->ui->openGLWidget->setRendererFactory(std::move(rendererFactory));
}
// forward slots
void GLMainWindow::setOpenGLLoggingEnabled(bool enabled) { this->ui->openGLWidget->setLoggingEnabled(enabled); }
void GLMainWindow::setOpenGLLoggingSynchronous(bool synchronous) { this->ui->openGLWidget->setLoggingSynchronous(synchronous); }
void GLMainWindow::on_actionFullScreen_toggled(bool checked)
{
#ifdef _WIN32
// add a window border to ensure window compositing is not disabled, otherwise context menus etc. stop working
this->window()->windowHandle()->nativeInterface<QNativeInterface::Private::QWindowsWindow>()->setHasBorderInFullScreen(true);
this->showNormal();
#endif
if(checked)
this->showFullScreen();
else
this->showNormal();
}
void GLMainWindow::on_actionFullScreenOpenGL_toggled(bool checked)
{
// hide/show widgets such as the menu bar to create a true full screen view
if(checked)
{
this->savedVisibilities.clear();
for(auto child : this->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly))
{
if(child == this->ui->openGLWidget)
continue;
this->savedVisibilities[child] = child->isVisible();
child->setVisible(false);
}
}
else
{
for(auto child : this->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly))
{
if(child == this->ui->openGLWidget)
continue;
auto it = this->savedVisibilities.find(child);
if(it != this->savedVisibilities.end())
child->setVisible(it->second);
}
}
// enable/disable shortcuts depending on menuBar visibility
for(auto shortcut : this->actionShortcuts)
shortcut->setEnabled(checked);
#ifdef _WIN32
// see on_actionFullScreen_toggled, we don't use any menus in "exclusive" fullscreen
this->window()->windowHandle()->nativeInterface<QNativeInterface::Private::QWindowsWindow>()->setHasBorderInFullScreen(!checked);
this->showNormal();
#endif
if(checked || this->ui->actionFullScreen->isChecked())
this->showFullScreen();
else
this->showNormal();
}
void GLMainWindow::on_actionAbout_triggered()
{
QMessageBox::about(this, tr("About %1").arg(QApplication::applicationDisplayName()), tr("This application is based on the simulation framework for the TU Darmstadt lecture on physically based simulation and animation."));
}
void GLMainWindow::fillActionShortcuts(QWidget * base)
{
// copy action shortcuts recursively
for(auto action : base->actions())
{
if(auto menu = action->menu())
{
this->fillActionShortcuts(menu);
continue;
}
if(action->isSeparator())
continue;
for(auto && shortcut : action->shortcuts())
{
this->actionShortcuts.emplace_back(new QShortcut{shortcut, this});
auto actionShortcut = this->actionShortcuts.back();
actionShortcut->setAutoRepeat(false);
// disable shortcuts by default to avoid ambiguity when menuBar is visible
actionShortcut->setEnabled(false);
this->connect(actionShortcut, &QShortcut::activated, action, [action] { if(action->isEnabled() && action->isVisible()) action->trigger(); });
}
}
}