From 7dcf25bf3a5ed8266b6cac01dca53729bfbbdb3b Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sun, 27 Jul 2025 04:24:02 +0500 Subject: [PATCH 01/14] Qt: Skip emulator-specific things on startup if starting in manager mode: - Don't try to read 86box.cfg; - Don't initialize subsystems that aren't used in manager mode; - Ignore `-I` or `-X` command-line options; - Don't block keyboard navigation and mnemonics in menus; - Don't perform UUID/WinBox/cpu_override checks. --- src/86box.c | 75 +++++++++++++++++++------------------ src/qt/qt_main.cpp | 32 ++++++++-------- src/qt/qt_styleoverride.cpp | 6 ++- 3 files changed, 61 insertions(+), 52 deletions(-) diff --git a/src/86box.c b/src/86box.c index b2c56caad..c653a2f0f 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1056,47 +1056,50 @@ usage: vmm_enabled = 1; pclog("# VM Manager enabled. Path: %s\n", vmm_path); } - /* - * We are about to read the configuration file, which MAY - * put data into global variables (the hard- and floppy - * disks are an example) so we have to initialize those - * modules before we load the config.. - */ - hdd_init(); - network_init(); - mouse_init(); - cdrom_global_init(); - rdisk_global_init(); - mo_global_init(); - /* Initialize the keyboard accelerator list with default values */ - for (int x = 0; x < NUM_ACCELS; x++) { - strcpy(acc_keys[x].name, def_acc_keys[x].name); - strcpy(acc_keys[x].desc, def_acc_keys[x].desc); - strcpy(acc_keys[x].seq, def_acc_keys[x].seq); - } + if (!vmm_enabled) { + /* + * We are about to read the configuration file, which MAY + * put data into global variables (the hard- and floppy + * disks are an example) so we have to initialize those + * modules before we load the config.. + */ + hdd_init(); + network_init(); + mouse_init(); + cdrom_global_init(); + rdisk_global_init(); + mo_global_init(); - /* Load the configuration file. */ - config_load(); + /* Initialize the keyboard accelerator list with default values */ + for (int x = 0; x < NUM_ACCELS; x++) { + strcpy(acc_keys[x].name, def_acc_keys[x].name); + strcpy(acc_keys[x].desc, def_acc_keys[x].desc); + strcpy(acc_keys[x].seq, def_acc_keys[x].seq); + } - /* Clear the CMOS and/or BIOS flash file, if we were started with - the relevant parameter(s). */ - if (clear_cmos) { - delete_nvr_file(0); - clear_cmos = 0; - } + /* Load the configuration file. */ + config_load(); - if (clear_flash) { - delete_nvr_file(1); - clear_flash = 0; - } + /* Clear the CMOS and/or BIOS flash file, if we were started with + the relevant parameter(s). */ + if (clear_cmos) { + delete_nvr_file(0); + clear_cmos = 0; + } - for (uint8_t i = 0; i < FDD_NUM; i++) { - if (fn[i] != NULL) { - if (strlen(fn[i]) <= 511) - strncpy(floppyfns[i], fn[i], 511); - free(fn[i]); - fn[i] = NULL; + if (clear_flash) { + delete_nvr_file(1); + clear_flash = 0; + } + + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fn[i] != NULL) { + if (strlen(fn[i]) <= 511) + strncpy(floppyfns[i], fn[i], 511); + free(fn[i]); + fn[i] = NULL; + } } } diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 77cf9b23e..06c5a8850 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -561,13 +561,11 @@ main(int argc, char *argv[]) } #endif - qt_set_sequence_auto_mnemonic(false); Q_INIT_RESOURCE(qt_resources); Q_INIT_RESOURCE(qt_translations); QSurfaceFormat fmt = QSurfaceFormat::defaultFormat(); fmt.setSwapInterval(0); QSurfaceFormat::setDefaultFormat(fmt); - app.setStyle(new StyleOverride()); #ifdef __APPLE__ CocoaEventFilter cocoafilter; @@ -586,6 +584,10 @@ main(int argc, char *argv[]) return 0; } + if (!vmm_enabled) + qt_set_sequence_auto_mnemonic(false); + app.setStyle(new StyleOverride()); + bool startMaximized = window_remember && monitor_settings[0].mon_window_maximized; fprintf(stderr, "Qt: version %s, platform \"%s\"\n", qVersion(), QApplication::platformName().toUtf8().data()); ProgSettings::loadTranslators(&app); @@ -619,6 +621,19 @@ main(int argc, char *argv[]) return 6; } + if (vmm_enabled) { + // VMManagerMain vmm; + // // Hackish until there is a proper solution + // QApplication::setApplicationName("86Box VM Manager"); + // QApplication::setApplicationDisplayName("86Box VM Manager"); + // vmm.show(); + // vmm.exec(); + const auto vmm_main_window = new VMManagerMainWindow(); + vmm_main_window->show(); + QApplication::exec(); + return 0; + } + // UUID / copy / move detection if(!util::compareUuid()) { QMessageBox movewarnbox; @@ -681,19 +696,6 @@ main(int argc, char *argv[]) return 0; } - if (vmm_enabled) { - // VMManagerMain vmm; - // // Hackish until there is a proper solution - // QApplication::setApplicationName("86Box VM Manager"); - // QApplication::setApplicationDisplayName("86Box VM Manager"); - // vmm.show(); - // vmm.exec(); - const auto vmm_main_window = new VMManagerMainWindow(); - vmm_main_window->show(); - QApplication::exec(); - return 0; - } - #ifdef DISCORD discord_load(); #endif diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index 0bade8fa6..237149a01 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -22,6 +22,10 @@ #include #include +extern "C" { +#include <86box/86box.h> +} + #ifdef Q_OS_WINDOWS #include #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE @@ -37,7 +41,7 @@ StyleOverride::styleHint( QStyleHintReturn *returnData) const { /* Disable using menu with alt key */ - if (hint == QStyle::SH_MenuBar_AltKeyNavigation) + if (!vmm_enabled && (hint == QStyle::SH_MenuBar_AltKeyNavigation)) return 0; return QProxyStyle::styleHint(hint, option, widget, returnData); From 3e1c6d3daed35103a75ccfb2f2334763512dd8bf Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sun, 27 Jul 2025 04:31:13 +0500 Subject: [PATCH 02/14] Manager: Add Help menu Move the About dialog into its own file and object --- src/qt/CMakeLists.txt | 2 + src/qt/qt_about.cpp | 75 ++++++++++++++++++++++++++++++ src/qt/qt_about.hpp | 13 ++++++ src/qt/qt_mainwindow.cpp | 39 ++-------------- src/qt/qt_vmmanager_mainwindow.cpp | 23 ++++++++- src/qt/qt_vmmanager_mainwindow.hpp | 3 ++ src/qt/qt_vmmanager_mainwindow.ui | 38 +++++++++++++-- 7 files changed, 151 insertions(+), 42 deletions(-) create mode 100644 src/qt/qt_about.cpp create mode 100644 src/qt/qt_about.hpp diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index aee0e2864..0479ff3f8 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -88,6 +88,8 @@ add_library(ui STATIC qt_openglrenderer.cpp qt_openglrenderer.hpp qt_glsl_parser.cpp + qt_about.cpp + qt_about.hpp qt_settings.cpp qt_settings.hpp diff --git a/src/qt/qt_about.cpp b/src/qt/qt_about.cpp new file mode 100644 index 000000000..96cde8522 --- /dev/null +++ b/src/qt/qt_about.cpp @@ -0,0 +1,75 @@ +/* + * 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. + * + * About dialog module. + * + * + * + * Authors: Joakim L. Gilje + * Cacodemon345 + * Teemu Korhonen + * dob205 + * + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Teemu Korhonen + * Copyright 2022 dob205 + */ +#include "qt_about.hpp" + +extern "C" { +#include <86box/86box.h> +#include <86box/version.h> +} + +#include +#include +#include +#include +#include + +About::About(QWidget *parent) +{ + setTextFormat(Qt::RichText); + QString versioninfo; +#ifdef EMU_GIT_HASH + versioninfo = QString(" [%1]").arg(EMU_GIT_HASH); +#endif +#ifdef USE_DYNAREC +# ifdef USE_NEW_DYNAREC +# define DYNAREC_STR "new dynarec" +# else +# define DYNAREC_STR "old dynarec" +# endif +#else +# define DYNAREC_STR "no dynarec" +#endif + versioninfo.append(QString(" [%1, %2]").arg(QSysInfo::buildCpuArchitecture(), tr(DYNAREC_STR))); + setText(QString("%3%1%2").arg(EMU_VERSION_FULL, versioninfo, tr("86Box v"))); + setInformativeText(tr("An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information.")); + setWindowTitle(tr("About 86Box")); + const auto closeButton = addButton("OK", QMessageBox::ButtonRole::AcceptRole); + setEscapeButton(closeButton); + const auto webSiteButton = addButton(EMU_SITE, QMessageBox::ButtonRole::HelpRole); + webSiteButton->connect(webSiteButton, &QPushButton::released, []() { + QDesktopServices::openUrl(QUrl("https://" EMU_SITE)); + }); +#ifdef RELEASE_BUILD + setIconPixmap(QIcon(":/settings/qt/icons/86Box-green.ico").pixmap(32, 32)); +#elif defined ALPHA_BUILD + setIconPixmap(QIcon(":/settings/qt/icons/86Box-red.ico").pixmap(32, 32)); +#elif defined BETA_BUILD + setIconPixmap(QIcon(":/settings/qt/icons/86Box-yellow.ico").pixmap(32, 32)); +#else + setIconPixmap(QIcon(":/settings/qt/icons/86Box-gray.ico").pixmap(32, 32)); +#endif + setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); +} + +About::~About() + = default; diff --git a/src/qt/qt_about.hpp b/src/qt/qt_about.hpp new file mode 100644 index 000000000..206aab37b --- /dev/null +++ b/src/qt/qt_about.hpp @@ -0,0 +1,13 @@ +#ifndef QT_ABOUT_HPP +#define QT_ABOUT_HPP + +#include + +class About final : public QMessageBox { + Q_OBJECT + +public: + explicit About(QWidget *parent = nullptr); + ~About() override; +}; +#endif // QT_ABOUT_HPP \ No newline at end of file diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 27eb5a14a..1b480152d 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -97,6 +97,7 @@ extern bool cpu_thread_running; #include #include "qt_settings.hpp" +#include "qt_about.hpp" #include "qt_machinestatus.hpp" #include "qt_mediamenu.hpp" #include "qt_util.hpp" @@ -1908,42 +1909,8 @@ MainWindow::on_actionAbout_Qt_triggered() void MainWindow::on_actionAbout_86Box_triggered() { - QMessageBox msgBox; - msgBox.setTextFormat(Qt::RichText); - QString versioninfo; -#ifdef EMU_GIT_HASH - versioninfo = QString(" [%1]").arg(EMU_GIT_HASH); -#endif -#ifdef USE_DYNAREC -# ifdef USE_NEW_DYNAREC -# define DYNAREC_STR "new dynarec" -# else -# define DYNAREC_STR "old dynarec" -# endif -#else -# define DYNAREC_STR "no dynarec" -#endif - versioninfo.append(QString(" [%1, %2]").arg(QSysInfo::buildCpuArchitecture(), tr(DYNAREC_STR))); - msgBox.setText(QString("%3%1%2").arg(EMU_VERSION_FULL, versioninfo, tr("86Box v"))); - msgBox.setInformativeText(tr("An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information.")); - msgBox.setWindowTitle(tr("About 86Box")); - const auto closeButton = msgBox.addButton("OK", QMessageBox::ButtonRole::AcceptRole); - msgBox.setEscapeButton(closeButton); - const auto webSiteButton = msgBox.addButton(EMU_SITE, QMessageBox::ButtonRole::HelpRole); - webSiteButton->connect(webSiteButton, &QPushButton::released, []() { - QDesktopServices::openUrl(QUrl("https://" EMU_SITE)); - }); -#ifdef RELEASE_BUILD - msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-green.ico").pixmap(32, 32)); -#elif defined ALPHA_BUILD - msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-red.ico").pixmap(32, 32)); -#elif defined BETA_BUILD - msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-yellow.ico").pixmap(32, 32)); -#else - msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-gray.ico").pixmap(32, 32)); -#endif - msgBox.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); - msgBox.exec(); + const auto msgBox = new About(this); + msgBox->exec(); } void diff --git a/src/qt/qt_vmmanager_mainwindow.cpp b/src/qt/qt_vmmanager_mainwindow.cpp index a349740e7..0bedfa224 100644 --- a/src/qt/qt_vmmanager_mainwindow.cpp +++ b/src/qt/qt_vmmanager_mainwindow.cpp @@ -22,10 +22,12 @@ #if EMU_BUILD_NUM != 0 # include "qt_updatecheckdialog.hpp" #endif +#include "qt_about.hpp" #include #include #include +#include VMManagerMainWindow:: VMManagerMainWindow(QWidget *parent) @@ -186,8 +188,27 @@ VMManagerMainWindow::checkForUpdatesTriggered() } #endif -void VMManagerMainWindow::on_actionExit_triggered() +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)); +} diff --git a/src/qt/qt_vmmanager_mainwindow.hpp b/src/qt/qt_vmmanager_mainwindow.hpp index 7a38750c4..f0e14b395 100644 --- a/src/qt/qt_vmmanager_mainwindow.hpp +++ b/src/qt/qt_vmmanager_mainwindow.hpp @@ -55,6 +55,9 @@ private slots: #endif void on_actionExit_triggered(); + void on_actionDocumentation_triggered(); + void on_actionAbout_86Box_triggered(); + void on_actionAbout_Qt_triggered(); protected: void closeEvent(QCloseEvent *event) override; diff --git a/src/qt/qt_vmmanager_mainwindow.ui b/src/qt/qt_vmmanager_mainwindow.ui index 1067c1e49..00dd8a4eb 100644 --- a/src/qt/qt_vmmanager_mainwindow.ui +++ b/src/qt/qt_vmmanager_mainwindow.ui @@ -38,8 +38,17 @@ + + + &Help + + + + + + @@ -71,11 +80,6 @@ - - - Do something - - true @@ -217,6 +221,30 @@ QAction::QuitRole + + + &Documentation... + + + + + &About 86Box... + + + QAction::AboutRole + + + + + About Qt + + + false + + + QAction::AboutQtRole + + From b42b735c25bdf87c2c1afc031f79e60c0f436979 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sun, 27 Jul 2025 04:38:00 +0500 Subject: [PATCH 03/14] Manager: Fix controls in the update details dialog not working --- src/qt/qt_updatecheckdialog.cpp | 2 +- src/qt/qt_updatedetails.cpp | 2 +- src/qt/qt_vmmanager_mainwindow.cpp | 2 +- src/qt/qt_vmmanager_mainwindow.hpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_updatecheckdialog.cpp b/src/qt/qt_updatecheckdialog.cpp index d0cb6941d..ef72af547 100644 --- a/src/qt/qt_updatecheckdialog.cpp +++ b/src/qt/qt_updatecheckdialog.cpp @@ -67,7 +67,7 @@ UpdateCheckDialog::downloadComplete(const UpdateCheck::UpdateResult &result) return; } - const auto updateDetails = new UpdateDetails(result); + const auto updateDetails = new UpdateDetails(result, this); connect(updateDetails, &QDialog::accepted, [this] { accept(); }); diff --git a/src/qt/qt_updatedetails.cpp b/src/qt/qt_updatedetails.cpp index dceeea47c..8b0b17eff 100644 --- a/src/qt/qt_updatedetails.cpp +++ b/src/qt/qt_updatedetails.cpp @@ -23,7 +23,7 @@ UpdateDetails:: -UpdateDetails(const UpdateCheck::UpdateResult &updateResult, QWidget *parent) : ui(new Ui::UpdateDetails) +UpdateDetails(const UpdateCheck::UpdateResult &updateResult, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDetails) { ui->setupUi(this); setWindowTitle("86Box Update"); diff --git a/src/qt/qt_vmmanager_mainwindow.cpp b/src/qt/qt_vmmanager_mainwindow.cpp index 0bedfa224..0ab4fcc2e 100644 --- a/src/qt/qt_vmmanager_mainwindow.cpp +++ b/src/qt/qt_vmmanager_mainwindow.cpp @@ -183,7 +183,7 @@ VMManagerMainWindow::checkForUpdatesTriggered() # ifdef RELEASE_BUILD updateChannel = UpdateCheck::UpdateChannel::Stable; # endif - const auto updateCheck = new UpdateCheckDialog(updateChannel); + const auto updateCheck = new UpdateCheckDialog(updateChannel, this); updateCheck->exec(); } #endif diff --git a/src/qt/qt_vmmanager_mainwindow.hpp b/src/qt/qt_vmmanager_mainwindow.hpp index f0e14b395..ca7b0043d 100644 --- a/src/qt/qt_vmmanager_mainwindow.hpp +++ b/src/qt/qt_vmmanager_mainwindow.hpp @@ -51,7 +51,7 @@ private slots: void vmmSelectionChanged(const QModelIndex ¤tSelection, QProcess::ProcessState processState) const; void preferencesTriggered(); #if EMU_BUILD_NUM != 0 - static void checkForUpdatesTriggered(); + void checkForUpdatesTriggered(); #endif void on_actionExit_triggered(); From cbd5991273337ce69120565c63b37e08004dd63c Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sun, 27 Jul 2025 04:38:55 +0500 Subject: [PATCH 04/14] Manager: Disable resizing the "Searching for VMs" window and the update checker window --- src/qt/qt_updatecheckdialog.cpp | 1 + src/qt/qt_updatecheckdialog.ui | 4 ++-- src/qt/qt_vmmanager_system.cpp | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_updatecheckdialog.cpp b/src/qt/qt_updatecheckdialog.cpp index ef72af547..c8254cafd 100644 --- a/src/qt/qt_updatecheckdialog.cpp +++ b/src/qt/qt_updatecheckdialog.cpp @@ -32,6 +32,7 @@ UpdateCheckDialog(const UpdateCheck::UpdateChannel channel, QWidget *parent) : Q ui->setupUi(this); setWindowTitle(tr("Update check")); ui->statusLabel->setHidden(true); + this->setFixedSize(400, 130); updateChannel = channel; currentVersion = UpdateCheck::getCurrentVersion(updateChannel); connect(updateCheck, &UpdateCheck::updateCheckError, [=](const QString &errorMsg) { diff --git a/src/qt/qt_updatecheckdialog.ui b/src/qt/qt_updatecheckdialog.ui index e50a541bb..84303f8bb 100644 --- a/src/qt/qt_updatecheckdialog.ui +++ b/src/qt/qt_updatecheckdialog.ui @@ -6,8 +6,8 @@ 0 0 - 350 - 134 + 400 + 130 diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 225b302df..355f0690f 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -126,6 +126,7 @@ VMManagerSystem::scanForConfigs(QWidget* parent, const QString &searchPath) progDialog.setMinimum(0); progDialog.setMaximum(0); progDialog.setWindowFlags(progDialog.windowFlags() & ~Qt::WindowCloseButtonHint); + progDialog.setFixedSize(progDialog.sizeHint()); QElapsedTimer scanTimer; scanTimer.start(); QVector system_configs; From b5ced14d1ba7ba36fd1641d5bf1b4e6538801e13 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 28 Jul 2025 19:25:04 +0500 Subject: [PATCH 05/14] Manager: Fix machine status showing as "Running"... instead of "Paused/Waiting" when opening settings for a stopped machine by establishing a minimal manager socket connection --- src/qt/qt_main.cpp | 5 +++++ src/qt/qt_vmmanager_main.cpp | 13 ------------- src/qt/qt_vmmanager_system.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 06c5a8850..0443c8b00 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -676,6 +676,11 @@ main(int argc, char *argv[]) #endif if (settings_only) { + VMManagerClientSocket manager_socket; + if (qgetenv("VMM_86BOX_SOCKET").size()) { + manager_socket.IPCConnect(qgetenv("VMM_86BOX_SOCKET")); + manager_socket.clientRunningStateChanged(VMManagerProtocol::RunningState::PausedWaiting); + } Settings settings; if (settings.exec() == QDialog::Accepted) { settings.save(); diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index 87649a6a1..85db8cb4a 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -182,19 +182,6 @@ VMManagerMain::settingsButtonPressed() { return; } selected_sysconfig->launchSettings(); - // If the process is already running, the system will be instructed to open its settings window. - // Otherwise the process will be launched and will need to be tracked here. - if (!selected_sysconfig->isProcessRunning()) { - connect(selected_sysconfig->process, QOverload::of(&QProcess::finished), - [=](const int exitCode, const QProcess::ExitStatus exitStatus){ - if (exitCode != 0 || exitStatus != QProcess::NormalExit) { - qInfo().nospace().noquote() << "Abnormal program termination while launching settings: exit code " << exitCode << ", exit status " << exitStatus; - return; - } - selected_sysconfig->reloadConfig(); - vm_details->updateData(selected_sysconfig); - }); - } } void diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 355f0690f..94340674a 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -418,6 +418,14 @@ VMManagerSystem::launchMainProcess() { qDebug() << Q_FUNC_INFO << " Full Command:" << process->program() << " " << process->arguments(); process->start(); updateTimestamp(); + + connect(process, QOverload::of(&QProcess::finished), + [=](const int exitCode, const QProcess::ExitStatus exitStatus){ + if (exitCode != 0 || exitStatus != QProcess::NormalExit) { + qInfo().nospace().noquote() << "Abnormal program termination while launching main process: exit code " << exitCode << ", exit status " << exitStatus; + return; + } + }); } void @@ -432,6 +440,15 @@ VMManagerSystem::launchSettings() { return; } + // start the server first to get the socket name + if (!serverIsRunning) { + if(!startServer()) { + // FIXME: Better error handling + qInfo("Failed to start VM Manager server"); + return; + } + } + // If the system is already running, instruct it to show settings if (process->processId() != 0) { #ifdef Q_OS_WINDOWS @@ -454,6 +471,14 @@ VMManagerSystem::launchSettings() { process->setArguments(args); qDebug() << Q_FUNC_INFO << " Full Command:" << process->program() << " " << process->arguments(); process->start(); + + connect(process, QOverload::of(&QProcess::finished), + [=](const int exitCode, const QProcess::ExitStatus exitStatus){ + if (exitCode != 0 || exitStatus != QProcess::NormalExit) { + qInfo().nospace().noquote() << "Abnormal program termination while launching settings: exit code " << exitCode << ", exit status " << exitStatus; + return; + } + }); } void From 494a24a3aea5fd5adbf6475d4326a3e415fe7a4c Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 28 Jul 2025 20:22:12 +0500 Subject: [PATCH 06/14] Manager: Implement double-clicking a VM entry to start a VM (and on Windows, bringing it to front if already running) --- src/qt/qt_vmmanager_main.cpp | 2 ++ src/qt/qt_vmmanager_system.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index 85db8cb4a..cbfdc3c0a 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -123,6 +123,8 @@ VMManagerMain::VMManagerMain(QWidget *parent) : ui->listView->setCurrentIndex(first_index); } + connect(ui->listView, &QListView::doubleClicked, this, &VMManagerMain::startButtonPressed); + // Load and apply settings loadSettings(); diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 94340674a..cd0f9c3ec 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -408,6 +408,15 @@ VMManagerSystem::launchMainProcess() { return; } } + // If the system is already running, bring it to front + if (process->processId() != 0) { +#ifdef Q_OS_WINDOWS + if (this->id) { + SetForegroundWindow((HWND)this->id); + } +#endif + return; + } setProcessEnvVars(); QString program = main_binary.filePath(); QStringList args; From dca59145f66868e6462a61cc91a8a01fbe67a414 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 28 Jul 2025 20:25:20 +0500 Subject: [PATCH 07/14] Manager: Fix UUID generation for manager config headers Fix different UUIDs generating depending on the whether the path is absolute or relative; they now always match the ones saved inside .cfg files Also reduce some code duplication --- src/qt/qt_util.cpp | 13 +++++++++---- src/qt/qt_util.hpp | 1 + src/qt/qt_vmmanager_system.cpp | 11 +++-------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index 5baaaaacf..bc9b9f1f8 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -117,11 +117,16 @@ DlgFilter(QStringList extensions, bool last) QString currentUuid() { - auto configPath = QFileInfo(cfg_path).dir().canonicalPath(); - if(!configPath.endsWith("/")) { - configPath.append("/"); + return generateUuid(QString(cfg_path)); +} + +QString generateUuid(const QString &path) +{ + auto dirPath = QFileInfo(path).dir().canonicalPath(); + if(!dirPath.endsWith("/")) { + dirPath.append("/"); } - return QUuid::createUuidV5(QUuid{}, configPath).toString(QUuid::WithoutBraces); + return QUuid::createUuidV5(QUuid{}, dirPath).toString(QUuid::WithoutBraces); } bool compareUuid() diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index e0d2648d0..de3457a88 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -18,6 +18,7 @@ QScreen *screenOfWidget(QWidget *widget); void setWin11RoundedCorners(WId hwnd, bool enable); #endif QString currentUuid(); +QString generateUuid(const QString &path); void storeCurrentUuid(); bool compareUuid(); void generateNewMacAdresses(); diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index cd0f9c3ec..bf40e1c36 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -28,6 +28,7 @@ #include #include #include +#include "qt_util.hpp" #include "qt_vmmanager_system.hpp" // #include "qt_vmmanager_details_section.hpp" #include "qt_vmmanager_detailsection.hpp" @@ -67,16 +68,10 @@ VMManagerSystem::VMManagerSystem(const QString &sysconfig_file) { // that contains the 86box configuration file config_name = config_file.dir().dirName(); // The full path of the directory that contains the 86box configuration file - config_dir = shortened_dir = config_file.dir().path(); + config_dir = shortened_dir = config_file.dir().absolutePath(); process_status = ProcessStatus::Stopped; - // Main 86Box uses usr_path for UUID which includes the trailing slash. - // Make sure to append the slash here so the UUIDs will match - auto uuid_path = config_dir; - if (!uuid_path.endsWith("/")) { - uuid_path.append("/"); - } // In the configuration file the UUID is used as a unique value - uuid = QUuid::createUuidV5(QUuid{}, uuid_path).toString(QUuid::WithoutBraces); + uuid = util::generateUuid(sysconfig_file); // That unique value is used to map the information to each individual system. config_settings = new VMManagerConfig(VMManagerConfig::ConfigType::System, uuid); From 1d421b4db0d6e291614958d2b0edea479a863ff5 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 28 Jul 2025 20:26:53 +0500 Subject: [PATCH 08/14] Manager: always use long arguments when starting a VM THey're unlikely to change, unlike short ones --- src/qt/qt_vmmanager_system.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index bf40e1c36..fa386266f 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -415,7 +415,7 @@ VMManagerSystem::launchMainProcess() { setProcessEnvVars(); QString program = main_binary.filePath(); QStringList args; - args << "-P" << config_dir; + args << "--vmpath" << config_dir; args << "--vmname" << displayName; process->setProgram(program); process->setArguments(args); @@ -470,7 +470,7 @@ VMManagerSystem::launchSettings() { QString program = main_binary.filePath(); QStringList open_command_args; QStringList args; - args << "-P" << config_dir << "-S"; + args << "--vmpath" << config_dir << "--settings"; process->setProgram(program); process->setArguments(args); qDebug() << Q_FUNC_INFO << " Full Command:" << process->program() << " " << process->arguments(); From 2657a5bade42f402b8e121a022a6c62be87a2b72 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Tue, 29 Jul 2025 05:39:43 +0500 Subject: [PATCH 09/14] Manager: Warn on close when machines are running --- src/qt/qt_vmmanager_main.cpp | 6 ++++++ src/qt/qt_vmmanager_main.hpp | 1 + src/qt/qt_vmmanager_mainwindow.cpp | 10 ++++++++++ src/qt/qt_vmmanager_model.cpp | 11 +++++++++++ src/qt/qt_vmmanager_model.hpp | 1 + 5 files changed, 29 insertions(+) diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index cbfdc3c0a..3973bebfd 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -459,6 +459,12 @@ VMManagerMain::onPreferencesUpdated() } } +int +VMManagerMain::getActiveMachineCount() +{ + return vm_model->getActiveMachineCount(); +} + #if EMU_BUILD_NUM != 0 void VMManagerMain::backgroundUpdateCheckStart() const diff --git a/src/qt/qt_vmmanager_main.hpp b/src/qt/qt_vmmanager_main.hpp index 075af76f1..d4591d418 100644 --- a/src/qt/qt_vmmanager_main.hpp +++ b/src/qt/qt_vmmanager_main.hpp @@ -77,6 +77,7 @@ public slots: #endif void modelDataChange(); void onPreferencesUpdated(); + int getActiveMachineCount(); private: Ui::VMManagerMain *ui; diff --git a/src/qt/qt_vmmanager_mainwindow.cpp b/src/qt/qt_vmmanager_mainwindow.cpp index 0ab4fcc2e..76b8ccb15 100644 --- a/src/qt/qt_vmmanager_mainwindow.cpp +++ b/src/qt/qt_vmmanager_mainwindow.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include VMManagerMainWindow:: @@ -159,6 +160,15 @@ VMManagerMainWindow::saveSettings() const 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("%1 machine(s) are currently active. Are you sure you want to exit the VM manager anyway?").arg(running), QMessageBox::Yes | QMessageBox::No, this); + warningbox.exec(); + if (warningbox.result() == QMessageBox::No) { + event->ignore(); + return; + } + } saveSettings(); QMainWindow::closeEvent(event); } diff --git a/src/qt/qt_vmmanager_model.cpp b/src/qt/qt_vmmanager_model.cpp index 848970f80..6c7cf09a0 100644 --- a/src/qt/qt_vmmanager_model.cpp +++ b/src/qt/qt_vmmanager_model.cpp @@ -160,4 +160,15 @@ VMManagerModel::getProcessStats() } } return stats; +} + +int +VMManagerModel::getActiveMachineCount() +{ + int running = 0; + for (const auto& system: machines) { + if (system->getProcessStatus() != VMManagerSystem::ProcessStatus::Stopped) + running++; + } + return running; } \ No newline at end of file diff --git a/src/qt/qt_vmmanager_model.hpp b/src/qt/qt_vmmanager_model.hpp index bc13cc16f..43757c78d 100644 --- a/src/qt/qt_vmmanager_model.hpp +++ b/src/qt/qt_vmmanager_model.hpp @@ -57,6 +57,7 @@ public: void reload(QWidget* parent = nullptr); void updateDisplayName(const QModelIndex &index, const QString &newDisplayName); QHash getProcessStats(); + int getActiveMachineCount(); signals: void systemDataChanged(); From 8c88d6257bd53ebb7cba85b495c7116d2de00e25 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Tue, 29 Jul 2025 05:41:23 +0500 Subject: [PATCH 10/14] Manager: Use monospace font for displaying the config Also make the config window resizable --- src/qt/qt_vmmanager_addmachine.cpp | 11 +++++++++++ src/qt/qt_vmmanager_main.cpp | 13 ++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_vmmanager_addmachine.cpp b/src/qt/qt_vmmanager_addmachine.cpp index aa6c7a1c4..cab50354b 100644 --- a/src/qt/qt_vmmanager_addmachine.cpp +++ b/src/qt/qt_vmmanager_addmachine.cpp @@ -139,6 +139,17 @@ WithExistingConfigPage(QWidget *parent) topLabel->setWordWrap(true); existingConfiguration = new QPlainTextEdit(); + const auto monospaceFont = new QFont(); +#ifdef Q_OS_WINDOWS + monospaceFont->setFamily("Consolas"); +#elif defined(Q_OS_MACOS) + monospaceFont->setFamily("Menlo"); +#else + monospaceFont->setFamily("Monospace"); +#endif + monospaceFont->setStyleHint(QFont::Monospace); + monospaceFont->setFixedPitch(true); + existingConfiguration->setFont(*monospaceFont); connect(existingConfiguration, &QPlainTextEdit::textChanged, this, &WithExistingConfigPage::completeChanged); registerField("existingConfiguration*", this, "configuration"); diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index 3973bebfd..9c695dc33 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -515,10 +515,21 @@ VMManagerMain::showTextFileContents(const QString &title, const QString &path) displayFile.close(); const auto textDisplayDialog = new QDialog(this); - textDisplayDialog->setFixedSize(QSize(540, 360)); + textDisplayDialog->setMinimumSize(QSize(540, 360)); textDisplayDialog->setWindowTitle(QString("%1 - %2").arg(title, fi.fileName())); const auto textEdit = new QPlainTextEdit(); + const auto monospaceFont = new QFont(); +#ifdef Q_OS_WINDOWS + monospaceFont->setFamily("Consolas"); +#elif defined(Q_OS_MACOS) + monospaceFont->setFamily("Menlo"); +#else + monospaceFont->setFamily("Monospace"); +#endif + monospaceFont->setStyleHint(QFont::Monospace); + monospaceFont->setFixedPitch(true); + textEdit->setFont(*monospaceFont); textEdit->setReadOnly(true); textEdit->setPlainText(configFileContents); const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); From 04966d609b8977aab5cee722ca0da1dd4efefdfa Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sun, 27 Jul 2025 04:36:21 +0500 Subject: [PATCH 11/14] Manager: Add keyboard mnemonics and ellipses to menu entries --- src/qt/languages/86box.pot | 2 +- src/qt/languages/ca-ES.po | 4 ++-- src/qt/languages/cs-CZ.po | 2 +- src/qt/languages/de-DE.po | 4 ++-- src/qt/languages/es-ES.po | 4 ++-- src/qt/languages/fi-FI.po | 4 ++-- src/qt/languages/fr-FR.po | 4 ++-- src/qt/languages/hr-HR.po | 4 ++-- src/qt/languages/hu-HU.po | 4 ++-- src/qt/languages/it-IT.po | 4 ++-- src/qt/languages/ja-JP.po | 4 ++-- src/qt/languages/ko-KR.po | 4 ++-- src/qt/languages/nl-NL.po | 4 ++-- src/qt/languages/pl-PL.po | 4 ++-- src/qt/languages/pt-BR.po | 4 ++-- src/qt/languages/pt-PT.po | 4 ++-- src/qt/languages/ru-RU.po | 4 ++-- src/qt/languages/sk-SK.po | 2 +- src/qt/languages/sl-SI.po | 4 ++-- src/qt/languages/sv-SE.po | 4 ++-- src/qt/languages/tr-TR.po | 4 ++-- src/qt/languages/uk-UA.po | 4 ++-- src/qt/languages/vi-VN.po | 4 ++-- src/qt/languages/zh-CN.po | 4 ++-- src/qt/languages/zh-TW.po | 4 ++-- src/qt/qt_mainwindow.ui | 2 +- src/qt/qt_vmmanager_main.cpp | 8 ++++---- src/qt/qt_vmmanager_mainwindow.cpp | 2 +- src/qt/qt_vmmanager_mainwindow.ui | 27 ++++++++++++++------------- 29 files changed, 67 insertions(+), 66 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index cbceeda70..16bffd679 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -30,7 +30,7 @@ msgstr "" msgid "Re&sume" msgstr "" -msgid "E&xit..." +msgid "E&xit" msgstr "" msgid "&View" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index bcd479612..d91784a4c 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -30,8 +30,8 @@ msgstr "&Pausa" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Sortir ..." +msgid "E&xit" +msgstr "&Sortir" msgid "&View" msgstr "&Vista" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index bbdac0727..6eee3fb97 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -30,7 +30,7 @@ msgstr "P&ozastavit" msgid "Re&sume" msgstr "" -msgid "E&xit..." +msgid "E&xit" msgstr "&Ukončit" msgid "&View" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index d05c983d4..cd42d929f 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -30,8 +30,8 @@ msgstr "&Pause" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "Be&enden..." +msgid "E&xit" +msgstr "Be&enden" msgid "&View" msgstr "&Ansicht" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index d81d1deb4..a3778ec95 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -30,8 +30,8 @@ msgstr "&Pausa" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Salir..." +msgid "E&xit" +msgstr "&Salir" msgid "&View" msgstr "&Vista" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index f1cdc6275..e32563384 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -30,8 +30,8 @@ msgstr "&Tauko" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Poistu..." +msgid "E&xit" +msgstr "&Poistu" msgid "&View" msgstr "&Näytä" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 18e2f0d4c..f53b7df65 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -30,8 +30,8 @@ msgstr "&Pause" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Quitter..." +msgid "E&xit" +msgstr "&Quitter" msgid "&View" msgstr "&Vue" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 64264be7b..d57aa726a 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -30,8 +30,8 @@ msgstr "&Pauza" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "Iz&laz..." +msgid "E&xit" +msgstr "Iz&laz" msgid "&View" msgstr "&Pogled" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index dfe32f40f..690375040 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -30,8 +30,8 @@ msgstr "&Szüneteltetés" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Kilépés..." +msgid "E&xit" +msgstr "&Kilépés" msgid "&View" msgstr "&Nézet" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index da9d0a97d..69013ef63 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -30,8 +30,8 @@ msgstr "&Pausa" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "E&sci..." +msgid "E&xit" +msgstr "E&sci" msgid "&View" msgstr "&Visualizza" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 05326224e..dbba3cde3 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -30,8 +30,8 @@ msgstr "一時停止(&P)" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "終了(&X)..." +msgid "E&xit" +msgstr "終了(&X)" msgid "&View" msgstr "表示(&V)" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 6744ea1c0..4ad717660 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -30,8 +30,8 @@ msgstr "일시정지(&P)" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "끝내기(&X)..." +msgid "E&xit" +msgstr "끝내기(&X)" msgid "&View" msgstr "표시(&V)" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 0a0f5b4f3..a811fcdf8 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -30,8 +30,8 @@ msgstr "&Pauze" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Afsluiten..." +msgid "E&xit" +msgstr "&Afsluiten" msgid "&View" msgstr "&Beeld" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 9608e52d0..2a3898026 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -30,8 +30,8 @@ msgstr "&Pauza" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "W&yjdź..." +msgid "E&xit" +msgstr "W&yjdź" msgid "&View" msgstr "&Widok" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 07152bd6b..d7393ef52 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -30,8 +30,8 @@ msgstr "&Pausar" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Sair..." +msgid "E&xit" +msgstr "&Sair" msgid "&View" msgstr "&Exibir" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 0c8118828..622189fc1 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -30,8 +30,8 @@ msgstr "&Pausa" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Sair..." +msgid "E&xit" +msgstr "&Sair" msgid "&View" msgstr "&Ver" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a453ad3e3..06e2fe054 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -30,8 +30,8 @@ msgstr "&Пауза" msgid "Re&sume" msgstr "В&озобновить" -msgid "E&xit..." -msgstr "&Выход..." +msgid "E&xit" +msgstr "&Выход" msgid "&View" msgstr "&Вид" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 072fa283e..f7e166e35 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -30,7 +30,7 @@ msgstr "P&ozastaviť" msgid "Re&sume" msgstr "" -msgid "E&xit..." +msgid "E&xit" msgstr "&Ukončiť" msgid "&View" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 524213c56..21b7b659e 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -30,8 +30,8 @@ msgstr "&Premor" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "Iz&hod..." +msgid "E&xit" +msgstr "Iz&hod" msgid "&View" msgstr "&Pogled" diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po index 35bb890f7..3d9b4552a 100644 --- a/src/qt/languages/sv-SE.po +++ b/src/qt/languages/sv-SE.po @@ -30,8 +30,8 @@ msgstr "&Pausa" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "A&vsluta..." +msgid "E&xit" +msgstr "A&vsluta" msgid "&View" msgstr "&Visa" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index bdda1bcd3..957c945b7 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -30,8 +30,8 @@ msgstr "&Duraklat" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Çıkış yap..." +msgid "E&xit" +msgstr "&Çıkış yap" msgid "&View" msgstr "&Görünüm" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index a2191f3ec..c99437441 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -30,8 +30,8 @@ msgstr "&Пауза" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "&Вихід..." +msgid "E&xit" +msgstr "&Вихід" msgid "&View" msgstr "&Вигляд" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 2424662f2..b6e04730d 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -30,8 +30,8 @@ msgstr "Tạm &dừng" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "Th&oát..." +msgid "E&xit" +msgstr "Th&oát" msgid "&View" msgstr "&Xem" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 9b1e66717..1dfa4bff6 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -30,8 +30,8 @@ msgstr "暂停(&P)" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "退出(&X)..." +msgid "E&xit" +msgstr "退出(&X)" msgid "&View" msgstr "查看(&V)" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 401b53103..a9a7a4091 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -30,8 +30,8 @@ msgstr "暫停(&P)" msgid "Re&sume" msgstr "" -msgid "E&xit..." -msgstr "退出(&X)..." +msgid "E&xit" +msgstr "退出(&X)" msgid "&View" msgstr "檢視(&V)" diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index 992a9a0d4..4cec06fdc 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -354,7 +354,7 @@ - Exit + E&xit QAction::QuitRole diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index 9c695dc33..2b7af6c80 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -53,7 +53,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) : if (indexAt.isValid()) { QMenu contextMenu(tr("Context Menu"), ui->listView); - QAction nameChangeAction(tr("Change display name")); + QAction nameChangeAction(tr("Change &display name...")); contextMenu.addAction(&nameChangeAction); // Use a lambda to call a function so indexAt can be passed connect(&nameChangeAction, &QAction::triggered, ui->listView, [this, indexAt] { @@ -61,7 +61,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) : }); nameChangeAction.setEnabled(!selected_sysconfig->window_obscured); - QAction openSystemFolderAction(tr("Open folder")); + QAction openSystemFolderAction(tr("&Open folder...")); contextMenu.addAction(&openSystemFolderAction); connect(&openSystemFolderAction, &QAction::triggered, [indexAt] { if (const auto configDir = indexAt.data(VMManagerModel::Roles::ConfigDir).toString(); !configDir.isEmpty()) { @@ -73,7 +73,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) : } }); - QAction setSystemIcon(tr("Set icon")); + QAction setSystemIcon(tr("Set &icon...")); contextMenu.addAction(&setSystemIcon); connect(&setSystemIcon, &QAction::triggered, [this] { IconSelectionDialog dialog(":/systemicons/"); @@ -98,7 +98,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) : contextMenu.addSeparator(); - QAction showRawConfigFile(tr("Show config file")); + QAction showRawConfigFile(tr("Show &config file")); contextMenu.addAction(&showRawConfigFile); connect(&showRawConfigFile, &QAction::triggered, [this, indexAt] { if (const auto configFile = indexAt.data(VMManagerModel::Roles::ConfigFile).toString(); !configFile.isEmpty()) { diff --git a/src/qt/qt_vmmanager_mainwindow.cpp b/src/qt/qt_vmmanager_mainwindow.cpp index 76b8ccb15..17995215a 100644 --- a/src/qt/qt_vmmanager_mainwindow.cpp +++ b/src/qt/qt_vmmanager_mainwindow.cpp @@ -46,11 +46,11 @@ VMManagerMainWindow(QWidget *parent) 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->actionNew_Machine, &QAction::triggered, vmm, &VMManagerMain::newMachineWizard); // Set up menu actions // (Disable this if the EMU_BUILD_NUM == 0) diff --git a/src/qt/qt_vmmanager_mainwindow.ui b/src/qt/qt_vmmanager_mainwindow.ui index 00dd8a4eb..33b80f687 100644 --- a/src/qt/qt_vmmanager_mainwindow.ui +++ b/src/qt/qt_vmmanager_mainwindow.ui @@ -25,14 +25,14 @@ - Tools + &Tools - File + &File @@ -73,12 +73,13 @@ false + + - @@ -89,7 +90,7 @@ :/menuicons/qt/icons/run.ico:/menuicons/qt/icons/run.ico - Start + &Start false @@ -116,7 +117,7 @@ :/menuicons/qt/icons/acpi_shutdown.ico:/menuicons/qt/icons/acpi_shutdown.ico - Force shutdown + &Force shutdown Force shutdown @@ -173,18 +174,18 @@ :/settings/qt/icons/86Box-yellow.ico:/settings/qt/icons/86Box-yellow.ico - New Machine + &New machine... - New Machine + New machine... - Preferences + &Preferences... - Preferences + Preferences... QAction::PreferencesRole @@ -199,7 +200,7 @@ :/menuicons/qt/icons/run.ico:/menuicons/qt/icons/run.ico - Start + &Start false @@ -207,7 +208,7 @@ - Check for updates + &Check for updates... @@ -215,7 +216,7 @@ - &Exit + E&xit QAction::QuitRole @@ -236,7 +237,7 @@ - About Qt + About &Qt false From 544c2ddee2a0cd27b8313c022515f27f45969e19 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 30 Jul 2025 02:42:29 +0500 Subject: [PATCH 12/14] Manager: Disable add machine wizard help entirely --- src/qt/qt_vmmanager_addmachine.cpp | 4 ++++ src/qt/qt_vmmanager_addmachine.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/qt/qt_vmmanager_addmachine.cpp b/src/qt/qt_vmmanager_addmachine.cpp index cab50354b..55ff7274b 100644 --- a/src/qt/qt_vmmanager_addmachine.cpp +++ b/src/qt/qt_vmmanager_addmachine.cpp @@ -62,11 +62,14 @@ VMManagerAddMachine(QWidget *parent) : QWizard(parent) setOption(HaveHelpButton, false); // setPixmap(LogoPixmap, QPixmap(":/settings/qt/icons/86Box-gray.ico")); +#if 0 connect(this, &QWizard::helpRequested, this, &VMManagerAddMachine::showHelp); +#endif setWindowTitle(tr("Add new system wizard")); } +#if 0 void VMManagerAddMachine::showHelp() { @@ -92,6 +95,7 @@ VMManagerAddMachine::showHelp() QMessageBox::information(this, tr("Add new system wizard help"), message); lastHelpMessage = message; } +#endif IntroPage:: IntroPage(QWidget *parent) diff --git a/src/qt/qt_vmmanager_addmachine.hpp b/src/qt/qt_vmmanager_addmachine.hpp index c1355b471..6ba1a53ce 100644 --- a/src/qt/qt_vmmanager_addmachine.hpp +++ b/src/qt/qt_vmmanager_addmachine.hpp @@ -42,8 +42,10 @@ public: explicit VMManagerAddMachine(QWidget *parent = nullptr); +#if 0 private slots: void showHelp(); +#endif }; class IntroPage : public QWizardPage { From 176c1d5402d31efcd538c0f8d51f92234ce0b87f Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 1 Aug 2025 02:36:31 +0500 Subject: [PATCH 13/14] Manager: Add a context menu entry to open a machine's printer output folder --- src/qt/qt_vmmanager_main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index 2b7af6c80..ae1083f52 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -73,6 +73,18 @@ VMManagerMain::VMManagerMain(QWidget *parent) : } }); + QAction openPrinterFolderAction(tr("Open &printer tray...")); + contextMenu.addAction(&openPrinterFolderAction); + connect(&openPrinterFolderAction, &QAction::triggered, [indexAt] { + if (const auto printerDir = indexAt.data(VMManagerModel::Roles::ConfigDir).toString() + QString("/printer/"); !printerDir.isEmpty()) { + QDir dir(printerDir); + if (!dir.exists()) + dir.mkpath("."); + + QDesktopServices::openUrl(QUrl(QString("file:///") + dir.canonicalPath())); + } + }); + QAction setSystemIcon(tr("Set &icon...")); contextMenu.addAction(&setSystemIcon); connect(&setSystemIcon, &QAction::triggered, [this] { From 0ea994a972acdc543774e534e7f6534b07b909cc Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 30 Jul 2025 23:39:59 +0500 Subject: [PATCH 14/14] Manager: Miscellaneous changes --- src/qt/qt_updatecheckdialog.cpp | 1 - src/qt/qt_updatecheckdialog.ui | 2 +- src/qt/qt_updatedetails.cpp | 1 - src/qt/qt_updatedetails.ui | 2 +- src/qt/qt_vmmanager_details.cpp | 2 +- src/qt/qt_vmmanager_detailsection.cpp | 2 +- src/qt/qt_vmmanager_main.cpp | 3 +-- src/qt/qt_vmmanager_main.hpp | 1 + src/qt/qt_vmmanager_mainwindow.cpp | 5 ++++- src/qt/qt_vmmanager_mainwindow.ui | 9 ++++++--- 10 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/qt/qt_updatecheckdialog.cpp b/src/qt/qt_updatecheckdialog.cpp index c8254cafd..71db9f31b 100644 --- a/src/qt/qt_updatecheckdialog.cpp +++ b/src/qt/qt_updatecheckdialog.cpp @@ -30,7 +30,6 @@ UpdateCheckDialog:: UpdateCheckDialog(const UpdateCheck::UpdateChannel channel, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateCheckDialog), updateCheck(new UpdateCheck(channel)) { ui->setupUi(this); - setWindowTitle(tr("Update check")); ui->statusLabel->setHidden(true); this->setFixedSize(400, 130); updateChannel = channel; diff --git a/src/qt/qt_updatecheckdialog.ui b/src/qt/qt_updatecheckdialog.ui index 84303f8bb..c70ca8de2 100644 --- a/src/qt/qt_updatecheckdialog.ui +++ b/src/qt/qt_updatecheckdialog.ui @@ -17,7 +17,7 @@ - Dialog + Update check diff --git a/src/qt/qt_updatedetails.cpp b/src/qt/qt_updatedetails.cpp index 8b0b17eff..f043c9504 100644 --- a/src/qt/qt_updatedetails.cpp +++ b/src/qt/qt_updatedetails.cpp @@ -26,7 +26,6 @@ UpdateDetails:: UpdateDetails(const UpdateCheck::UpdateResult &updateResult, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDetails) { ui->setupUi(this); - setWindowTitle("86Box Update"); ui->updateTitle->setText("An update to 86Box is available!"); QString currentVersionText; QString releaseType = updateResult.channel == UpdateCheck::UpdateChannel::Stable ? tr("version") : tr("build"); diff --git a/src/qt/qt_updatedetails.ui b/src/qt/qt_updatedetails.ui index 7b9c0aa2a..7798896a9 100644 --- a/src/qt/qt_updatedetails.ui +++ b/src/qt/qt_updatedetails.ui @@ -17,7 +17,7 @@ - Dialog + 86Box Update diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index c3b5ac4ce..7744f32de 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -60,7 +60,7 @@ VMManagerDetails::VMManagerDetails(QWidget *parent) : ui->leftColumn->layout()->addWidget(networkSection); // ui->leftColumn->layout()->addWidget(createHorizontalLine()); - inputSection = new VMManagerDetailSection(tr("Input Devices", "Header for Input section in VM Manager Details")); + inputSection = new VMManagerDetailSection(tr("Input devices", "Header for Input section in VM Manager Details")); ui->leftColumn->layout()->addWidget(inputSection); // ui->leftColumn->layout()->addWidget(createHorizontalLine()); diff --git a/src/qt/qt_vmmanager_detailsection.cpp b/src/qt/qt_vmmanager_detailsection.cpp index ce42ae281..23c940706 100644 --- a/src/qt/qt_vmmanager_detailsection.cpp +++ b/src/qt/qt_vmmanager_detailsection.cpp @@ -216,7 +216,7 @@ VMManagerDetailSection::setSections() labelKey->setFont(smaller_font); labelValue->setFont(smaller_font); - labelKey->setText(section.name + ":"); + labelKey->setText(QCoreApplication::translate("", QString(section.name + ":").toUtf8().data())); labelValue->setText(line); if(!keyAdded) { frameGridLayout->addWidget(labelKey, row, 0, Qt::AlignLeft); diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index ae1083f52..9ae953ada 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -32,7 +32,6 @@ VMManagerMain::VMManagerMain(QWidget *parent) : QWidget(parent), ui(new Ui::VMManagerMain), selected_sysconfig(new VMManagerSystem) { ui->setupUi(this); - this->setWindowTitle("86Box VM Manager"); // Set up the main listView ui->listView->setItemDelegate(new VMManagerListViewDelegate); @@ -100,7 +99,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) : QAction killIcon(tr("&Kill")); contextMenu.addAction(&killIcon); connect(&killIcon, &QAction::triggered, [this, parent] { - QMessageBox msgbox(QMessageBox::Warning, tr("Warning"), tr("Killing a virtual machine can cause data loss. Only do this if 86Box.exe process gets stuck.\n\nDo you really wish to kill the virtual machine \"%1\"?").arg(selected_sysconfig->displayName), QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, parent); + QMessageBox msgbox(QMessageBox::Warning, tr("Warning"), tr("Killing a virtual machine can cause data loss. Only do this if the 86Box process gets stuck.\n\nDo you really wish to kill the virtual machine \"%1\"?").arg(selected_sysconfig->displayName), QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, parent); msgbox.exec(); if (msgbox.result() == QMessageBox::Yes) { selected_sysconfig->process->kill(); diff --git a/src/qt/qt_vmmanager_main.hpp b/src/qt/qt_vmmanager_main.hpp index d4591d418..b1ba6886c 100644 --- a/src/qt/qt_vmmanager_main.hpp +++ b/src/qt/qt_vmmanager_main.hpp @@ -27,6 +27,7 @@ extern "C" { #include <86box/86box.h> // for vmm_path +#include <86box/version.h> } #if EMU_BUILD_NUM != 0 diff --git a/src/qt/qt_vmmanager_mainwindow.cpp b/src/qt/qt_vmmanager_mainwindow.cpp index 17995215a..42464294b 100644 --- a/src/qt/qt_vmmanager_mainwindow.cpp +++ b/src/qt/qt_vmmanager_mainwindow.cpp @@ -42,7 +42,7 @@ VMManagerMainWindow(QWidget *parent) // Connect signals from the VMManagerMain widget connect(vmm, &VMManagerMain::selectionChanged, this, &VMManagerMainWindow::vmmSelectionChanged); - setWindowTitle(tr("86Box VM Manager")); + setWindowTitle(tr("%1 VM Manager").arg(EMU_NAME)); setCentralWidget(vmm); // Set up the buttons @@ -97,6 +97,9 @@ VMManagerMainWindow(QWidget *parent) auto *completerModel = new QStringListModel(allStrings, completer); completer->setModel(completerModel); searchBar->setCompleter(completer); +#ifdef Q_OS_WINDOWS + ui->toolBar->setBackgroundRole(QPalette::Light); +#endif ui->toolBar->setVisible(false); // END REMOVE diff --git a/src/qt/qt_vmmanager_mainwindow.ui b/src/qt/qt_vmmanager_mainwindow.ui index 33b80f687..fa32241a4 100644 --- a/src/qt/qt_vmmanager_mainwindow.ui +++ b/src/qt/qt_vmmanager_mainwindow.ui @@ -52,12 +52,18 @@ + + true + toolBar false + + Qt::TopToolBarArea + 16 @@ -212,9 +218,6 @@ - - - E&xit