mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 01:25:33 -07:00
Previously, we determined the UI font from a predefined set of fonts each mapped to a language. This works well if the user doesn't change their Windows UI font, but if one does, they will get the default UI font associated with their language instead of the one the set. This commit replaces ProgSettings::getFontName with ProgSettings::getUIFont, which uses the SystemParametersInfo API to query the message font from the system, which will allow users to have a custom font. It will also not interfere with different languages, as the message font will be appropriately set by default there.
352 lines
12 KiB
C++
352 lines
12 KiB
C++
/*
|
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
* running old operating systems and software designed for IBM
|
|
* PC systems and compatibles from 1981 through fairly recent
|
|
* system designs based on the PCI bus.
|
|
*
|
|
* This file is part of the 86Box distribution.
|
|
*
|
|
* 86Box VM manager main window
|
|
*
|
|
* Authors: cold-brewed
|
|
*
|
|
* Copyright 2024 cold-brewed
|
|
*/
|
|
#include "qt_vmmanager_mainwindow.hpp"
|
|
#include "qt_vmmanager_main.hpp"
|
|
#include "qt_vmmanager_preferences.hpp"
|
|
#include "qt_vmmanager_windarkmodefilter.hpp"
|
|
#include "ui_qt_vmmanager_mainwindow.h"
|
|
#if EMU_BUILD_NUM != 0
|
|
# include "qt_updatecheckdialog.hpp"
|
|
#endif
|
|
#include "qt_about.hpp"
|
|
#include "qt_progsettings.hpp"
|
|
#include "qt_util.hpp"
|
|
|
|
#include <QCloseEvent>
|
|
#include <QDesktopServices>
|
|
|
|
extern "C" {
|
|
extern void config_load_global();
|
|
extern void config_save_global();
|
|
}
|
|
|
|
VMManagerMainWindow *vmm_main_window = nullptr;
|
|
extern WindowsDarkModeFilter *vmm_dark_mode_filter;
|
|
|
|
VMManagerMainWindow::
|
|
VMManagerMainWindow(QWidget *parent)
|
|
: ui(new Ui::VMManagerMainWindow)
|
|
, vmm(new VMManagerMain(this))
|
|
, statusLeft(new QLabel)
|
|
, statusRight(new QLabel)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
vmm_main_window = this;
|
|
|
|
runIcon = QIcon(":/menuicons/qt/icons/run.ico");
|
|
pauseIcon = QIcon(":/menuicons/qt/icons/pause.ico");
|
|
|
|
// Connect signals from the VMManagerMain widget
|
|
connect(vmm, &VMManagerMain::selectionOrStateChanged, this, &VMManagerMainWindow::vmmStateChanged);
|
|
|
|
setWindowTitle(tr("%1 VM Manager").arg(EMU_NAME));
|
|
setCentralWidget(vmm);
|
|
|
|
// Set up the buttons
|
|
connect(ui->actionNew_Machine, &QAction::triggered, vmm, &VMManagerMain::newMachineWizard);
|
|
connect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::startButtonPressed);
|
|
connect(ui->actionSettings, &QAction::triggered, vmm, &VMManagerMain::settingsButtonPressed);
|
|
connect(ui->actionHard_Reset, &QAction::triggered, vmm, &VMManagerMain::restartButtonPressed);
|
|
connect(ui->actionForce_Shutdown, &QAction::triggered, vmm, &VMManagerMain::shutdownForceButtonPressed);
|
|
connect(ui->actionCtrl_Alt_Del, &QAction::triggered, vmm, &VMManagerMain::cadButtonPressed);
|
|
|
|
// Set up menu actions
|
|
// (Disable this if the EMU_BUILD_NUM == 0)
|
|
#if EMU_BUILD_NUM == 0
|
|
ui->actionCheck_for_updates->setVisible(false);
|
|
#else
|
|
connect(ui->actionCheck_for_updates, &QAction::triggered, this, &VMManagerMainWindow::checkForUpdatesTriggered);
|
|
#endif
|
|
|
|
// Set up the toolbar
|
|
ui->actionStartPause->setEnabled(false);
|
|
ui->actionStartPause->setIcon(runIcon);
|
|
ui->actionStartPause->setText(tr("Start"));
|
|
ui->actionStartPause->setToolTip(tr("Start"));
|
|
ui->actionHard_Reset->setEnabled(false);
|
|
ui->actionForce_Shutdown->setEnabled(false);
|
|
ui->actionCtrl_Alt_Del->setEnabled(false);
|
|
ui->actionSettings->setEnabled(false);
|
|
|
|
// Preferences
|
|
connect(ui->actionPreferences, &QAction::triggered, this, &VMManagerMainWindow::preferencesTriggered);
|
|
|
|
#ifdef Q_OS_WINDOWS
|
|
ui->toolBar->setBackgroundRole(QPalette::Light);
|
|
#endif
|
|
|
|
// Status bar widgets
|
|
statusLeft->setAlignment(Qt::AlignLeft);
|
|
statusRight->setAlignment(Qt::AlignRight);
|
|
ui->statusbar->addPermanentWidget(statusLeft, 1);
|
|
ui->statusbar->addPermanentWidget(statusRight, 1);
|
|
connect(vmm, &VMManagerMain::updateStatusLeft, this, &VMManagerMainWindow::setStatusLeft);
|
|
connect(vmm, &VMManagerMain::updateStatusRight, this, &VMManagerMainWindow::setStatusRight);
|
|
|
|
// Inform the main view when preferences are updated
|
|
connect(this, &VMManagerMainWindow::preferencesUpdated, vmm, &VMManagerMain::onPreferencesUpdated);
|
|
connect(this, &VMManagerMainWindow::languageUpdated, vmm, &VMManagerMain::onLanguageUpdated);
|
|
#ifdef Q_OS_WINDOWS
|
|
connect(this, &VMManagerMainWindow::darkModeUpdated, vmm, &VMManagerMain::onDarkModeUpdated);
|
|
connect(this, &VMManagerMainWindow::preferencesUpdated, []() { vmm_dark_mode_filter->reselectDarkMode(); });
|
|
#endif
|
|
|
|
{
|
|
auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General);
|
|
ui->actionHide_tool_bar->setChecked(!!config->getStringValue("hide_tool_bar").toInt());
|
|
if (ui->actionHide_tool_bar->isChecked())
|
|
ui->toolBar->setVisible(false);
|
|
if (!!config->getStringValue("window_remember").toInt()) {
|
|
QString coords = config->getStringValue("window_coordinates");
|
|
if (!coords.isEmpty()) {
|
|
QStringList list = coords.split(',');
|
|
for (auto &cur : list) {
|
|
cur = cur.trimmed();
|
|
}
|
|
QRect geom;
|
|
geom.setX(list[0].toInt());
|
|
geom.setY(list[1].toInt());
|
|
geom.setWidth(list[2].toInt());
|
|
geom.setHeight(list[3].toInt());
|
|
|
|
setGeometry(geom);
|
|
}
|
|
|
|
if (!!config->getStringValue("window_maximized").toInt()) {
|
|
setWindowState(windowState() | Qt::WindowMaximized);
|
|
}
|
|
|
|
QString splitter = config->getStringValue("window_splitter");
|
|
if (!splitter.isEmpty()) {
|
|
QStringList list = splitter.split(',');
|
|
for (auto &cur : list) {
|
|
cur = cur.trimmed();
|
|
}
|
|
QList<int> paneSizes;
|
|
paneSizes.append(list[0].toInt());
|
|
paneSizes.append(list[1].toInt());
|
|
|
|
vmm->setPaneSizes(paneSizes);
|
|
}
|
|
} else {
|
|
config->setStringValue("window_coordinates", "");
|
|
config->setStringValue("window_maximized", "");
|
|
config->setStringValue("window_splitter", "");
|
|
}
|
|
delete config;
|
|
}
|
|
}
|
|
|
|
VMManagerMainWindow::~VMManagerMainWindow()
|
|
= default;
|
|
|
|
void
|
|
VMManagerMainWindow::vmmStateChanged(const VMManagerSystem *sysconfig) const
|
|
{
|
|
if (sysconfig == nullptr) {
|
|
// This doubles both as a safety check and a way to disable
|
|
// all machine-related buttons when no machines are present
|
|
ui->actionStartPause->setEnabled(false);
|
|
ui->actionSettings->setEnabled(false);
|
|
ui->actionHard_Reset->setEnabled(false);
|
|
ui->actionForce_Shutdown->setEnabled(false);
|
|
ui->actionCtrl_Alt_Del->setEnabled(false);
|
|
return;
|
|
}
|
|
const bool running = sysconfig->process->state() == QProcess::ProcessState::Running;
|
|
|
|
if (running) {
|
|
if (sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::Running) {
|
|
ui->actionStartPause->setIcon(pauseIcon);
|
|
ui->actionStartPause->setText(tr("&Pause"));
|
|
ui->actionStartPause->setToolTip(tr("Pause"));
|
|
ui->actionStartPause->setIconText(tr("Pause"));
|
|
} else {
|
|
ui->actionStartPause->setIcon(runIcon);
|
|
ui->actionStartPause->setText(tr("&Continue"));
|
|
ui->actionStartPause->setToolTip(tr("Continue"));
|
|
ui->actionStartPause->setIconText(tr("Continue"));
|
|
}
|
|
disconnect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::startButtonPressed);
|
|
disconnect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::pauseButtonPressed);
|
|
connect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::pauseButtonPressed);
|
|
} else {
|
|
ui->actionStartPause->setIcon(runIcon);
|
|
ui->actionStartPause->setText(tr("&Start"));
|
|
ui->actionStartPause->setToolTip(tr("Start"));
|
|
ui->actionStartPause->setIconText(tr("Start"));
|
|
disconnect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::pauseButtonPressed);
|
|
disconnect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::startButtonPressed);
|
|
connect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::startButtonPressed);
|
|
}
|
|
|
|
ui->actionStartPause->setEnabled(!sysconfig->window_obscured);
|
|
ui->actionSettings->setEnabled(!sysconfig->window_obscured);
|
|
ui->actionHard_Reset->setEnabled(sysconfig->window_obscured ? false : running);
|
|
ui->actionForce_Shutdown->setEnabled(sysconfig->window_obscured ? false : running);
|
|
ui->actionCtrl_Alt_Del->setEnabled(sysconfig->window_obscured ? false : running);
|
|
}
|
|
void
|
|
VMManagerMainWindow::preferencesTriggered()
|
|
{
|
|
bool machinesRunning = (vmm->getActiveMachineCount() > 0);
|
|
auto old_vmm_path = QString(vmm_path_cfg);
|
|
const auto prefs = new VMManagerPreferences(this, machinesRunning);
|
|
if (prefs->exec() == QDialog::Accepted) {
|
|
emit preferencesUpdated();
|
|
updateLanguage();
|
|
|
|
auto new_vmm_path = QString(vmm_path_cfg);
|
|
if (!machinesRunning && (new_vmm_path != old_vmm_path)) {
|
|
qDebug() << "Machine path changed: old path " << old_vmm_path << ", new path " << new_vmm_path;
|
|
strncpy(vmm_path, vmm_path_cfg, sizeof(vmm_path));
|
|
vmm->reload();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::updateSettings()
|
|
{
|
|
config_load_global();
|
|
emit preferencesUpdated();
|
|
updateLanguage();
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::saveSettings() const
|
|
{
|
|
const auto currentSelection = vmm->getCurrentSelection();
|
|
const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General);
|
|
config->setStringValue("last_selection", currentSelection);
|
|
config->setStringValue("hide_tool_bar", (ui->toolBar->isVisible() ? "0" : "1"));
|
|
if (!!config->getStringValue("window_remember").toInt()) {
|
|
config->setStringValue("window_coordinates", QString::asprintf("%i, %i, %i, %i", this->geometry().x(), this->geometry().y(), this->geometry().width(), this->geometry().height()));
|
|
config->setStringValue("window_maximized", this->isMaximized() ? "1" : "");
|
|
config->setStringValue("window_splitter", QString::asprintf("%i, %i", vmm->getPaneSizes()[0], vmm->getPaneSizes()[1]));
|
|
} else {
|
|
config->setStringValue("window_coordinates", "");
|
|
config->setStringValue("window_maximized", "");
|
|
config->setStringValue("window_splitter", "");
|
|
}
|
|
// Sometimes required to ensure the settings save before the app exits
|
|
config->sync();
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::updateLanguage()
|
|
{
|
|
ProgSettings::loadTranslators(QCoreApplication::instance());
|
|
ProgSettings::reloadStrings();
|
|
ui->retranslateUi(this);
|
|
setWindowTitle(tr("%1 VM Manager").arg(EMU_NAME));
|
|
emit languageUpdated();
|
|
}
|
|
|
|
#ifdef Q_OS_WINDOWS
|
|
void
|
|
VMManagerMainWindow::updateDarkMode()
|
|
{
|
|
emit darkModeUpdated();
|
|
}
|
|
#endif
|
|
|
|
void
|
|
VMManagerMainWindow::changeEvent(QEvent *event)
|
|
{
|
|
#ifdef Q_OS_WINDOWS
|
|
if (event->type() == QEvent::LanguageChange) {
|
|
QApplication::setFont(QFont(ProgSettings::getUIFont()));
|
|
}
|
|
#endif
|
|
QWidget::changeEvent(event);
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::closeEvent(QCloseEvent *event)
|
|
{
|
|
int running = vmm->getActiveMachineCount();
|
|
if (running > 0) {
|
|
QMessageBox warningbox(QMessageBox::Icon::Warning, tr("%1 VM Manager").arg(EMU_NAME), tr("%n machine(s) are currently active. Are you sure you want to exit the VM manager anyway?", "", running), QMessageBox::Yes | QMessageBox::No, this);
|
|
warningbox.exec();
|
|
if (warningbox.result() == QMessageBox::No) {
|
|
event->ignore();
|
|
return;
|
|
}
|
|
}
|
|
saveSettings();
|
|
QMainWindow::closeEvent(event);
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::setStatusLeft(const QString &text) const
|
|
{
|
|
statusLeft->setText(text);
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::setStatusRight(const QString &text) const
|
|
{
|
|
statusRight->setText(text);
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::on_actionHide_tool_bar_triggered()
|
|
{
|
|
const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General);
|
|
int isHidden = config->getStringValue("hide_tool_bar").toInt();
|
|
ui->toolBar->setVisible(!!isHidden);
|
|
config->setStringValue("hide_tool_bar", (isHidden ? "0" : "1"));
|
|
}
|
|
|
|
#if EMU_BUILD_NUM != 0
|
|
void
|
|
VMManagerMainWindow::checkForUpdatesTriggered()
|
|
{
|
|
auto updateChannel = UpdateCheck::UpdateChannel::CI;
|
|
# ifdef RELEASE_BUILD
|
|
updateChannel = UpdateCheck::UpdateChannel::Stable;
|
|
# endif
|
|
const auto updateCheck = new UpdateCheckDialog(updateChannel, this);
|
|
updateCheck->exec();
|
|
}
|
|
#endif
|
|
|
|
void
|
|
VMManagerMainWindow::on_actionExit_triggered()
|
|
{
|
|
this->close();
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::on_actionAbout_Qt_triggered()
|
|
{
|
|
QApplication::aboutQt();
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::on_actionAbout_86Box_triggered()
|
|
{
|
|
const auto msgBox = new About(this);
|
|
msgBox->exec();
|
|
}
|
|
|
|
void
|
|
VMManagerMainWindow::on_actionDocumentation_triggered()
|
|
{
|
|
QDesktopServices::openUrl(QUrl(EMU_DOCS_URL));
|
|
}
|