|
|
|
@ -17,6 +17,7 @@
|
|
|
|
|
#include "citra_qt/game_list.h"
|
|
|
|
|
#include "citra_qt/hotkeys.h"
|
|
|
|
|
#include "citra_qt/main.h"
|
|
|
|
|
#include "citra_qt/ui_settings.h"
|
|
|
|
|
|
|
|
|
|
// Debugger
|
|
|
|
|
#include "citra_qt/debugger/callstack.h"
|
|
|
|
@ -51,12 +52,10 @@
|
|
|
|
|
|
|
|
|
|
#include "video_core/video_core.h"
|
|
|
|
|
|
|
|
|
|
GMainWindow::GMainWindow() : emu_thread(nullptr)
|
|
|
|
|
GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr)
|
|
|
|
|
{
|
|
|
|
|
Pica::g_debug_context = Pica::DebugContext::Construct();
|
|
|
|
|
|
|
|
|
|
Config config;
|
|
|
|
|
|
|
|
|
|
ui.setupUi(this);
|
|
|
|
|
statusBar()->hide();
|
|
|
|
|
|
|
|
|
@ -134,25 +133,21 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
|
|
|
|
|
setGeometry(x, y, w, h);
|
|
|
|
|
|
|
|
|
|
// Restore UI state
|
|
|
|
|
QSettings settings;
|
|
|
|
|
restoreGeometry(UISettings::values.geometry);
|
|
|
|
|
restoreState(UISettings::values.state);
|
|
|
|
|
render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
|
|
|
|
|
microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);
|
|
|
|
|
microProfileDialog->setVisible(UISettings::values.microprofile_visible);
|
|
|
|
|
|
|
|
|
|
settings.beginGroup("UILayout");
|
|
|
|
|
restoreGeometry(settings.value("geometry").toByteArray());
|
|
|
|
|
restoreState(settings.value("state").toByteArray());
|
|
|
|
|
render_window->restoreGeometry(settings.value("geometryRenderWindow").toByteArray());
|
|
|
|
|
microProfileDialog->restoreGeometry(settings.value("microProfileDialogGeometry").toByteArray());
|
|
|
|
|
microProfileDialog->setVisible(settings.value("microProfileDialogVisible").toBool());
|
|
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
|
|
game_list->LoadInterfaceLayout(settings);
|
|
|
|
|
game_list->LoadInterfaceLayout();
|
|
|
|
|
|
|
|
|
|
GDBStub::ToggleServer(Settings::values.use_gdbstub);
|
|
|
|
|
GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port));
|
|
|
|
|
|
|
|
|
|
ui.action_Single_Window_Mode->setChecked(settings.value("singleWindowMode", true).toBool());
|
|
|
|
|
ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode);
|
|
|
|
|
ToggleWindowMode();
|
|
|
|
|
|
|
|
|
|
ui.actionDisplay_widget_title_bars->setChecked(settings.value("displayTitleBars", true).toBool());
|
|
|
|
|
ui.actionDisplay_widget_title_bars->setChecked(UISettings::values.display_titlebar);
|
|
|
|
|
OnDisplayTitleBars(ui.actionDisplay_widget_title_bars->isChecked());
|
|
|
|
|
|
|
|
|
|
// Prepare actions for recent files
|
|
|
|
@ -165,12 +160,10 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
|
|
|
|
|
}
|
|
|
|
|
UpdateRecentFiles();
|
|
|
|
|
|
|
|
|
|
confirm_before_closing = settings.value("confirmClose", true).toBool();
|
|
|
|
|
|
|
|
|
|
// Setup connections
|
|
|
|
|
connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)));
|
|
|
|
|
connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), Qt::DirectConnection);
|
|
|
|
|
connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure()));
|
|
|
|
|
connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()));
|
|
|
|
|
connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),Qt::DirectConnection);
|
|
|
|
|
connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap()));
|
|
|
|
|
connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, SLOT(OnMenuSelectGameListRoot()));
|
|
|
|
|
connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame()));
|
|
|
|
@ -191,7 +184,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
|
|
|
|
|
// Setup hotkeys
|
|
|
|
|
RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
|
|
|
|
|
RegisterHotkey("Main Window", "Start Emulation");
|
|
|
|
|
LoadHotkeys(settings);
|
|
|
|
|
LoadHotkeys();
|
|
|
|
|
|
|
|
|
|
connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile()));
|
|
|
|
|
connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame()));
|
|
|
|
@ -201,7 +194,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
|
|
|
|
|
|
|
|
|
|
show();
|
|
|
|
|
|
|
|
|
|
game_list->PopulateAsync(settings.value("gameListRootDir", ".").toString(), settings.value("gameListDeepScan", false).toBool());
|
|
|
|
|
game_list->PopulateAsync(UISettings::values.gamedir_path, UISettings::values.gamedir_deepscan);
|
|
|
|
|
|
|
|
|
|
QStringList args = QApplication::arguments();
|
|
|
|
|
if (args.length() >= 2) {
|
|
|
|
@ -365,32 +358,24 @@ void GMainWindow::ShutdownGame() {
|
|
|
|
|
emulation_running = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GMainWindow::StoreRecentFile(const std::string& filename)
|
|
|
|
|
{
|
|
|
|
|
QSettings settings;
|
|
|
|
|
QStringList recent_files = settings.value("recentFiles").toStringList();
|
|
|
|
|
recent_files.prepend(QString::fromStdString(filename));
|
|
|
|
|
recent_files.removeDuplicates();
|
|
|
|
|
while (recent_files.size() > max_recent_files_item) {
|
|
|
|
|
recent_files.removeLast();
|
|
|
|
|
void GMainWindow::StoreRecentFile(const std::string& filename) {
|
|
|
|
|
UISettings::values.recent_files.prepend(QString::fromStdString(filename));
|
|
|
|
|
UISettings::values.recent_files.removeDuplicates();
|
|
|
|
|
while (UISettings::values.recent_files.size() > max_recent_files_item) {
|
|
|
|
|
UISettings::values.recent_files.removeLast();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
settings.setValue("recentFiles", recent_files);
|
|
|
|
|
|
|
|
|
|
UpdateRecentFiles();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GMainWindow::UpdateRecentFiles() {
|
|
|
|
|
QSettings settings;
|
|
|
|
|
QStringList recent_files = settings.value("recentFiles").toStringList();
|
|
|
|
|
|
|
|
|
|
unsigned int num_recent_files = std::min(recent_files.size(), static_cast<int>(max_recent_files_item));
|
|
|
|
|
unsigned int num_recent_files = std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item));
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < num_recent_files; i++) {
|
|
|
|
|
QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(recent_files[i]).fileName());
|
|
|
|
|
QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(UISettings::values.recent_files[i]).fileName());
|
|
|
|
|
actions_recent_files[i]->setText(text);
|
|
|
|
|
actions_recent_files[i]->setData(recent_files[i]);
|
|
|
|
|
actions_recent_files[i]->setToolTip(recent_files[i]);
|
|
|
|
|
actions_recent_files[i]->setData(UISettings::values.recent_files[i]);
|
|
|
|
|
actions_recent_files[i]->setToolTip(UISettings::values.recent_files[i]);
|
|
|
|
|
actions_recent_files[i]->setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -411,36 +396,28 @@ void GMainWindow::OnGameListLoadFile(QString game_path) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GMainWindow::OnMenuLoadFile() {
|
|
|
|
|
QSettings settings;
|
|
|
|
|
QString rom_path = settings.value("romsPath", QString()).toString();
|
|
|
|
|
|
|
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), rom_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)"));
|
|
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)"));
|
|
|
|
|
if (!filename.isEmpty()) {
|
|
|
|
|
settings.setValue("romsPath", QFileInfo(filename).path());
|
|
|
|
|
UISettings::values.roms_path = QFileInfo(filename).path();
|
|
|
|
|
|
|
|
|
|
BootGame(filename.toLocal8Bit().data());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GMainWindow::OnMenuLoadSymbolMap() {
|
|
|
|
|
QSettings settings;
|
|
|
|
|
QString symbol_path = settings.value("symbolsPath", QString()).toString();
|
|
|
|
|
|
|
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), symbol_path, tr("Symbol map (*)"));
|
|
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)"));
|
|
|
|
|
if (!filename.isEmpty()) {
|
|
|
|
|
settings.setValue("symbolsPath", QFileInfo(filename).path());
|
|
|
|
|
UISettings::values.symbols_path = QFileInfo(filename).path();
|
|
|
|
|
|
|
|
|
|
LoadSymbolMap(filename.toLocal8Bit().data());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GMainWindow::OnMenuSelectGameListRoot() {
|
|
|
|
|
QSettings settings;
|
|
|
|
|
|
|
|
|
|
QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
|
|
|
|
|
if (!dir_path.isEmpty()) {
|
|
|
|
|
settings.setValue("gameListRootDir", dir_path);
|
|
|
|
|
game_list->PopulateAsync(dir_path, settings.value("gameListDeepScan").toBool());
|
|
|
|
|
UISettings::values.gamedir_path = dir_path;
|
|
|
|
|
game_list->PopulateAsync(dir_path, UISettings::values.gamedir_deepscan);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -456,10 +433,7 @@ void GMainWindow::OnMenuRecentFile() {
|
|
|
|
|
// Display an error message and remove the file from the list.
|
|
|
|
|
QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename));
|
|
|
|
|
|
|
|
|
|
QSettings settings;
|
|
|
|
|
QStringList recent_files = settings.value("recentFiles").toStringList();
|
|
|
|
|
recent_files.removeOne(filename);
|
|
|
|
|
settings.setValue("recentFiles", recent_files);
|
|
|
|
|
UISettings::values.recent_files.removeOne(filename);
|
|
|
|
|
UpdateRecentFiles();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -536,23 +510,18 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Save window layout
|
|
|
|
|
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra");
|
|
|
|
|
UISettings::values.geometry = saveGeometry();
|
|
|
|
|
UISettings::values.state = saveState();
|
|
|
|
|
UISettings::values.renderwindow_geometry = render_window->saveGeometry();
|
|
|
|
|
UISettings::values.microprofile_geometry = microProfileDialog->saveGeometry();
|
|
|
|
|
UISettings::values.microprofile_visible = microProfileDialog->isVisible();
|
|
|
|
|
|
|
|
|
|
settings.beginGroup("UILayout");
|
|
|
|
|
settings.setValue("geometry", saveGeometry());
|
|
|
|
|
settings.setValue("state", saveState());
|
|
|
|
|
settings.setValue("geometryRenderWindow", render_window->saveGeometry());
|
|
|
|
|
settings.setValue("microProfileDialogGeometry", microProfileDialog->saveGeometry());
|
|
|
|
|
settings.setValue("microProfileDialogVisible", microProfileDialog->isVisible());
|
|
|
|
|
settings.endGroup();
|
|
|
|
|
UISettings::values.single_window_mode = ui.action_Single_Window_Mode->isChecked();
|
|
|
|
|
UISettings::values.display_titlebar = ui.actionDisplay_widget_title_bars->isChecked();
|
|
|
|
|
UISettings::values.first_start = false;
|
|
|
|
|
|
|
|
|
|
settings.setValue("singleWindowMode", ui.action_Single_Window_Mode->isChecked());
|
|
|
|
|
settings.setValue("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked());
|
|
|
|
|
settings.setValue("firstStart", false);
|
|
|
|
|
settings.setValue("confirmClose", confirm_before_closing);
|
|
|
|
|
game_list->SaveInterfaceLayout(settings);
|
|
|
|
|
SaveHotkeys(settings);
|
|
|
|
|
game_list->SaveInterfaceLayout();
|
|
|
|
|
SaveHotkeys();
|
|
|
|
|
|
|
|
|
|
// Shutdown session if the emu thread is active...
|
|
|
|
|
if (emu_thread != nullptr)
|
|
|
|
@ -577,7 +546,6 @@ int main(int argc, char* argv[]) {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Init settings params
|
|
|
|
|
QSettings::setDefaultFormat(QSettings::IniFormat);
|
|
|
|
|
QCoreApplication::setOrganizationName("Citra team");
|
|
|
|
|
QCoreApplication::setApplicationName("Citra");
|
|
|
|
|
|
|
|
|
|