/* * 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 "ui_qt_vmmanager_mainwindow.h" #if EMU_BUILD_NUM != 0 # include "qt_updatecheckdialog.hpp" #endif #include "qt_about.hpp" #include #include #include #include #include VMManagerMainWindow:: VMManagerMainWindow(QWidget *parent) : ui(new Ui::VMManagerMainWindow) , vmm(new VMManagerMain(this)) , statusLeft(new QLabel) , statusRight(new QLabel) { ui->setupUi(this); // Connect signals from the VMManagerMain widget connect(vmm, &VMManagerMain::selectionChanged, this, &VMManagerMainWindow::vmmSelectionChanged); 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); // 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 // TODO: Remove all of this (all the way to END REMOVE) once certain the search will no longer be in the toolbar. // BEGIN REMOVE // Everything is still setup here for it but it is all hidden. None of it will be // needed if the search stays in VMManagerMain ui->actionStartPause->setEnabled(true); ui->actionStartPause->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); 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); const auto searchBar = new QLineEdit(); searchBar->setMinimumWidth(150); searchBar->setPlaceholderText(" " + tr("Search")); searchBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); searchBar->setClearButtonEnabled(true); // Spacer to make the search go all the way to the right const auto spacer = new QWidget(); spacer->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); ui->toolBar->addWidget(spacer); ui->toolBar->addWidget(searchBar); // Connect signal for search connect(searchBar, &QLineEdit::textChanged, vmm, &VMManagerMain::searchSystems); // Preferences connect(ui->actionPreferences, &QAction::triggered, this, &VMManagerMainWindow::preferencesTriggered); // Create a completer for the search bar auto *completer = new QCompleter(this); completer->setCaseSensitivity(Qt::CaseInsensitive); completer->setFilterMode(Qt::MatchContains); // Get the completer list const auto allStrings = vmm->getSearchCompletionList(); // Set up the completer 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 // 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); } VMManagerMainWindow::~ VMManagerMainWindow() = default; void VMManagerMainWindow::vmmSelectionChanged(const QModelIndex ¤tSelection, const QProcess::ProcessState processState) const { if (processState == QProcess::Running) { ui->actionStartPause->setEnabled(true); ui->actionStartPause->setIcon(QIcon(":/menuicons/qt/icons/pause.ico")); ui->actionStartPause->setText(tr("Pause")); ui->actionStartPause->setToolTip(tr("Pause")); disconnect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::startButtonPressed); connect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::pauseButtonPressed); ui->actionHard_Reset->setEnabled(true); ui->actionForce_Shutdown->setEnabled(true); ui->actionCtrl_Alt_Del->setEnabled(true); } else { ui->actionStartPause->setEnabled(true); ui->actionStartPause->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); ui->actionStartPause->setText(tr("Start")); ui->actionStartPause->setToolTip(tr("Start")); disconnect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::pauseButtonPressed); connect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::startButtonPressed); ui->actionHard_Reset->setEnabled(false); ui->actionForce_Shutdown->setEnabled(false); ui->actionCtrl_Alt_Del->setEnabled(false); } } void VMManagerMainWindow::preferencesTriggered() { const auto prefs = new VMManagerPreferences(); if (prefs->exec() == QDialog::Accepted) { emit preferencesUpdated(); } } void VMManagerMainWindow::saveSettings() const { const auto currentSelection = vmm->getCurrentSelection(); const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); config->setStringValue("last_selection", currentSelection); // Sometimes required to ensure the settings save before the app exits config->sync(); } 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); } void VMManagerMainWindow::setStatusLeft(const QString &text) const { statusLeft->setText(text); } void VMManagerMainWindow::setStatusRight(const QString &text) const { statusRight->setText(text); } #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)); }