2015-11-27 08:33:07 +00:00
|
|
|
// Copyright 2015 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2+
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2017-06-15 23:42:12 +00:00
|
|
|
#include <QApplication>
|
2017-06-24 15:00:37 +00:00
|
|
|
#include <QCloseEvent>
|
2015-11-27 08:33:07 +00:00
|
|
|
#include <QDir>
|
2017-06-26 21:22:40 +00:00
|
|
|
#include <QDragEnterEvent>
|
|
|
|
#include <QDropEvent>
|
2015-11-27 08:33:07 +00:00
|
|
|
#include <QFileDialog>
|
2017-06-26 21:22:40 +00:00
|
|
|
#include <QFileInfo>
|
2015-11-27 08:33:07 +00:00
|
|
|
#include <QIcon>
|
|
|
|
#include <QMessageBox>
|
2017-06-26 21:22:40 +00:00
|
|
|
#include <QMimeData>
|
2015-11-27 08:33:07 +00:00
|
|
|
|
2017-06-05 18:36:30 +00:00
|
|
|
#include "Common/Common.h"
|
|
|
|
|
2017-05-27 13:43:40 +00:00
|
|
|
#include "Core/Boot/Boot.h"
|
2015-11-27 08:33:07 +00:00
|
|
|
#include "Core/BootManager.h"
|
2016-07-13 01:11:29 +00:00
|
|
|
#include "Core/ConfigManager.h"
|
2015-11-27 08:33:07 +00:00
|
|
|
#include "Core/Core.h"
|
2017-05-23 20:12:01 +00:00
|
|
|
#include "Core/HW/GCKeyboard.h"
|
|
|
|
#include "Core/HW/GCPad.h"
|
2016-06-24 08:43:46 +00:00
|
|
|
#include "Core/HW/ProcessorInterface.h"
|
2017-05-23 20:12:01 +00:00
|
|
|
#include "Core/HW/Wiimote.h"
|
|
|
|
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
|
|
|
#include "Core/HotkeyManager.h"
|
2016-02-15 01:56:40 +00:00
|
|
|
#include "Core/Movie.h"
|
2017-05-09 16:49:10 +00:00
|
|
|
#include "Core/NetPlayProto.h"
|
2016-02-15 01:56:40 +00:00
|
|
|
#include "Core/State.h"
|
2016-05-09 13:34:07 +00:00
|
|
|
|
2016-02-11 11:59:44 +00:00
|
|
|
#include "DolphinQt2/AboutDialog.h"
|
2017-05-09 16:49:10 +00:00
|
|
|
#include "DolphinQt2/Config/ControllersWindow.h"
|
2017-06-15 23:42:12 +00:00
|
|
|
|
|
|
|
#include "DolphinQt2/Config/Graphics/GraphicsWindow.h"
|
2017-06-06 11:49:49 +00:00
|
|
|
#include "DolphinQt2/Config/Mapping/MappingWindow.h"
|
2016-06-24 08:43:46 +00:00
|
|
|
#include "DolphinQt2/Config/SettingsWindow.h"
|
2015-11-27 08:33:07 +00:00
|
|
|
#include "DolphinQt2/Host.h"
|
2017-06-06 11:49:49 +00:00
|
|
|
#include "DolphinQt2/HotkeyScheduler.h"
|
2015-11-27 08:33:07 +00:00
|
|
|
#include "DolphinQt2/MainWindow.h"
|
2017-06-15 01:49:56 +00:00
|
|
|
#include "DolphinQt2/QtUtils/WindowActivationEventFilter.h"
|
2015-11-27 08:33:07 +00:00
|
|
|
#include "DolphinQt2/Resources.h"
|
2015-12-20 23:36:39 +00:00
|
|
|
#include "DolphinQt2/Settings.h"
|
2017-06-14 09:58:11 +00:00
|
|
|
#include "DolphinQt2/WiiUpdate.h"
|
2015-11-27 08:33:07 +00:00
|
|
|
|
2017-05-23 20:12:01 +00:00
|
|
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
|
|
|
|
2017-06-24 15:00:37 +00:00
|
|
|
#include "UICommon/UICommon.h"
|
|
|
|
|
2017-06-15 23:42:12 +00:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
|
|
|
#include <qpa/qplatformnativeinterface.h>
|
|
|
|
#include "UICommon/X11Utils.h"
|
|
|
|
#endif
|
|
|
|
|
2015-11-27 08:33:07 +00:00
|
|
|
MainWindow::MainWindow() : QMainWindow(nullptr)
|
|
|
|
{
|
2017-06-05 18:36:30 +00:00
|
|
|
setWindowTitle(QString::fromStdString(scm_rev_str));
|
2016-06-24 08:43:46 +00:00
|
|
|
setWindowIcon(QIcon(Resources::GetMisc(Resources::LOGO_SMALL)));
|
|
|
|
setUnifiedTitleAndToolBarOnMac(true);
|
2017-06-26 21:22:40 +00:00
|
|
|
setAcceptDrops(true);
|
2015-11-27 08:33:07 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
CreateComponents();
|
2016-02-10 04:42:06 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
ConnectGameList();
|
|
|
|
ConnectToolBar();
|
|
|
|
ConnectRenderWidget();
|
|
|
|
ConnectStack();
|
|
|
|
ConnectMenuBar();
|
2017-05-23 20:12:01 +00:00
|
|
|
|
|
|
|
InitControllers();
|
2017-06-16 13:27:00 +00:00
|
|
|
InitCoreCallbacks();
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-15 01:04:16 +00:00
|
|
|
MainWindow::~MainWindow()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
m_render_widget->deleteLater();
|
2017-06-01 04:11:54 +00:00
|
|
|
ShutdownControllers();
|
2016-02-15 01:04:16 +00:00
|
|
|
}
|
|
|
|
|
2017-05-23 20:12:01 +00:00
|
|
|
void MainWindow::InitControllers()
|
|
|
|
{
|
|
|
|
if (g_controller_interface.IsInit())
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_controller_interface.Initialize(reinterpret_cast<void*>(winId()));
|
|
|
|
Pad::Initialize();
|
|
|
|
Keyboard::Initialize();
|
|
|
|
Wiimote::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
|
2017-06-06 11:49:49 +00:00
|
|
|
m_hotkey_scheduler = new HotkeyScheduler();
|
|
|
|
m_hotkey_scheduler->Start();
|
|
|
|
|
|
|
|
ConnectHotkeys();
|
2017-05-23 20:12:01 +00:00
|
|
|
}
|
|
|
|
|
2017-06-01 04:11:54 +00:00
|
|
|
void MainWindow::ShutdownControllers()
|
|
|
|
{
|
2017-06-06 11:49:49 +00:00
|
|
|
m_hotkey_scheduler->Stop();
|
|
|
|
|
2017-06-01 04:11:54 +00:00
|
|
|
g_controller_interface.Shutdown();
|
|
|
|
Pad::Shutdown();
|
|
|
|
Keyboard::Shutdown();
|
|
|
|
Wiimote::Shutdown();
|
|
|
|
HotkeyManagerEmu::Shutdown();
|
2017-06-06 11:49:49 +00:00
|
|
|
|
|
|
|
m_hotkey_scheduler->deleteLater();
|
|
|
|
}
|
|
|
|
|
2017-06-16 13:27:00 +00:00
|
|
|
void MainWindow::InitCoreCallbacks()
|
|
|
|
{
|
|
|
|
Core::SetOnStoppedCallback([this] { emit EmulationStopped(); });
|
2017-06-24 15:00:37 +00:00
|
|
|
installEventFilter(this);
|
|
|
|
m_render_widget->installEventFilter(this);
|
2017-06-16 13:27:00 +00:00
|
|
|
}
|
|
|
|
|
2017-06-15 01:49:56 +00:00
|
|
|
static void InstallHotkeyFilter(QWidget* dialog)
|
2017-06-06 11:49:49 +00:00
|
|
|
{
|
2017-06-15 01:49:56 +00:00
|
|
|
auto* filter = new WindowActivationEventFilter();
|
2017-06-06 11:49:49 +00:00
|
|
|
dialog->installEventFilter(filter);
|
|
|
|
|
2017-06-15 01:49:56 +00:00
|
|
|
filter->connect(filter, &WindowActivationEventFilter::windowDeactivated,
|
|
|
|
[] { HotkeyManagerEmu::Enable(true); });
|
|
|
|
filter->connect(filter, &WindowActivationEventFilter::windowActivated,
|
|
|
|
[] { HotkeyManagerEmu::Enable(false); });
|
2017-06-01 04:11:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 04:42:06 +00:00
|
|
|
void MainWindow::CreateComponents()
|
2015-11-27 08:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
m_menu_bar = new MenuBar(this);
|
|
|
|
m_tool_bar = new ToolBar(this);
|
|
|
|
m_game_list = new GameList(this);
|
|
|
|
m_render_widget = new RenderWidget;
|
|
|
|
m_stack = new QStackedWidget(this);
|
2017-05-09 16:49:10 +00:00
|
|
|
m_controllers_window = new ControllersWindow(this);
|
2016-06-24 08:43:46 +00:00
|
|
|
m_settings_window = new SettingsWindow(this);
|
2017-06-06 11:49:49 +00:00
|
|
|
m_hotkey_window = new MappingWindow(this, 0);
|
|
|
|
|
2017-06-21 08:27:21 +00:00
|
|
|
connect(this, &MainWindow::EmulationStarted, m_settings_window,
|
|
|
|
&SettingsWindow::EmulationStarted);
|
|
|
|
connect(this, &MainWindow::EmulationStopped, m_settings_window,
|
|
|
|
&SettingsWindow::EmulationStopped);
|
|
|
|
|
2017-06-15 23:42:12 +00:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
|
|
|
m_graphics_window = new GraphicsWindow(
|
|
|
|
new X11Utils::XRRConfiguration(
|
|
|
|
static_cast<Display*>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow(
|
|
|
|
"display", windowHandle())),
|
|
|
|
winId()),
|
|
|
|
this);
|
|
|
|
#else
|
|
|
|
m_graphics_window = new GraphicsWindow(nullptr, this);
|
|
|
|
#endif
|
|
|
|
|
2017-06-06 11:49:49 +00:00
|
|
|
InstallHotkeyFilter(m_hotkey_window);
|
|
|
|
InstallHotkeyFilter(m_controllers_window);
|
|
|
|
InstallHotkeyFilter(m_settings_window);
|
2017-06-15 23:42:12 +00:00
|
|
|
InstallHotkeyFilter(m_graphics_window);
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 04:42:06 +00:00
|
|
|
void MainWindow::ConnectMenuBar()
|
2015-11-27 08:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
setMenuBar(m_menu_bar);
|
|
|
|
// File
|
|
|
|
connect(m_menu_bar, &MenuBar::Open, this, &MainWindow::Open);
|
|
|
|
connect(m_menu_bar, &MenuBar::Exit, this, &MainWindow::close);
|
|
|
|
|
|
|
|
// Emulation
|
|
|
|
connect(m_menu_bar, &MenuBar::Pause, this, &MainWindow::Pause);
|
|
|
|
connect(m_menu_bar, &MenuBar::Play, this, &MainWindow::Play);
|
|
|
|
connect(m_menu_bar, &MenuBar::Stop, this, &MainWindow::Stop);
|
|
|
|
connect(m_menu_bar, &MenuBar::Reset, this, &MainWindow::Reset);
|
|
|
|
connect(m_menu_bar, &MenuBar::Fullscreen, this, &MainWindow::FullScreen);
|
|
|
|
connect(m_menu_bar, &MenuBar::FrameAdvance, this, &MainWindow::FrameAdvance);
|
|
|
|
connect(m_menu_bar, &MenuBar::Screenshot, this, &MainWindow::ScreenShot);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateLoad, this, &MainWindow::StateLoad);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateSave, this, &MainWindow::StateSave);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateLoadSlot, this, &MainWindow::StateLoadSlot);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateSaveSlot, this, &MainWindow::StateSaveSlot);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateLoadSlotAt, this, &MainWindow::StateLoadSlotAt);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateSaveSlotAt, this, &MainWindow::StateSaveSlotAt);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateLoadUndo, this, &MainWindow::StateLoadUndo);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateSaveUndo, this, &MainWindow::StateSaveUndo);
|
|
|
|
connect(m_menu_bar, &MenuBar::StateSaveOldest, this, &MainWindow::StateSaveOldest);
|
|
|
|
connect(m_menu_bar, &MenuBar::SetStateSlot, this, &MainWindow::SetStateSlot);
|
|
|
|
|
2017-06-06 11:49:49 +00:00
|
|
|
// Options
|
|
|
|
connect(m_menu_bar, &MenuBar::ConfigureHotkeys, this, &MainWindow::ShowHotkeyDialog);
|
|
|
|
|
2017-06-14 09:58:11 +00:00
|
|
|
// Tools
|
|
|
|
connect(m_menu_bar, &MenuBar::PerformOnlineUpdate, this, &MainWindow::PerformOnlineUpdate);
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
// View
|
|
|
|
connect(m_menu_bar, &MenuBar::ShowTable, m_game_list, &GameList::SetTableView);
|
|
|
|
connect(m_menu_bar, &MenuBar::ShowList, m_game_list, &GameList::SetListView);
|
2017-05-08 17:03:59 +00:00
|
|
|
connect(m_menu_bar, &MenuBar::ColumnVisibilityToggled, m_game_list,
|
|
|
|
&GameList::OnColumnVisibilityToggled);
|
2016-06-24 08:43:46 +00:00
|
|
|
connect(m_menu_bar, &MenuBar::ShowAboutDialog, this, &MainWindow::ShowAboutDialog);
|
|
|
|
|
|
|
|
connect(this, &MainWindow::EmulationStarted, m_menu_bar, &MenuBar::EmulationStarted);
|
|
|
|
connect(this, &MainWindow::EmulationPaused, m_menu_bar, &MenuBar::EmulationPaused);
|
|
|
|
connect(this, &MainWindow::EmulationStopped, m_menu_bar, &MenuBar::EmulationStopped);
|
2017-05-09 16:49:10 +00:00
|
|
|
|
|
|
|
connect(this, &MainWindow::EmulationStarted, this,
|
|
|
|
[=]() { m_controllers_window->OnEmulationStateChanged(true); });
|
|
|
|
connect(this, &MainWindow::EmulationStopped, this,
|
|
|
|
[=]() { m_controllers_window->OnEmulationStateChanged(false); });
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2017-06-06 11:49:49 +00:00
|
|
|
void MainWindow::ConnectHotkeys()
|
|
|
|
{
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::ExitHotkey, this, &MainWindow::close);
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::PauseHotkey, this, &MainWindow::Pause);
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::StopHotkey, this, &MainWindow::Stop);
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::ScreenShotHotkey, this, &MainWindow::ScreenShot);
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::FullScreenHotkey, this, &MainWindow::FullScreen);
|
|
|
|
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::StateLoadSlotHotkey, this,
|
|
|
|
&MainWindow::StateLoadSlot);
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::StateSaveSlotHotkey, this,
|
|
|
|
&MainWindow::StateSaveSlot);
|
|
|
|
connect(m_hotkey_scheduler, &HotkeyScheduler::SetStateSlotHotkey, this,
|
|
|
|
&MainWindow::SetStateSlot);
|
|
|
|
}
|
|
|
|
|
2016-02-10 04:42:06 +00:00
|
|
|
void MainWindow::ConnectToolBar()
|
2015-11-27 08:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
addToolBar(m_tool_bar);
|
|
|
|
connect(m_tool_bar, &ToolBar::OpenPressed, this, &MainWindow::Open);
|
|
|
|
connect(m_tool_bar, &ToolBar::PlayPressed, this, &MainWindow::Play);
|
|
|
|
connect(m_tool_bar, &ToolBar::PausePressed, this, &MainWindow::Pause);
|
|
|
|
connect(m_tool_bar, &ToolBar::StopPressed, this, &MainWindow::Stop);
|
|
|
|
connect(m_tool_bar, &ToolBar::FullScreenPressed, this, &MainWindow::FullScreen);
|
|
|
|
connect(m_tool_bar, &ToolBar::ScreenShotPressed, this, &MainWindow::ScreenShot);
|
|
|
|
connect(m_tool_bar, &ToolBar::SettingsPressed, this, &MainWindow::ShowSettingsWindow);
|
2017-05-09 16:49:10 +00:00
|
|
|
connect(m_tool_bar, &ToolBar::ControllersPressed, this, &MainWindow::ShowControllersWindow);
|
2017-06-15 23:42:12 +00:00
|
|
|
connect(m_tool_bar, &ToolBar::GraphicsPressed, this, &MainWindow::ShowGraphicsWindow);
|
2015-12-04 04:41:17 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
connect(this, &MainWindow::EmulationStarted, m_tool_bar, &ToolBar::EmulationStarted);
|
|
|
|
connect(this, &MainWindow::EmulationPaused, m_tool_bar, &ToolBar::EmulationPaused);
|
|
|
|
connect(this, &MainWindow::EmulationStopped, m_tool_bar, &ToolBar::EmulationStopped);
|
2017-06-24 15:00:37 +00:00
|
|
|
|
|
|
|
connect(this, &MainWindow::EmulationStopped, [this] {
|
|
|
|
m_stop_requested = false;
|
|
|
|
m_render_widget->hide();
|
|
|
|
});
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 04:42:06 +00:00
|
|
|
void MainWindow::ConnectGameList()
|
2015-11-27 08:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
connect(m_game_list, &GameList::GameSelected, this, &MainWindow::Play);
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 04:42:06 +00:00
|
|
|
void MainWindow::ConnectRenderWidget()
|
2015-11-27 08:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
m_rendering_to_main = false;
|
|
|
|
m_render_widget->hide();
|
|
|
|
connect(m_render_widget, &RenderWidget::EscapePressed, this, &MainWindow::Stop);
|
|
|
|
connect(m_render_widget, &RenderWidget::Closed, this, &MainWindow::ForceStop);
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 04:42:06 +00:00
|
|
|
void MainWindow::ConnectStack()
|
2015-11-27 08:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
m_stack->setMinimumSize(800, 600);
|
|
|
|
m_stack->addWidget(m_game_list);
|
|
|
|
setCentralWidget(m_stack);
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::Open()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
QString file = QFileDialog::getOpenFileName(
|
|
|
|
this, tr("Select a File"), QDir::currentPath(),
|
2016-12-17 13:48:49 +00:00
|
|
|
tr("All GC/Wii files (*.elf *.dol *.gcm *.iso *.tgc *.wbfs *.ciso *.gcz *.wad);;"
|
2016-06-24 08:43:46 +00:00
|
|
|
"All Files (*)"));
|
|
|
|
if (!file.isEmpty())
|
|
|
|
StartGame(file);
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::Play()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// If we're in a paused game, start it up again.
|
|
|
|
// Otherwise, play the selected game, if there is one.
|
|
|
|
// Otherwise, play the default game.
|
|
|
|
// Otherwise, play the last played game, if there is one.
|
|
|
|
// Otherwise, prompt for a new game.
|
2017-02-05 12:39:58 +00:00
|
|
|
if (Core::GetState() == Core::State::Paused)
|
2016-06-24 08:43:46 +00:00
|
|
|
{
|
2017-02-05 12:39:58 +00:00
|
|
|
Core::SetState(Core::State::Running);
|
2016-06-24 08:43:46 +00:00
|
|
|
emit EmulationStarted();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QString selection = m_game_list->GetSelectedGame();
|
|
|
|
if (selection.length() > 0)
|
|
|
|
{
|
|
|
|
StartGame(selection);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-31 07:17:39 +00:00
|
|
|
QString default_path = Settings::Instance().GetDefaultGame();
|
2016-06-24 08:43:46 +00:00
|
|
|
if (!default_path.isEmpty() && QFile::exists(default_path))
|
|
|
|
{
|
|
|
|
StartGame(default_path);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-04 20:43:41 +00:00
|
|
|
Open();
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::Pause()
|
|
|
|
{
|
2017-02-05 12:39:58 +00:00
|
|
|
Core::SetState(Core::State::Paused);
|
2016-06-24 08:43:46 +00:00
|
|
|
emit EmulationPaused();
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MainWindow::Stop()
|
|
|
|
{
|
2017-06-24 15:00:37 +00:00
|
|
|
if (!Core::IsRunning())
|
|
|
|
return true;
|
|
|
|
|
2017-05-31 07:17:39 +00:00
|
|
|
if (Settings::Instance().GetConfirmStop())
|
2016-06-24 08:43:46 +00:00
|
|
|
{
|
2017-06-24 15:00:37 +00:00
|
|
|
const Core::State state = Core::GetState();
|
|
|
|
// Set to false when Netplay is running as a CPU thread
|
|
|
|
bool pause = true;
|
|
|
|
|
|
|
|
if (pause)
|
|
|
|
Core::SetState(Core::State::Paused);
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
QMessageBox::StandardButton confirm;
|
2017-06-24 15:00:37 +00:00
|
|
|
confirm = QMessageBox::question(m_render_widget, tr("Confirm"),
|
|
|
|
m_stop_requested ?
|
|
|
|
tr("A shutdown is already in progress. Unsaved data "
|
|
|
|
"may be lost if you stop the current emulation "
|
|
|
|
"before it completes. Force stop?") :
|
|
|
|
tr("Do you want to stop the current emulation?"));
|
|
|
|
if (pause)
|
|
|
|
Core::SetState(state);
|
2017-06-27 16:06:27 +00:00
|
|
|
|
|
|
|
if (confirm != QMessageBox::Yes)
|
|
|
|
return false;
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
2015-11-27 08:33:07 +00:00
|
|
|
|
2017-06-24 15:00:37 +00:00
|
|
|
// TODO: Add Movie shutdown
|
|
|
|
// TODO: Add Debugger shutdown
|
|
|
|
|
|
|
|
if (!m_stop_requested && UICommon::TriggerSTMPowerEvent())
|
2016-07-07 00:00:33 +00:00
|
|
|
{
|
2017-06-24 15:00:37 +00:00
|
|
|
m_stop_requested = true;
|
|
|
|
|
|
|
|
// Unpause because gracefully shutting down needs the game to actually request a shutdown.
|
|
|
|
// Do not unpause in debug mode to allow debugging until the complete shutdown.
|
|
|
|
if (Core::GetState() == Core::State::Paused)
|
|
|
|
Core::SetState(Core::State::Running);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ForceStop();
|
2015-11-27 08:33:07 +00:00
|
|
|
|
2016-07-07 00:00:33 +00:00
|
|
|
#ifdef Q_OS_WIN
|
2017-06-24 15:00:37 +00:00
|
|
|
// Allow windows to idle or turn off display again
|
|
|
|
SetThreadExecutionState(ES_CONTINUOUS);
|
2016-07-07 00:00:33 +00:00
|
|
|
#endif
|
2017-06-24 15:00:37 +00:00
|
|
|
return true;
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::ForceStop()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
BootManager::Stop();
|
|
|
|
HideRenderWidget();
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-15 01:56:40 +00:00
|
|
|
void MainWindow::Reset()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (Movie::IsRecordingInput())
|
2016-08-04 16:54:45 +00:00
|
|
|
Movie::SetReset(true);
|
2016-06-24 08:43:46 +00:00
|
|
|
ProcessorInterface::ResetButton_Tap();
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::FrameAdvance()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
Movie::DoFrameStep();
|
|
|
|
EmulationPaused();
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
2015-11-27 08:33:07 +00:00
|
|
|
void MainWindow::FullScreen()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// If the render widget is fullscreen we want to reset it to whatever is in
|
|
|
|
// settings. If it's set to be fullscreen then it just remakes the window,
|
|
|
|
// which probably isn't ideal.
|
|
|
|
bool was_fullscreen = m_render_widget->isFullScreen();
|
|
|
|
HideRenderWidget();
|
|
|
|
if (was_fullscreen)
|
|
|
|
ShowRenderWidget();
|
|
|
|
else
|
|
|
|
m_render_widget->showFullScreen();
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::ScreenShot()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
Core::SaveScreenShot();
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
2015-12-22 03:46:03 +00:00
|
|
|
void MainWindow::StartGame(const QString& path)
|
2015-11-27 08:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// If we're running, only start a new game once we've stopped the last.
|
2017-02-05 12:39:58 +00:00
|
|
|
if (Core::GetState() != Core::State::Uninitialized)
|
2016-06-24 08:43:46 +00:00
|
|
|
{
|
|
|
|
if (!Stop())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Boot up, show an error if it fails to load the game.
|
2017-05-27 13:43:40 +00:00
|
|
|
if (!BootManager::BootCore(BootParameters::GenerateFromFile(path.toStdString())))
|
2016-06-24 08:43:46 +00:00
|
|
|
{
|
|
|
|
QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ShowRenderWidget();
|
|
|
|
emit EmulationStarted();
|
2016-07-07 00:00:33 +00:00
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
// Prevents Windows from sleeping, turning off the display, or idling
|
|
|
|
EXECUTION_STATE shouldScreenSave =
|
|
|
|
SConfig::GetInstance().bDisableScreenSaver ? ES_DISPLAY_REQUIRED : 0;
|
|
|
|
SetThreadExecutionState(ES_CONTINUOUS | shouldScreenSave | ES_SYSTEM_REQUIRED);
|
|
|
|
#endif
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::ShowRenderWidget()
|
|
|
|
{
|
2017-05-31 07:17:39 +00:00
|
|
|
auto& settings = Settings::Instance();
|
2016-06-24 08:43:46 +00:00
|
|
|
if (settings.GetRenderToMain())
|
|
|
|
{
|
|
|
|
// If we're rendering to main, add it to the stack and update our title when necessary.
|
|
|
|
m_rendering_to_main = true;
|
|
|
|
m_stack->setCurrentIndex(m_stack->addWidget(m_render_widget));
|
|
|
|
connect(Host::GetInstance(), &Host::RequestTitle, this, &MainWindow::setWindowTitle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Otherwise, just show it.
|
|
|
|
m_rendering_to_main = false;
|
|
|
|
if (settings.GetFullScreen())
|
|
|
|
{
|
|
|
|
m_render_widget->showFullScreen();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-01 04:10:47 +00:00
|
|
|
m_render_widget->resize(settings.GetRenderWindowSize());
|
2016-06-24 08:43:46 +00:00
|
|
|
m_render_widget->showNormal();
|
|
|
|
}
|
|
|
|
}
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::HideRenderWidget()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (m_rendering_to_main)
|
|
|
|
{
|
|
|
|
// Remove the widget from the stack and reparent it to nullptr, so that it can draw
|
|
|
|
// itself in a new window if it wants. Disconnect the title updates.
|
|
|
|
m_stack->removeWidget(m_render_widget);
|
|
|
|
m_render_widget->setParent(nullptr);
|
|
|
|
m_rendering_to_main = false;
|
|
|
|
disconnect(Host::GetInstance(), &Host::RequestTitle, this, &MainWindow::setWindowTitle);
|
2017-06-05 18:36:30 +00:00
|
|
|
setWindowTitle(QString::fromStdString(scm_rev_str));
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
m_render_widget->hide();
|
2015-11-27 08:33:07 +00:00
|
|
|
}
|
2016-02-10 04:42:06 +00:00
|
|
|
|
2017-05-09 16:49:10 +00:00
|
|
|
void MainWindow::ShowControllersWindow()
|
|
|
|
{
|
|
|
|
m_controllers_window->show();
|
|
|
|
m_controllers_window->raise();
|
|
|
|
m_controllers_window->activateWindow();
|
|
|
|
}
|
|
|
|
|
2016-05-09 13:34:07 +00:00
|
|
|
void MainWindow::ShowSettingsWindow()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
m_settings_window->show();
|
|
|
|
m_settings_window->raise();
|
|
|
|
m_settings_window->activateWindow();
|
2016-05-09 13:34:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 11:59:44 +00:00
|
|
|
void MainWindow::ShowAboutDialog()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
AboutDialog* about = new AboutDialog(this);
|
|
|
|
about->show();
|
2016-02-11 11:59:44 +00:00
|
|
|
}
|
2016-02-15 01:56:40 +00:00
|
|
|
|
2017-06-06 11:49:49 +00:00
|
|
|
void MainWindow::ShowHotkeyDialog()
|
|
|
|
{
|
|
|
|
m_hotkey_window->ChangeMappingType(MappingWindow::Type::MAPPING_HOTKEYS);
|
|
|
|
m_hotkey_window->show();
|
|
|
|
m_hotkey_window->raise();
|
|
|
|
m_hotkey_window->activateWindow();
|
|
|
|
}
|
|
|
|
|
2017-06-15 23:42:12 +00:00
|
|
|
void MainWindow::ShowGraphicsWindow()
|
|
|
|
{
|
|
|
|
m_graphics_window->show();
|
|
|
|
m_graphics_window->raise();
|
|
|
|
m_graphics_window->activateWindow();
|
|
|
|
}
|
|
|
|
|
2016-02-15 01:56:40 +00:00
|
|
|
void MainWindow::StateLoad()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
QString path = QFileDialog::getOpenFileName(this, tr("Select a File"), QDir::currentPath(),
|
|
|
|
tr("All Save States (*.sav *.s##);; All Files (*)"));
|
|
|
|
State::LoadAs(path.toStdString());
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateSave()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
QString path = QFileDialog::getSaveFileName(this, tr("Select a File"), QDir::currentPath(),
|
|
|
|
tr("All Save States (*.sav *.s##);; All Files (*)"));
|
|
|
|
State::SaveAs(path.toStdString());
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateLoadSlot()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
State::Load(m_state_slot);
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateSaveSlot()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
State::Save(m_state_slot, true);
|
|
|
|
m_menu_bar->UpdateStateSlotMenu();
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateLoadSlotAt(int slot)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
State::Load(slot);
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateSaveSlotAt(int slot)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
State::Save(slot, true);
|
|
|
|
m_menu_bar->UpdateStateSlotMenu();
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateLoadUndo()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
State::UndoLoadState();
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateSaveUndo()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
State::UndoSaveState();
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::StateSaveOldest()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
State::SaveFirstSaved();
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::SetStateSlot(int slot)
|
|
|
|
{
|
2017-05-31 07:17:39 +00:00
|
|
|
Settings::Instance().SetStateSlot(slot);
|
2016-06-24 08:43:46 +00:00
|
|
|
m_state_slot = slot;
|
2016-02-15 01:56:40 +00:00
|
|
|
}
|
2017-06-24 15:00:37 +00:00
|
|
|
|
2017-06-14 09:58:11 +00:00
|
|
|
void MainWindow::PerformOnlineUpdate(const std::string& region)
|
|
|
|
{
|
|
|
|
WiiUpdate::PerformOnlineUpdate(region, this);
|
|
|
|
// Since the update may have installed a newer system menu, refresh the tools menu.
|
|
|
|
m_menu_bar->UpdateToolsMenu(false);
|
|
|
|
}
|
|
|
|
|
2017-06-24 15:00:37 +00:00
|
|
|
bool MainWindow::eventFilter(QObject* object, QEvent* event)
|
|
|
|
{
|
|
|
|
if (event->type() == QEvent::Close && !Stop())
|
|
|
|
{
|
|
|
|
static_cast<QCloseEvent*>(event)->ignore();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2017-06-26 21:22:40 +00:00
|
|
|
|
|
|
|
void MainWindow::dragEnterEvent(QDragEnterEvent* event)
|
|
|
|
{
|
|
|
|
if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1)
|
|
|
|
event->acceptProposedAction();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::dropEvent(QDropEvent* event)
|
|
|
|
{
|
|
|
|
const auto& urls = event->mimeData()->urls();
|
|
|
|
if (urls.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto& url = urls[0];
|
|
|
|
QFileInfo file_info(url.toLocalFile());
|
|
|
|
|
|
|
|
auto path = file_info.filePath();
|
|
|
|
|
|
|
|
if (!file_info.exists() || !file_info.isReadable())
|
|
|
|
{
|
|
|
|
QMessageBox::critical(this, tr("Error"), tr("Failed to open '%1'").arg(path));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file_info.isFile())
|
|
|
|
{
|
|
|
|
StartGame(path);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto& settings = Settings::Instance();
|
|
|
|
|
|
|
|
if (settings.GetPaths().size() != 0)
|
|
|
|
{
|
|
|
|
if (QMessageBox::question(
|
|
|
|
this, tr("Confirm"),
|
|
|
|
tr("Do you want to add \"%1\" to the list of Game Paths?").arg(path)) !=
|
|
|
|
QMessageBox::Yes)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
settings.AddPath(path);
|
|
|
|
}
|
|
|
|
}
|