diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index feaac4a090..42a42bfaa8 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -32,7 +32,6 @@ set(SRCS Config/Mapping/WiimoteEmuExtension.cpp Config/Mapping/WiimoteEmuGeneral.cpp Config/Mapping/WiimoteEmuMotionControl.cpp - Config/PathDialog.cpp Config/PropertiesDialog.cpp Config/SettingsWindow.cpp GameList/GameFile.cpp @@ -40,9 +39,11 @@ set(SRCS GameList/GameListModel.cpp GameList/GameTracker.cpp GameList/ListProxyModel.cpp + QtUtils/DoubleClickEventFilter.cpp QtUtils/ElidedButton.cpp Settings/GeneralPane.cpp Settings/InterfacePane.cpp + Settings/PathPane.cpp ) list(APPEND LIBS core uicommon) diff --git a/Source/Core/DolphinQt2/Config/ControllersWindow.cpp b/Source/Core/DolphinQt2/Config/ControllersWindow.cpp index 84490433f5..f7fb269129 100644 --- a/Source/Core/DolphinQt2/Config/ControllersWindow.cpp +++ b/Source/Core/DolphinQt2/Config/ControllersWindow.cpp @@ -371,7 +371,7 @@ void ControllersWindow::OnWiimoteRefreshPressed() void ControllersWindow::OnEmulationStateChanged(bool running) { - if (!Settings().IsWiiGameRunning() || NetPlay::IsNetPlayRunning()) + if (!Settings::Instance().IsWiiGameRunning() || NetPlay::IsNetPlayRunning()) { m_wiimote_sync->setEnabled(!running); m_wiimote_reset->setEnabled(!running); @@ -383,7 +383,7 @@ void ControllersWindow::OnEmulationStateChanged(bool running) m_wiimote_emu->setEnabled(!running); m_wiimote_passthrough->setEnabled(!running); - if (!Settings().IsWiiGameRunning()) + if (!Settings::Instance().IsWiiGameRunning()) { m_wiimote_real_balance_board->setEnabled(!running); m_wiimote_continuous_scanning->setEnabled(!running); @@ -471,33 +471,35 @@ void ControllersWindow::UnimplementedButton() void ControllersWindow::LoadSettings() { + auto& settings = Settings::Instance(); for (size_t i = 0; i < m_wiimote_groups.size(); i++) { - m_gc_controller_boxes[i]->setCurrentIndex(ToGCMenuIndex(Settings().GetSIDevice(i))); + m_gc_controller_boxes[i]->setCurrentIndex(ToGCMenuIndex(settings.GetSIDevice(i))); m_wiimote_boxes[i]->setCurrentIndex(ToWiimoteMenuIndex(g_wiimote_sources[i])); } m_wiimote_real_balance_board->setChecked(g_wiimote_sources[WIIMOTE_BALANCE_BOARD] == WIIMOTE_SRC_REAL); - m_wiimote_speaker_data->setChecked(Settings().IsWiimoteSpeakerEnabled()); - m_wiimote_continuous_scanning->setChecked(Settings().IsContinuousScanningEnabled()); + m_wiimote_speaker_data->setChecked(settings.IsWiimoteSpeakerEnabled()); + m_wiimote_continuous_scanning->setChecked(settings.IsContinuousScanningEnabled()); - m_advanced_bg_input->setChecked(Settings().IsBackgroundInputEnabled()); + m_advanced_bg_input->setChecked(settings.IsBackgroundInputEnabled()); - if (Settings().IsBluetoothPassthroughEnabled()) + if (settings.IsBluetoothPassthroughEnabled()) m_wiimote_passthrough->setChecked(true); else m_wiimote_emu->setChecked(true); - OnWiimoteModeChanged(Settings().IsBluetoothPassthroughEnabled()); + OnWiimoteModeChanged(settings.IsBluetoothPassthroughEnabled()); } void ControllersWindow::SaveSettings() { - Settings().SetWiimoteSpeakerEnabled(m_wiimote_speaker_data->isChecked()); - Settings().SetContinuousScanningEnabled(m_wiimote_continuous_scanning->isChecked()); + auto& settings = Settings::Instance(); + settings.SetWiimoteSpeakerEnabled(m_wiimote_speaker_data->isChecked()); + settings.SetContinuousScanningEnabled(m_wiimote_continuous_scanning->isChecked()); - Settings().SetBluetoothPassthroughEnabled(m_wiimote_passthrough->isChecked()); - Settings().SetBackgroundInputEnabled(m_advanced_bg_input->isChecked()); + settings.SetBluetoothPassthroughEnabled(m_wiimote_passthrough->isChecked()); + settings.SetBackgroundInputEnabled(m_advanced_bg_input->isChecked()); WiimoteReal::ChangeWiimoteSource(WIIMOTE_BALANCE_BOARD, m_wiimote_real_balance_board->isChecked() ? WIIMOTE_SRC_REAL : @@ -515,8 +517,8 @@ void ControllersWindow::SaveSettings() for (size_t i = 0; i < m_gc_groups.size(); i++) { const int index = m_gc_controller_boxes[i]->currentIndex(); - Settings().SetSIDevice(i, FromGCMenuIndex(index)); + settings.SetSIDevice(i, FromGCMenuIndex(index)); m_gc_buttons[i]->setEnabled(index != 0 && index != 6); } - Settings().Save(); + settings.Save(); } diff --git a/Source/Core/DolphinQt2/Config/Mapping/GCPadWiiU.cpp b/Source/Core/DolphinQt2/Config/Mapping/GCPadWiiU.cpp index 7a2610bffd..e5a2a3ce4c 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/GCPadWiiU.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/GCPadWiiU.cpp @@ -48,14 +48,14 @@ void GCPadWiiU::ConnectWidgets() void GCPadWiiU::LoadSettings() { - m_rumble->setChecked(Settings().IsGCAdapterRumbleEnabled(GetPort())); - m_simulate_bongos->setChecked(Settings().IsGCAdapterSimulatingDKBongos(GetPort())); + m_rumble->setChecked(Settings::Instance().IsGCAdapterRumbleEnabled(GetPort())); + m_simulate_bongos->setChecked(Settings::Instance().IsGCAdapterSimulatingDKBongos(GetPort())); } void GCPadWiiU::SaveSettings() { - Settings().SetGCAdapterRumbleEnabled(GetPort(), m_rumble->isChecked()); - Settings().SetGCAdapterSimulatingDKBongos(GetPort(), m_simulate_bongos->isChecked()); + Settings::Instance().SetGCAdapterRumbleEnabled(GetPort(), m_rumble->isChecked()); + Settings::Instance().SetGCAdapterSimulatingDKBongos(GetPort(), m_simulate_bongos->isChecked()); } InputConfig* GCPadWiiU::GetConfig() diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp index 7b24f1c678..04e20485b2 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp @@ -126,8 +126,9 @@ void MappingWindow::ConnectWidgets() void MappingWindow::OnDeleteProfilePressed() { + auto& settings = Settings::Instance(); const QString profile_name = m_profiles_combo->currentText(); - if (!Settings().GetProfiles(m_config).contains(profile_name)) + if (!settings.GetProfiles(m_config).contains(profile_name)) { QMessageBox error; error.setIcon(QMessageBox::Critical); @@ -153,7 +154,7 @@ void MappingWindow::OnDeleteProfilePressed() QMessageBox result(this); - std::string profile_path = Settings().GetProfileINIPath(m_config, profile_name).toStdString(); + std::string profile_path = settings.GetProfileINIPath(m_config, profile_name).toStdString(); File::CreateFullPath(profile_path); @@ -170,7 +171,8 @@ void MappingWindow::OnLoadProfilePressed() if (profile_name.isEmpty()) return; - std::string profile_path = Settings().GetProfileINIPath(m_config, profile_name).toStdString(); + std::string profile_path = + Settings::Instance().GetProfileINIPath(m_config, profile_name).toStdString(); File::CreateFullPath(profile_path); @@ -192,7 +194,8 @@ void MappingWindow::OnSaveProfilePressed() if (profile_name.isEmpty()) return; - std::string profile_path = Settings().GetProfileINIPath(m_config, profile_name).toStdString(); + std::string profile_path = + Settings::Instance().GetProfileINIPath(m_config, profile_name).toStdString(); File::CreateFullPath(profile_path); @@ -297,7 +300,7 @@ void MappingWindow::ChangeMappingType(MappingWindow::Type type) m_controller = m_config->GetController(GetPort()); m_profiles_combo->addItem(QStringLiteral("")); - for (const auto& item : Settings().GetProfiles(m_config)) + for (const auto& item : Settings::Instance().GetProfiles(m_config)) m_profiles_combo->addItem(item); } diff --git a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp index fb1a8190fe..7993925d25 100644 --- a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp @@ -6,6 +6,7 @@ #include "DolphinQt2/Settings.h" #include "DolphinQt2/Settings/GeneralPane.h" #include "DolphinQt2/Settings/InterfacePane.h" +#include "DolphinQt2/Settings/PathPane.h" SettingsWindow::SettingsWindow(QWidget* parent) : QDialog(parent) { @@ -53,6 +54,7 @@ void SettingsWindow::SetupSettingsWidget() // Panes initalised here m_settings_outer->addWidget(new GeneralPane); m_settings_outer->addWidget(new InterfacePane); + m_settings_outer->addWidget(new PathPane); } void SettingsWindow::MakeUnfinishedWarning() @@ -67,7 +69,7 @@ void SettingsWindow::MakeUnfinishedWarning() void SettingsWindow::AddCategoryToList(const QString& title, const QString& icon) { - QString dir = Settings().GetThemeDir(); + QString dir = Settings::Instance().GetThemeDir(); QListWidgetItem* button = new QListWidgetItem(); button->setIcon(QIcon(dir.append(icon))); button->setText(title); @@ -87,6 +89,7 @@ void SettingsWindow::MakeCategoryList() AddCategoryToList(tr("General"), QStringLiteral("config.png")); AddCategoryToList(tr("Interface"), QStringLiteral("browse.png")); + AddCategoryToList(tr("Paths"), QStringLiteral("browse.png")); connect(m_categories, &QListWidget::currentItemChanged, this, &SettingsWindow::changePage); } diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index 113637506c..3e5ba69f0e 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -52,7 +52,7 @@ /NODEFAULTLIB:libcmt %(AdditionalOptions) - $(ProjectDir)\VideoInterface;$(ProjectDir)\GameList;$(ProjectDir)\Settings;$(ProjectDir)\Config;$(ProjectDir)\Config\Mapping;%(AdditionalIncludeDirectories) + $(ProjectDir)\VideoInterface;$(ProjectDir)\GameList;$(ProjectDir)\Settings;$(ProjectDir)\Config;$(ProjectDir)\Config\Mapping;$(ProjectDir)\QtUtils;%(AdditionalIncludeDirectories) DolphinQt2.manifest;%(AdditionalManifestFiles) @@ -75,7 +75,6 @@ - @@ -88,6 +87,7 @@ + @@ -112,8 +112,8 @@ - + @@ -133,7 +133,6 @@ - @@ -146,12 +145,14 @@ + + diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters b/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters index e3d6e53cec..e2947829f6 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters @@ -29,6 +29,9 @@ Generated Files + + Generated Files + Generated Files @@ -57,12 +60,6 @@ - - Generated Files - - - Config - Generated Files @@ -103,6 +100,9 @@ Settings + + Settings + @@ -116,6 +116,9 @@ + + QtUtils + QtUtils @@ -142,9 +145,6 @@ GameList - - Config - @@ -160,6 +160,9 @@ + + QtUtils + diff --git a/Source/Core/DolphinQt2/GameList/GameFile.cpp b/Source/Core/DolphinQt2/GameList/GameFile.cpp index 94ed8e6e47..5b921e78f2 100644 --- a/Source/Core/DolphinQt2/GameList/GameFile.cpp +++ b/Source/Core/DolphinQt2/GameList/GameFile.cpp @@ -217,9 +217,9 @@ QString GameFile::GetBannerString(const QMap& m) cons bool wii = m_platform != DiscIO::Platform::GAMECUBE_DISC; DiscIO::Language current_lang; if (wii) - current_lang = Settings().GetWiiSystemLanguage(); + current_lang = Settings::Instance().GetWiiSystemLanguage(); else - current_lang = Settings().GetGCSystemLanguage(); + current_lang = Settings::Instance().GetGCSystemLanguage(); if (m.contains(current_lang)) return m[current_lang]; diff --git a/Source/Core/DolphinQt2/GameList/GameList.cpp b/Source/Core/DolphinQt2/GameList/GameList.cpp index 41a063322d..b961fde176 100644 --- a/Source/Core/DolphinQt2/GameList/GameList.cpp +++ b/Source/Core/DolphinQt2/GameList/GameList.cpp @@ -22,6 +22,7 @@ #include "DolphinQt2/Config/PropertiesDialog.h" #include "DolphinQt2/GameList/GameList.h" #include "DolphinQt2/GameList/ListProxyModel.h" +#include "DolphinQt2/QtUtils/DoubleClickEventFilter.h" #include "DolphinQt2/Settings.h" static bool CompressCB(const std::string&, float, void*); @@ -42,15 +43,15 @@ GameList::GameList(QWidget* parent) : QStackedWidget(parent) connect(m_table, &QTableView::doubleClicked, this, &GameList::GameSelected); connect(m_list, &QListView::doubleClicked, this, &GameList::GameSelected); - connect(this, &GameList::DirectoryAdded, m_model, &GameListModel::DirectoryAdded); - connect(this, &GameList::DirectoryRemoved, m_model, &GameListModel::DirectoryRemoved); + connect(&Settings::Instance(), &Settings::PathAdded, m_model, &GameListModel::DirectoryAdded); + connect(&Settings::Instance(), &Settings::PathRemoved, m_model, &GameListModel::DirectoryRemoved); connect(m_model, &QAbstractItemModel::rowsInserted, this, &GameList::ConsiderViewChange); connect(m_model, &QAbstractItemModel::rowsRemoved, this, &GameList::ConsiderViewChange); addWidget(m_table); addWidget(m_list); addWidget(m_empty); - m_prefer_table = Settings().GetPreferredView(); + m_prefer_table = Settings::Instance().GetPreferredView(); ConsiderViewChange(); } @@ -70,15 +71,16 @@ void GameList::MakeTableView() connect(m_table, &QTableView::customContextMenuRequested, this, &GameList::ShowContextMenu); - m_table->setColumnHidden(GameListModel::COL_PLATFORM, !Settings().PlatformVisible()); - m_table->setColumnHidden(GameListModel::COL_ID, !Settings().IDVisible()); - m_table->setColumnHidden(GameListModel::COL_BANNER, !Settings().BannerVisible()); - m_table->setColumnHidden(GameListModel::COL_TITLE, !Settings().TitleVisible()); - m_table->setColumnHidden(GameListModel::COL_DESCRIPTION, !Settings().DescriptionVisible()); - m_table->setColumnHidden(GameListModel::COL_MAKER, !Settings().MakerVisible()); - m_table->setColumnHidden(GameListModel::COL_SIZE, !Settings().SizeVisible()); - m_table->setColumnHidden(GameListModel::COL_COUNTRY, !Settings().CountryVisible()); - m_table->setColumnHidden(GameListModel::COL_RATING, !Settings().StateVisible()); + auto& settings = Settings::Instance(); + m_table->setColumnHidden(GameListModel::COL_PLATFORM, !settings.PlatformVisible()); + m_table->setColumnHidden(GameListModel::COL_ID, !settings.IDVisible()); + m_table->setColumnHidden(GameListModel::COL_BANNER, !settings.BannerVisible()); + m_table->setColumnHidden(GameListModel::COL_TITLE, !settings.TitleVisible()); + m_table->setColumnHidden(GameListModel::COL_DESCRIPTION, !settings.DescriptionVisible()); + m_table->setColumnHidden(GameListModel::COL_MAKER, !settings.MakerVisible()); + m_table->setColumnHidden(GameListModel::COL_SIZE, !settings.SizeVisible()); + m_table->setColumnHidden(GameListModel::COL_COUNTRY, !settings.CountryVisible()); + m_table->setColumnHidden(GameListModel::COL_RATING, !settings.StateVisible()); QHeaderView* hor_header = m_table->horizontalHeader(); hor_header->setSectionResizeMode(GameListModel::COL_PLATFORM, QHeaderView::ResizeToContents); @@ -97,9 +99,18 @@ void GameList::MakeTableView() void GameList::MakeEmptyView() { m_empty = new QLabel(this); - m_empty->setText(tr("Dolphin did not find any game files.\n" - "Open the Paths dialog to add game folders.")); + m_empty->setText(tr("Dolphin could not find any GameCube/Wii ISOs or WADs.\n" + "Double-click here to set a games directory...")); m_empty->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + + auto event_filter = new DoubleClickEventFilter{}; + m_empty->installEventFilter(event_filter); + connect(event_filter, &DoubleClickEventFilter::doubleClicked, [this] { + auto current_dir = QDir::currentPath(); + auto dir = QFileDialog::getExistingDirectory(this, tr("Select a Directory"), current_dir); + if (!dir.isEmpty()) + Settings::Instance().AddPath(dir); + }); } void GameList::MakeListView() @@ -284,7 +295,7 @@ void GameList::UninstallWAD() void GameList::SetDefaultISO() { - Settings().SetDefaultGame(GetSelectedGame()); + Settings::Instance().SetDefaultGame(GetSelectedGame()); } void GameList::OpenContainingFolder() @@ -364,7 +375,7 @@ QString GameList::GetSelectedGame() const void GameList::SetPreferredView(bool table) { m_prefer_table = table; - Settings().SetPreferredView(table); + Settings::Instance().SetPreferredView(table); ConsiderViewChange(); } diff --git a/Source/Core/DolphinQt2/GameList/GameList.h b/Source/Core/DolphinQt2/GameList/GameList.h index 750ed92c7a..ae4e6edf74 100644 --- a/Source/Core/DolphinQt2/GameList/GameList.h +++ b/Source/Core/DolphinQt2/GameList/GameList.h @@ -42,8 +42,6 @@ private slots: signals: void GameSelected(); - void DirectoryAdded(const QString& dir); - void DirectoryRemoved(const QString& dir); private: void MakeTableView(); diff --git a/Source/Core/DolphinQt2/GameList/GameTracker.cpp b/Source/Core/DolphinQt2/GameList/GameTracker.cpp index 1097504ff8..be66ab406e 100644 --- a/Source/Core/DolphinQt2/GameList/GameTracker.cpp +++ b/Source/Core/DolphinQt2/GameList/GameTracker.cpp @@ -28,7 +28,7 @@ GameTracker::GameTracker(QObject* parent) : QFileSystemWatcher(parent) m_loader_thread.start(); - for (QString dir : Settings().GetPaths()) + for (QString dir : Settings::Instance().GetPaths()) AddDirectory(dir); } diff --git a/Source/Core/DolphinQt2/Main.cpp b/Source/Core/DolphinQt2/Main.cpp index 781f89d2da..439c8b81c3 100644 --- a/Source/Core/DolphinQt2/Main.cpp +++ b/Source/Core/DolphinQt2/Main.cpp @@ -34,8 +34,9 @@ int main(int argc, char* argv[]) QObject::connect(QAbstractEventDispatcher::instance(), &QAbstractEventDispatcher::aboutToBlock, &app, &Core::HostDispatchJobs); + auto& settings = Settings::Instance(); int retval = 0; - if (Settings().IsInDevelopmentWarningEnabled()) + if (settings.IsInDevelopmentWarningEnabled()) { InDevelopmentWarning warning_box; retval = warning_box.exec() == QDialog::Rejected; @@ -48,7 +49,7 @@ int main(int argc, char* argv[]) win.show(); #if defined(USE_ANALYTICS) && USE_ANALYTICS - if (!Settings().HasAskedForAnalyticsPermission()) + if (!settings.HasAskedForAnalyticsPermission()) { QMessageBox analytics_prompt(&win); @@ -69,9 +70,9 @@ int main(int argc, char* argv[]) const int answer = analytics_prompt.exec(); - Settings().SetAskedForAnalyticsPermission(true); - Settings().SetAnalyticsEnabled(answer == QMessageBox::Yes); - Settings().Save(); + settings.SetAskedForAnalyticsPermission(true); + settings.SetAnalyticsEnabled(answer == QMessageBox::Yes); + settings.Save(); DolphinAnalytics::Instance()->ReloadConfig(); } diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp index 3382cee4c0..bf35b867bc 100644 --- a/Source/Core/DolphinQt2/MainWindow.cpp +++ b/Source/Core/DolphinQt2/MainWindow.cpp @@ -22,7 +22,6 @@ #include "DolphinQt2/AboutDialog.h" #include "DolphinQt2/Config/ControllersWindow.h" -#include "DolphinQt2/Config/PathDialog.h" #include "DolphinQt2/Config/SettingsWindow.h" #include "DolphinQt2/Host.h" #include "DolphinQt2/MainWindow.h" @@ -40,7 +39,6 @@ MainWindow::MainWindow() : QMainWindow(nullptr) CreateComponents(); ConnectGameList(); - ConnectPathsDialog(); ConnectToolBar(); ConnectRenderWidget(); ConnectStack(); @@ -83,7 +81,6 @@ void MainWindow::CreateComponents() m_game_list = new GameList(this); m_render_widget = new RenderWidget; m_stack = new QStackedWidget(this); - m_paths_dialog = new PathDialog(this); m_controllers_window = new ControllersWindow(this); m_settings_window = new SettingsWindow(this); } @@ -140,7 +137,6 @@ void MainWindow::ConnectToolBar() 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::PathsPressed, this, &MainWindow::ShowPathsDialog); connect(m_tool_bar, &ToolBar::SettingsPressed, this, &MainWindow::ShowSettingsWindow); connect(m_tool_bar, &ToolBar::ControllersPressed, this, &MainWindow::ShowControllersWindow); @@ -169,12 +165,6 @@ void MainWindow::ConnectStack() setCentralWidget(m_stack); } -void MainWindow::ConnectPathsDialog() -{ - connect(m_paths_dialog, &PathDialog::PathAdded, m_game_list, &GameList::DirectoryAdded); - connect(m_paths_dialog, &PathDialog::PathRemoved, m_game_list, &GameList::DirectoryRemoved); -} - void MainWindow::Open() { QString file = QFileDialog::getOpenFileName( @@ -206,7 +196,7 @@ void MainWindow::Play() } else { - QString default_path = Settings().GetDefaultGame(); + QString default_path = Settings::Instance().GetDefaultGame(); if (!default_path.isEmpty() && QFile::exists(default_path)) { StartGame(default_path); @@ -228,7 +218,7 @@ void MainWindow::Pause() bool MainWindow::Stop() { bool stop = true; - if (Settings().GetConfirmStop()) + if (Settings::Instance().GetConfirmStop()) { // We could pause the game here and resume it if they say no. QMessageBox::StandardButton confirm; @@ -313,7 +303,7 @@ void MainWindow::StartGame(const QString& path) void MainWindow::ShowRenderWidget() { - Settings settings; + auto& settings = Settings::Instance(); if (settings.GetRenderToMain()) { // If we're rendering to main, add it to the stack and update our title when necessary. @@ -352,13 +342,6 @@ void MainWindow::HideRenderWidget() m_render_widget->hide(); } -void MainWindow::ShowPathsDialog() -{ - m_paths_dialog->show(); - m_paths_dialog->raise(); - m_paths_dialog->activateWindow(); -} - void MainWindow::ShowControllersWindow() { m_controllers_window->show(); @@ -432,6 +415,6 @@ void MainWindow::StateSaveOldest() void MainWindow::SetStateSlot(int slot) { - Settings().SetStateSlot(slot); + Settings::Instance().SetStateSlot(slot); m_state_slot = slot; } diff --git a/Source/Core/DolphinQt2/MainWindow.h b/Source/Core/DolphinQt2/MainWindow.h index cc617c3ac0..5e089c2572 100644 --- a/Source/Core/DolphinQt2/MainWindow.h +++ b/Source/Core/DolphinQt2/MainWindow.h @@ -14,7 +14,6 @@ #include "DolphinQt2/RenderWidget.h" #include "DolphinQt2/ToolBar.h" -class PathDialog; class SettingsWindow; class ControllersWindow; @@ -63,7 +62,6 @@ private: void ConnectRenderWidget(); void ConnectStack(); void ConnectToolBar(); - void ConnectPathsDialog(); void InitControllers(); void ShutdownControllers(); @@ -72,7 +70,6 @@ private: void ShowRenderWidget(); void HideRenderWidget(); - void ShowPathsDialog(); void ShowSettingsWindow(); void ShowControllersWindow(); void ShowAboutDialog(); @@ -85,7 +82,6 @@ private: bool m_rendering_to_main; int m_state_slot = 1; - PathDialog* m_paths_dialog; ControllersWindow* m_controllers_window; SettingsWindow* m_settings_window; }; diff --git a/Source/Core/DolphinQt2/MenuBar.cpp b/Source/Core/DolphinQt2/MenuBar.cpp index f387b6864d..ef9a449621 100644 --- a/Source/Core/DolphinQt2/MenuBar.cpp +++ b/Source/Core/DolphinQt2/MenuBar.cpp @@ -140,7 +140,7 @@ void MenuBar::AddStateSlotMenu(QMenu* emu_menu) QAction* action = m_state_slot_menu->addAction(QStringLiteral("")); action->setCheckable(true); action->setActionGroup(m_state_slots); - if (Settings().GetStateSlot() == i) + if (Settings::Instance().GetStateSlot() == i) action->setChecked(true); connect(action, &QAction::triggered, this, [=]() { emit SetStateSlot(i); }); @@ -203,7 +203,7 @@ void MenuBar::AddGameListTypeSection(QMenu* view_menu) list_group->addAction(table_view); list_group->addAction(list_view); - bool prefer_table = Settings().GetPreferredView(); + bool prefer_table = Settings::Instance().GetPreferredView(); table_view->setChecked(prefer_table); list_view->setChecked(!prefer_table); @@ -213,15 +213,16 @@ void MenuBar::AddGameListTypeSection(QMenu* view_menu) void MenuBar::AddTableColumnsMenu(QMenu* view_menu) { - static const QMap columns{{tr("Platform"), &Settings().PlatformVisible()}, - {tr("ID"), &Settings().IDVisible()}, - {tr("Banner"), &Settings().BannerVisible()}, - {tr("Title"), &Settings().TitleVisible()}, - {tr("Description"), &Settings().DescriptionVisible()}, - {tr("Maker"), &Settings().MakerVisible()}, - {tr("Size"), &Settings().SizeVisible()}, - {tr("Country"), &Settings().CountryVisible()}, - {tr("Quality"), &Settings().StateVisible()}}; + auto& settings = Settings::Instance(); + static const QMap columns{{tr("Platform"), &settings.PlatformVisible()}, + {tr("ID"), &settings.IDVisible()}, + {tr("Banner"), &settings.BannerVisible()}, + {tr("Title"), &settings.TitleVisible()}, + {tr("Description"), &settings.DescriptionVisible()}, + {tr("Maker"), &settings.MakerVisible()}, + {tr("Size"), &settings.SizeVisible()}, + {tr("Country"), &settings.CountryVisible()}, + {tr("Quality"), &settings.StateVisible()}}; QActionGroup* column_group = new QActionGroup(this); QMenu* cols_menu = view_menu->addMenu(tr("Table Columns")); @@ -235,7 +236,7 @@ void MenuBar::AddTableColumnsMenu(QMenu* view_menu) action->setChecked(*config); connect(action, &QAction::toggled, [this, config, key](bool value) { *config = value; - Settings().Save(); + Settings::Instance().Save(); emit ColumnVisibilityToggled(key, value); }); } diff --git a/Source/Core/DolphinQt2/QtUtils/DoubleClickEventFilter.cpp b/Source/Core/DolphinQt2/QtUtils/DoubleClickEventFilter.cpp new file mode 100644 index 0000000000..3a626e1203 --- /dev/null +++ b/Source/Core/DolphinQt2/QtUtils/DoubleClickEventFilter.cpp @@ -0,0 +1,15 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#include "DolphinQt2/QtUtils/DoubleClickEventFilter.h" + +bool DoubleClickEventFilter::eventFilter(QObject* object, QEvent* event) +{ + if (event->type() == QEvent::MouseButtonDblClick) + emit doubleClicked(); + + return false; +} diff --git a/Source/Core/DolphinQt2/QtUtils/DoubleClickEventFilter.h b/Source/Core/DolphinQt2/QtUtils/DoubleClickEventFilter.h new file mode 100644 index 0000000000..1e2da4a960 --- /dev/null +++ b/Source/Core/DolphinQt2/QtUtils/DoubleClickEventFilter.h @@ -0,0 +1,17 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class DoubleClickEventFilter : public QObject +{ + Q_OBJECT +signals: + void doubleClicked(); + +private: + bool eventFilter(QObject* object, QEvent* event) override; +}; diff --git a/Source/Core/DolphinQt2/Resources.cpp b/Source/Core/DolphinQt2/Resources.cpp index 27639023cf..69b1b22515 100644 --- a/Source/Core/DolphinQt2/Resources.cpp +++ b/Source/Core/DolphinQt2/Resources.cpp @@ -47,22 +47,22 @@ QPixmap Resources::GetPixmap(const QString& name, const QString& dir) QIcon Resources::GetScaledIcon(const std::string& name) { - return GetIcon(QString::fromStdString(name), Settings().GetResourcesDir()); + return GetIcon(QString::fromStdString(name), Settings::Instance().GetResourcesDir()); } QIcon Resources::GetScaledThemeIcon(const std::string& name) { - return GetIcon(QString::fromStdString(name), Settings().GetThemeDir()); + return GetIcon(QString::fromStdString(name), Settings::Instance().GetThemeDir()); } QPixmap Resources::GetScaledPixmap(const std::string& name) { - return GetPixmap(QString::fromStdString(name), Settings().GetResourcesDir()); + return GetPixmap(QString::fromStdString(name), Settings::Instance().GetResourcesDir()); } QPixmap Resources::GetScaledThemePixmap(const std::string& name) { - return GetPixmap(QString::fromStdString(name), Settings().GetThemeDir()); + return GetPixmap(QString::fromStdString(name), Settings::Instance().GetThemeDir()); } void Resources::Init() diff --git a/Source/Core/DolphinQt2/Settings.cpp b/Source/Core/DolphinQt2/Settings.cpp index 248589a8a1..a1ec7d7b94 100644 --- a/Source/Core/DolphinQt2/Settings.cpp +++ b/Source/Core/DolphinQt2/Settings.cpp @@ -17,10 +17,16 @@ static QString GetSettingsPath() return QString::fromStdString(File::GetUserPath(D_CONFIG_IDX)) + QStringLiteral("/UI.ini"); } -Settings::Settings(QObject* parent) : QSettings(GetSettingsPath(), QSettings::IniFormat, parent) +Settings::Settings() : QSettings(GetSettingsPath(), QSettings::IniFormat) { } +Settings& Settings::Instance() +{ + static Settings settings; + return settings; +} + QString Settings::GetThemeDir() const { return QString::fromStdString(File::GetThemeDir(SConfig::GetInstance().theme_name)); @@ -55,16 +61,32 @@ QStringList Settings::GetPaths() const return value(QStringLiteral("GameList/Paths")).toStringList(); } +void Settings::AddPath(const QString& path) +{ + QStringList game_folders = Settings::Instance().GetPaths(); + if (!game_folders.contains(path)) + { + game_folders << path; + Settings::Instance().SetPaths(game_folders); + emit PathAdded(path); + } +} + void Settings::SetPaths(const QStringList& paths) { setValue(QStringLiteral("GameList/Paths"), paths); } -void Settings::RemovePath(int i) +void Settings::RemovePath(const QString& path) { QStringList paths = GetPaths(); + int i = paths.indexOf(path); + if (i < 0) + return; + paths.removeAt(i); SetPaths(paths); + emit PathRemoved(path); } QString Settings::GetDefaultGame() const diff --git a/Source/Core/DolphinQt2/Settings.h b/Source/Core/DolphinQt2/Settings.h index fa01aac02d..d7f3dae319 100644 --- a/Source/Core/DolphinQt2/Settings.h +++ b/Source/Core/DolphinQt2/Settings.h @@ -7,6 +7,7 @@ #include #include +#include "Common/NonCopyable.h" #include "Core/HW/SI/SI.h" namespace DiscIO @@ -17,12 +18,12 @@ enum class Language; class InputConfig; // UI settings to be stored in the config directory. -class Settings final : public QSettings +class Settings final : public QSettings, NonCopyable { Q_OBJECT public: - explicit Settings(QObject* parent = nullptr); + static Settings& Instance(); // UI QString GetThemeDir() const; @@ -34,8 +35,9 @@ public: // GameList QStringList GetPaths() const; + void AddPath(const QString& path); void SetPaths(const QStringList& paths); - void RemovePath(int i); + void RemovePath(const QString& path); QString GetDefaultGame() const; void SetDefaultGame(const QString& path); QString GetDVDRoot() const; @@ -105,4 +107,11 @@ public: void SetGCAdapterSimulatingDKBongos(int port, bool enabled); void Save(); + +signals: + void PathAdded(const QString&); + void PathRemoved(const QString&); + +private: + Settings(); }; diff --git a/Source/Core/DolphinQt2/Settings/GeneralPane.cpp b/Source/Core/DolphinQt2/Settings/GeneralPane.cpp index f9e5e53f33..06862c8473 100644 --- a/Source/Core/DolphinQt2/Settings/GeneralPane.cpp +++ b/Source/Core/DolphinQt2/Settings/GeneralPane.cpp @@ -140,11 +140,12 @@ void GeneralPane::CreateAdvanced() void GeneralPane::LoadConfig() { - m_checkbox_force_ntsc->setChecked(Settings().GetForceNTSCJ()); - m_checkbox_enable_analytics->setChecked(Settings().GetAnalyticsEnabled()); + auto& settings = Settings::Instance(); + m_checkbox_force_ntsc->setChecked(settings.GetForceNTSCJ()); + m_checkbox_enable_analytics->setChecked(settings.GetAnalyticsEnabled()); m_checkbox_dualcore->setChecked(SConfig::GetInstance().bCPUThread); m_checkbox_cheats->setChecked(SConfig::GetInstance().bEnableCheats); - int selection = qRound(Settings().GetEmulationSpeed() * 10); + int selection = qRound(settings.GetEmulationSpeed() * 10); if (selection < m_combobox_speedlimit->count()) m_combobox_speedlimit->setCurrentIndex(selection); m_checkbox_dualcore->setChecked(SConfig::GetInstance().bCPUThread); @@ -170,8 +171,9 @@ void GeneralPane::LoadConfig() void GeneralPane::OnSaveConfig() { - Settings().SetForceNTSCJ(m_checkbox_force_ntsc->isChecked()); - Settings().SetAnalyticsEnabled(m_checkbox_enable_analytics->isChecked()); + auto& settings = Settings::Instance(); + settings.SetForceNTSCJ(m_checkbox_force_ntsc->isChecked()); + settings.SetAnalyticsEnabled(m_checkbox_enable_analytics->isChecked()); SConfig::GetInstance().bCPUThread = m_checkbox_dualcore->isChecked(); SConfig::GetInstance().bEnableCheats = m_checkbox_cheats->isChecked(); SConfig::GetInstance().m_EmulationSpeed = m_combobox_speedlimit->currentIndex() * 0.1f; diff --git a/Source/Core/DolphinQt2/Config/PathDialog.cpp b/Source/Core/DolphinQt2/Settings/PathPane.cpp similarity index 58% rename from Source/Core/DolphinQt2/Config/PathDialog.cpp rename to Source/Core/DolphinQt2/Settings/PathPane.cpp index c99b82acac..afd58b535f 100644 --- a/Source/Core/DolphinQt2/Config/PathDialog.cpp +++ b/Source/Core/DolphinQt2/Settings/PathPane.cpp @@ -2,22 +2,18 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. -#include -#include -#include #include -#include +#include #include #include #include #include -#include #include -#include "DolphinQt2/Config/PathDialog.h" #include "DolphinQt2/Settings.h" +#include "DolphinQt2/Settings/PathPane.h" -PathDialog::PathDialog(QWidget* parent) : QDialog(parent) +PathPane::PathPane(QWidget* parent) : QWidget(parent) { setWindowTitle(tr("Paths")); @@ -25,32 +21,18 @@ PathDialog::PathDialog(QWidget* parent) : QDialog(parent) layout->addWidget(MakeGameFolderBox()); layout->addLayout(MakePathsLayout()); - QDialogButtonBox* ok_box = new QDialogButtonBox(QDialogButtonBox::Ok); - connect(ok_box, &QDialogButtonBox::accepted, this, &PathDialog::accept); - layout->addWidget(ok_box); - setLayout(layout); } -void PathDialog::Browse() +void PathPane::Browse() { QString dir = QFileDialog::getExistingDirectory(this, tr("Select a Directory"), QDir::currentPath()); if (!dir.isEmpty()) - { - Settings settings; - QStringList game_folders = settings.GetPaths(); - if (!game_folders.contains(dir)) - { - game_folders << dir; - settings.SetPaths(game_folders); - m_path_list->addItem(dir); - emit PathAdded(dir); - } - } + Settings::Instance().AddPath(dir); } -void PathDialog::BrowseDefaultGame() +void PathPane::BrowseDefaultGame() { QString file = QFileDialog::getOpenFileName( this, tr("Select a Game"), QDir::currentPath(), @@ -59,51 +41,58 @@ void PathDialog::BrowseDefaultGame() if (!file.isEmpty()) { m_game_edit->setText(file); - Settings().SetDefaultGame(file); + Settings::Instance().SetDefaultGame(file); } } -void PathDialog::BrowseDVDRoot() +void PathPane::BrowseDVDRoot() { QString dir = QFileDialog::getExistingDirectory(this, tr("Select DVD Root"), QDir::currentPath()); if (!dir.isEmpty()) { m_dvd_edit->setText(dir); - Settings().SetDVDRoot(dir); + Settings::Instance().SetDVDRoot(dir); } } -void PathDialog::BrowseApploader() +void PathPane::BrowseApploader() { QString file = QFileDialog::getOpenFileName(this, tr("Select an Apploader"), QDir::currentPath(), tr("Apploaders (*.img)")); if (!file.isEmpty()) { m_app_edit->setText(file); - Settings().SetApploader(file); + Settings::Instance().SetApploader(file); } } -void PathDialog::BrowseWiiNAND() +void PathPane::BrowseWiiNAND() { QString dir = QFileDialog::getExistingDirectory(this, tr("Select Wii NAND Root"), QDir::currentPath()); if (!dir.isEmpty()) { m_nand_edit->setText(dir); - Settings().SetWiiNAND(dir); + Settings::Instance().SetWiiNAND(dir); } } -QGroupBox* PathDialog::MakeGameFolderBox() +QGroupBox* PathPane::MakeGameFolderBox() { QGroupBox* game_box = new QGroupBox(tr("Game Folders")); game_box->setMinimumSize(QSize(400, 250)); QVBoxLayout* vlayout = new QVBoxLayout; m_path_list = new QListWidget; - m_path_list->insertItems(0, Settings().GetPaths()); + m_path_list->insertItems(0, Settings::Instance().GetPaths()); m_path_list->setSpacing(1); + connect(&Settings::Instance(), &Settings::PathAdded, + [this](const QString& dir) { m_path_list->addItem(dir); }); + connect(&Settings::Instance(), &Settings::PathRemoved, [this](const QString& dir) { + auto items = m_path_list->findItems(dir, Qt::MatchExactly); + for (auto& item : items) + delete item; + }); vlayout->addWidget(m_path_list); QHBoxLayout* hlayout = new QHBoxLayout; @@ -115,50 +104,51 @@ QGroupBox* PathDialog::MakeGameFolderBox() hlayout->addWidget(remove); vlayout->addLayout(hlayout); - connect(add, &QPushButton::clicked, this, &PathDialog::Browse); - connect(remove, &QPushButton::clicked, this, &PathDialog::RemovePath); + connect(add, &QPushButton::clicked, this, &PathPane::Browse); + connect(remove, &QPushButton::clicked, this, &PathPane::RemovePath); game_box->setLayout(vlayout); return game_box; } -QGridLayout* PathDialog::MakePathsLayout() +QGridLayout* PathPane::MakePathsLayout() { + auto& settings = Settings::Instance(); QGridLayout* layout = new QGridLayout; layout->setColumnStretch(1, 1); - m_game_edit = new QLineEdit(Settings().GetDefaultGame()); + m_game_edit = new QLineEdit(settings.GetDefaultGame()); connect(m_game_edit, &QLineEdit::editingFinished, - [=] { Settings().SetDefaultGame(m_game_edit->text()); }); + [=, &settings] { settings.SetDefaultGame(m_game_edit->text()); }); QPushButton* game_open = new QPushButton; - connect(game_open, &QPushButton::clicked, this, &PathDialog::BrowseDefaultGame); + connect(game_open, &QPushButton::clicked, this, &PathPane::BrowseDefaultGame); layout->addWidget(new QLabel(tr("Default Game")), 0, 0); layout->addWidget(m_game_edit, 0, 1); layout->addWidget(game_open, 0, 2); - m_dvd_edit = new QLineEdit(Settings().GetDVDRoot()); + m_dvd_edit = new QLineEdit(settings.GetDVDRoot()); connect(m_dvd_edit, &QLineEdit::editingFinished, - [=] { Settings().SetDVDRoot(m_dvd_edit->text()); }); + [=, &settings] { settings.SetDVDRoot(m_dvd_edit->text()); }); QPushButton* dvd_open = new QPushButton; - connect(dvd_open, &QPushButton::clicked, this, &PathDialog::BrowseDVDRoot); + connect(dvd_open, &QPushButton::clicked, this, &PathPane::BrowseDVDRoot); layout->addWidget(new QLabel(tr("DVD Root")), 1, 0); layout->addWidget(m_dvd_edit, 1, 1); layout->addWidget(dvd_open, 1, 2); - m_app_edit = new QLineEdit(Settings().GetApploader()); + m_app_edit = new QLineEdit(settings.GetApploader()); connect(m_app_edit, &QLineEdit::editingFinished, - [=] { Settings().SetApploader(m_app_edit->text()); }); + [=, &settings] { settings.SetApploader(m_app_edit->text()); }); QPushButton* app_open = new QPushButton; - connect(app_open, &QPushButton::clicked, this, &PathDialog::BrowseApploader); + connect(app_open, &QPushButton::clicked, this, &PathPane::BrowseApploader); layout->addWidget(new QLabel(tr("Apploader")), 2, 0); layout->addWidget(m_app_edit, 2, 1); layout->addWidget(app_open, 2, 2); - m_nand_edit = new QLineEdit(Settings().GetWiiNAND()); + m_nand_edit = new QLineEdit(settings.GetWiiNAND()); connect(m_nand_edit, &QLineEdit::editingFinished, - [=] { Settings().SetWiiNAND(m_nand_edit->text()); }); + [=, &settings] { settings.SetWiiNAND(m_nand_edit->text()); }); QPushButton* nand_open = new QPushButton; - connect(nand_open, &QPushButton::clicked, this, &PathDialog::BrowseWiiNAND); + connect(nand_open, &QPushButton::clicked, this, &PathPane::BrowseWiiNAND); layout->addWidget(new QLabel(tr("Wii NAND Root")), 3, 0); layout->addWidget(m_nand_edit, 3, 1); layout->addWidget(nand_open, 3, 2); @@ -166,11 +156,10 @@ QGridLayout* PathDialog::MakePathsLayout() return layout; } -void PathDialog::RemovePath() +void PathPane::RemovePath() { - int row = m_path_list->currentRow(); - if (row < 0) + auto item = m_path_list->currentItem(); + if (!item) return; - emit PathRemoved(m_path_list->takeItem(row)->text()); - Settings().RemovePath(row); + Settings::Instance().RemovePath(item->text()); } diff --git a/Source/Core/DolphinQt2/Config/PathDialog.h b/Source/Core/DolphinQt2/Settings/PathPane.h similarity index 62% rename from Source/Core/DolphinQt2/Config/PathDialog.h rename to Source/Core/DolphinQt2/Settings/PathPane.h index a486889680..753c5001c4 100644 --- a/Source/Core/DolphinQt2/Config/PathDialog.h +++ b/Source/Core/DolphinQt2/Settings/PathPane.h @@ -4,30 +4,24 @@ #pragma once -#include -#include -#include -#include -#include +#include -class PathDialog final : public QDialog +class QGridLayout; +class QGroupBox; +class QLineEdit; +class QListWidget; + +class PathPane final : public QWidget { - Q_OBJECT public: - explicit PathDialog(QWidget* parent = nullptr); + explicit PathPane(QWidget* parent = nullptr); -public slots: +private: void Browse(); void BrowseDefaultGame(); void BrowseDVDRoot(); void BrowseApploader(); void BrowseWiiNAND(); - -signals: - void PathAdded(QString path); - void PathRemoved(QString path); - -private: QGroupBox* MakeGameFolderBox(); QGridLayout* MakePathsLayout(); void RemovePath(); diff --git a/Source/Core/DolphinQt2/ToolBar.cpp b/Source/Core/DolphinQt2/ToolBar.cpp index adb344a2a3..d1e075e500 100644 --- a/Source/Core/DolphinQt2/ToolBar.cpp +++ b/Source/Core/DolphinQt2/ToolBar.cpp @@ -79,9 +79,6 @@ void ToolBar::MakeActions() addSeparator(); - m_paths_action = addAction(tr("Paths"), this, SIGNAL(PathsPressed())); - widgetForAction(m_paths_action)->setMinimumWidth(button_width); - m_config_action = addAction(tr("Settings"), this, SIGNAL(SettingsPressed())); widgetForAction(m_config_action)->setMinimumWidth(button_width); @@ -93,7 +90,6 @@ void ToolBar::MakeActions() void ToolBar::UpdateIcons() { m_open_action->setIcon(Resources::GetScaledThemeIcon("open")); - m_paths_action->setIcon(Resources::GetScaledThemeIcon("browse")); m_play_action->setIcon(Resources::GetScaledThemeIcon("play")); m_pause_action->setIcon(Resources::GetScaledThemeIcon("pause")); m_stop_action->setIcon(Resources::GetScaledThemeIcon("stop")); diff --git a/Source/Core/DolphinQt2/ToolBar.h b/Source/Core/DolphinQt2/ToolBar.h index 275afb4038..1150a26f81 100644 --- a/Source/Core/DolphinQt2/ToolBar.h +++ b/Source/Core/DolphinQt2/ToolBar.h @@ -28,7 +28,6 @@ signals: void FullScreenPressed(); void ScreenShotPressed(); - void PathsPressed(); void SettingsPressed(); void ControllersPressed(); @@ -42,7 +41,6 @@ private: QAction* m_stop_action; QAction* m_fullscreen_action; QAction* m_screenshot_action; - QAction* m_paths_action; QAction* m_config_action; QAction* m_controllers_action; };