mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
59bdeb411c
This lets us sort by the underlying integers while only displaying the icons. Currently, in both DolphinQt and DolphinQt2, we display both the icon and the integer, but cut off the column width to not show the integer. We also currently sort by the size's formatted string, not by the size itself, which leads to "1 MB" sorting to less than "2 KB". This commit fixes these issues. In the future, we can use the filter methods here to allow for searching for games.
407 lines
12 KiB
C++
407 lines
12 KiB
C++
// Copyright 2015 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <QAction>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QFileDialog>
|
|
#include <QIcon>
|
|
#include <QMenu>
|
|
#include <QMenuBar>
|
|
#include <QMessageBox>
|
|
|
|
#include "Common/FileUtil.h"
|
|
#include "Core/BootManager.h"
|
|
#include "Core/ConfigManager.h"
|
|
#include "Core/Core.h"
|
|
#include "DolphinQt2/Host.h"
|
|
#include "DolphinQt2/MainWindow.h"
|
|
#include "DolphinQt2/Resources.h"
|
|
#include "DolphinQt2/GameList/GameListModel.h"
|
|
|
|
MainWindow::MainWindow() : QMainWindow(nullptr)
|
|
{
|
|
setWindowTitle(tr("Dolphin"));
|
|
setWindowIcon(QIcon(Resources::GetMisc(Resources::LOGO_SMALL)));
|
|
|
|
MakeToolBar();
|
|
MakeGameList();
|
|
MakeRenderWidget();
|
|
MakeStack();
|
|
MakeMenus();
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
m_render_widget->deleteLater();
|
|
}
|
|
|
|
void MainWindow::MakeMenus()
|
|
{
|
|
MakeFileMenu();
|
|
menuBar()->addMenu(tr("Emulation"));
|
|
menuBar()->addMenu(tr("Movie"));
|
|
menuBar()->addMenu(tr("Options"));
|
|
menuBar()->addMenu(tr("Tools"));
|
|
MakeViewMenu();
|
|
menuBar()->addMenu(tr("Help"));
|
|
}
|
|
|
|
void MainWindow::MakeFileMenu()
|
|
{
|
|
QMenu* file_menu = menuBar()->addMenu(tr("File"));
|
|
file_menu->addAction(tr("Open"), this, SLOT(Open()));
|
|
file_menu->addAction(tr("Exit"), this, SLOT(close()));
|
|
}
|
|
|
|
void MainWindow::MakeViewMenu()
|
|
{
|
|
QMenu* view_menu = menuBar()->addMenu(tr("View"));
|
|
AddTableColumnsMenu(view_menu);
|
|
AddListTypePicker(view_menu);
|
|
}
|
|
|
|
void MainWindow::AddTableColumnsMenu(QMenu* view_menu)
|
|
{
|
|
QActionGroup* column_group = new QActionGroup(this);
|
|
QMenu* cols_menu = view_menu->addMenu(tr("Table Columns"));
|
|
column_group->setExclusive(false);
|
|
|
|
QStringList col_names{
|
|
tr("Platform"),
|
|
tr("ID"),
|
|
tr("Banner"),
|
|
tr("Title"),
|
|
tr("Description"),
|
|
tr("Maker"),
|
|
tr("Size"),
|
|
tr("Country"),
|
|
tr("Quality")
|
|
};
|
|
// TODO we'll need to update SConfig with the extra columns. Then we can
|
|
// clean this up significantly.
|
|
QList<bool> show_cols{
|
|
SConfig::GetInstance().m_showSystemColumn,
|
|
SConfig::GetInstance().m_showIDColumn,
|
|
SConfig::GetInstance().m_showBannerColumn,
|
|
true,
|
|
false,
|
|
SConfig::GetInstance().m_showMakerColumn,
|
|
SConfig::GetInstance().m_showSizeColumn,
|
|
SConfig::GetInstance().m_showRegionColumn,
|
|
SConfig::GetInstance().m_showStateColumn,
|
|
};
|
|
// - 1 because we never show COL_LARGE_ICON column in the table.
|
|
for (int i = 0; i < GameListModel::NUM_COLS - 1; i++)
|
|
{
|
|
QAction* action = column_group->addAction(cols_menu->addAction(col_names[i]));
|
|
action->setCheckable(true);
|
|
action->setChecked(show_cols[i]);
|
|
m_game_list->SetViewColumn(i, show_cols[i]);
|
|
connect(action, &QAction::triggered, [=]()
|
|
{
|
|
m_game_list->SetViewColumn(i, action->isChecked());
|
|
switch (i)
|
|
{
|
|
case GameListModel::COL_PLATFORM:
|
|
SConfig::GetInstance().m_showSystemColumn = action->isChecked();
|
|
break;
|
|
case GameListModel::COL_ID:
|
|
SConfig::GetInstance().m_showIDColumn = action->isChecked();
|
|
break;
|
|
case GameListModel::COL_TITLE:
|
|
SConfig::GetInstance().m_showBannerColumn = action->isChecked();
|
|
break;
|
|
case GameListModel::COL_MAKER:
|
|
SConfig::GetInstance().m_showMakerColumn = action->isChecked();
|
|
break;
|
|
case GameListModel::COL_SIZE:
|
|
SConfig::GetInstance().m_showSizeColumn = action->isChecked();
|
|
break;
|
|
case GameListModel::COL_COUNTRY:
|
|
SConfig::GetInstance().m_showRegionColumn = action->isChecked();
|
|
break;
|
|
case GameListModel::COL_RATING:
|
|
SConfig::GetInstance().m_showStateColumn = action->isChecked();
|
|
break;
|
|
default: break;
|
|
}
|
|
SConfig::GetInstance().SaveSettings();
|
|
});
|
|
}
|
|
}
|
|
|
|
void MainWindow::AddListTypePicker(QMenu* view_menu)
|
|
{
|
|
QActionGroup* list_group = new QActionGroup(this);
|
|
view_menu->addSection(tr("List Type"));
|
|
list_group->setExclusive(true);
|
|
|
|
QAction* set_table = list_group->addAction(view_menu->addAction(tr("Table")));
|
|
QAction* set_list = list_group->addAction(view_menu->addAction(tr("List")));
|
|
|
|
set_table->setCheckable(true);
|
|
set_table->setChecked(true);
|
|
set_list->setCheckable(true);
|
|
|
|
connect(set_table, &QAction::triggered, m_game_list, &GameList::SetTableView);
|
|
connect(set_list, &QAction::triggered, m_game_list, &GameList::SetListView);
|
|
}
|
|
|
|
void MainWindow::MakeToolBar()
|
|
{
|
|
setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
m_tool_bar = addToolBar(tr("ToolBar"));
|
|
m_tool_bar->setMovable(false);
|
|
m_tool_bar->setFloatable(false);
|
|
|
|
PopulateToolBar();
|
|
}
|
|
|
|
void MainWindow::MakeGameList()
|
|
{
|
|
m_game_list = new GameList(this);
|
|
connect(m_game_list, &GameList::GameSelected, this, &MainWindow::Play);
|
|
}
|
|
|
|
void MainWindow::MakeRenderWidget()
|
|
{
|
|
m_render_widget = new RenderWidget;
|
|
connect(m_render_widget, &RenderWidget::EscapePressed, this, &MainWindow::Stop);
|
|
connect(m_render_widget, &RenderWidget::Closed, this, &MainWindow::ForceStop);
|
|
m_render_widget->hide();
|
|
m_rendering_to_main = false;
|
|
}
|
|
|
|
void MainWindow::MakeStack()
|
|
{
|
|
m_stack = new QStackedWidget;
|
|
m_stack->setMinimumSize(800, 600);
|
|
m_stack->addWidget(m_game_list);
|
|
setCentralWidget(m_stack);
|
|
}
|
|
|
|
void MainWindow::PopulateToolBar()
|
|
{
|
|
m_tool_bar->clear();
|
|
|
|
QString dir = QString::fromStdString(File::GetThemeDir(SConfig::GetInstance().theme_name));
|
|
m_tool_bar->addAction(
|
|
QIcon(dir + QStringLiteral("open.png")), tr("Open"),
|
|
this, SLOT(Open()));
|
|
m_tool_bar->addAction(
|
|
QIcon(dir + QStringLiteral("browse.png")), tr("Browse"),
|
|
this, SLOT(Browse()));
|
|
|
|
m_tool_bar->addSeparator();
|
|
|
|
QAction* play_action = m_tool_bar->addAction(
|
|
QIcon(dir + QStringLiteral("play.png")), tr("Play"),
|
|
this, SLOT(Play()));
|
|
connect(this, &MainWindow::EmulationStarted, [=](){ play_action->setEnabled(false); });
|
|
connect(this, &MainWindow::EmulationPaused, [=](){ play_action->setEnabled(true); });
|
|
connect(this, &MainWindow::EmulationStopped, [=](){ play_action->setEnabled(true); });
|
|
|
|
QAction* pause_action = m_tool_bar->addAction(
|
|
QIcon(dir + QStringLiteral("pause.png")), tr("Pause"),
|
|
this, SLOT(Pause()));
|
|
pause_action->setEnabled(false);
|
|
connect(this, &MainWindow::EmulationStarted, [=](){ pause_action->setEnabled(true); });
|
|
connect(this, &MainWindow::EmulationPaused, [=](){ pause_action->setEnabled(false); });
|
|
connect(this, &MainWindow::EmulationStopped, [=](){ pause_action->setEnabled(false); });
|
|
|
|
QAction* stop_action = m_tool_bar->addAction(
|
|
QIcon(dir + QStringLiteral("stop.png")), tr("Stop"),
|
|
this, SLOT(Stop()));
|
|
stop_action->setEnabled(false);
|
|
connect(this, &MainWindow::EmulationStarted, [=](){ stop_action->setEnabled(true); });
|
|
connect(this, &MainWindow::EmulationPaused, [=](){ stop_action->setEnabled(true); });
|
|
connect(this, &MainWindow::EmulationStopped, [=](){ stop_action->setEnabled(false); });
|
|
|
|
QAction* fullscreen_action = m_tool_bar->addAction(
|
|
QIcon(dir + QStringLiteral("fullscreen.png")), tr("Full Screen"),
|
|
this, SLOT(FullScreen()));
|
|
fullscreen_action->setEnabled(false);
|
|
connect(this, &MainWindow::EmulationStarted, [=](){ fullscreen_action->setEnabled(true); });
|
|
connect(this, &MainWindow::EmulationStopped, [=](){ fullscreen_action->setEnabled(false); });
|
|
|
|
QAction* screenshot_action = m_tool_bar->addAction(
|
|
QIcon(dir + QStringLiteral("screenshot.png")), tr("Screen Shot"),
|
|
this, SLOT(ScreenShot()));
|
|
screenshot_action->setEnabled(false);
|
|
connect(this, &MainWindow::EmulationStarted, [=](){ screenshot_action->setEnabled(true); });
|
|
connect(this, &MainWindow::EmulationStopped, [=](){ screenshot_action->setEnabled(false); });
|
|
|
|
m_tool_bar->addSeparator();
|
|
m_tool_bar->addAction(QIcon(dir + QStringLiteral("config.png")), tr("Settings"))->setEnabled(false);
|
|
m_tool_bar->addAction(QIcon(dir + QStringLiteral("graphics.png")), tr("Graphics"))->setEnabled(false);
|
|
m_tool_bar->addAction(QIcon(dir + QStringLiteral("classic.png")), tr("Controllers"))->setEnabled(false);
|
|
}
|
|
|
|
void MainWindow::Open()
|
|
{
|
|
QString file = QFileDialog::getOpenFileName(this,
|
|
tr("Select a File"),
|
|
QDir::currentPath(),
|
|
tr("All GC/Wii files (*.elf *.dol *.gcm *.iso *.wbfs *.ciso *.gcz *.wad);;"
|
|
"All Files (*)"));
|
|
if (!file.isEmpty())
|
|
StartGame(file);
|
|
}
|
|
|
|
void MainWindow::Browse()
|
|
{
|
|
QString dir = QFileDialog::getExistingDirectory(this,
|
|
tr("Select a Directory"),
|
|
QDir::currentPath());
|
|
if (!dir.isEmpty())
|
|
{
|
|
std::vector<std::string>& iso_folders = SConfig::GetInstance().m_ISOFolder;
|
|
auto found = std::find(iso_folders.begin(), iso_folders.end(), dir.toStdString());
|
|
if (found == iso_folders.end())
|
|
{
|
|
iso_folders.push_back(dir.toStdString());
|
|
SConfig::GetInstance().SaveSettings();
|
|
emit m_game_list->DirectoryAdded(dir);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::Play()
|
|
{
|
|
// If we're in a paused game, start it up again.
|
|
// Otherwise, play the selected game, if there is one.
|
|
// Otherwise, play the last played game, if there is one.
|
|
// Otherwise, prompt for a new game.
|
|
if (Core::GetState() == Core::CORE_PAUSE)
|
|
{
|
|
Core::SetState(Core::CORE_RUN);
|
|
emit EmulationStarted();
|
|
}
|
|
else
|
|
{
|
|
QString selection = m_game_list->GetSelectedGame();
|
|
if (selection.length() > 0)
|
|
{
|
|
StartGame(selection);
|
|
}
|
|
else
|
|
{
|
|
QString path = QString::fromStdString(SConfig::GetInstance().m_LastFilename);
|
|
if (QFile::exists(path))
|
|
StartGame(path);
|
|
else
|
|
Open();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::Pause()
|
|
{
|
|
Core::SetState(Core::CORE_PAUSE);
|
|
emit EmulationPaused();
|
|
}
|
|
|
|
bool MainWindow::Stop()
|
|
{
|
|
bool stop = true;
|
|
if (SConfig::GetInstance().bConfirmStop)
|
|
{
|
|
// We could pause the game here and resume it if they say no.
|
|
QMessageBox::StandardButton confirm;
|
|
confirm = QMessageBox::question(m_render_widget, tr("Confirm"), tr("Stop emulation?"));
|
|
stop = (confirm == QMessageBox::Yes);
|
|
}
|
|
|
|
if (stop)
|
|
ForceStop();
|
|
|
|
return stop;
|
|
}
|
|
|
|
void MainWindow::ForceStop()
|
|
{
|
|
BootManager::Stop();
|
|
HideRenderWidget();
|
|
emit EmulationStopped();
|
|
}
|
|
|
|
void MainWindow::FullScreen()
|
|
{
|
|
// If the render widget is fullscreen we want to reset it to whatever is in
|
|
// SConfig. 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();
|
|
}
|
|
|
|
void MainWindow::ScreenShot()
|
|
{
|
|
Core::SaveScreenShot();
|
|
}
|
|
|
|
void MainWindow::StartGame(QString path)
|
|
{
|
|
// If we're running, only start a new game once we've stopped the last.
|
|
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
|
{
|
|
if (!Stop())
|
|
return;
|
|
}
|
|
// Boot up, show an error if it fails to load the game.
|
|
if (!BootManager::BootCore(path.toStdString()))
|
|
{
|
|
QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
|
|
return;
|
|
}
|
|
ShowRenderWidget();
|
|
emit EmulationStarted();
|
|
}
|
|
|
|
void MainWindow::ShowRenderWidget()
|
|
{
|
|
if (SConfig::GetInstance().bRenderToMain)
|
|
{
|
|
// 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 (SConfig::GetInstance().bFullscreen)
|
|
{
|
|
m_render_widget->showFullScreen();
|
|
}
|
|
else
|
|
{
|
|
m_render_widget->setFixedSize(
|
|
SConfig::GetInstance().iRenderWindowWidth,
|
|
SConfig::GetInstance().iRenderWindowHeight);
|
|
m_render_widget->showNormal();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::HideRenderWidget()
|
|
{
|
|
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);
|
|
setWindowTitle(tr("Dolphin"));
|
|
}
|
|
m_render_widget->hide();
|
|
}
|