From 8d2c7db2246202910dcddbee2caa752e26058bbe Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 12 Jun 2020 02:47:39 +1000 Subject: [PATCH] Qt: Source input profiles from program and user directory This way Linux users as well as Windows users who use the Documents user directory can use the shipped input profiles. --- .../controllersettingswidget.cpp | 2 +- src/duckstation-qt/qthostinterface.h | 9 ++-- src/frontend-common/common_host_interface.cpp | 41 ++++++++++++++----- src/frontend-common/common_host_interface.h | 12 +++++- 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/duckstation-qt/controllersettingswidget.cpp b/src/duckstation-qt/controllersettingswidget.cpp index 5ad465285..c6c11f384 100644 --- a/src/duckstation-qt/controllersettingswidget.cpp +++ b/src/duckstation-qt/controllersettingswidget.cpp @@ -335,7 +335,7 @@ void ControllerSettingsWidget::onSaveProfileClicked() return; } - m_host_interface->saveInputProfile(m_host_interface->getPathForInputProfile(name)); + m_host_interface->saveInputProfile(m_host_interface->getSavePathForInputProfile(name)); }); QAction* browse = menu.addAction(tr("Browse...")); diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h index 302e1b633..97993e803 100644 --- a/src/duckstation-qt/qthostinterface.h +++ b/src/duckstation-qt/qthostinterface.h @@ -73,14 +73,11 @@ public: /// Fills menu with save state info and handlers. void populateGameListContextMenu(const char* game_code, QWidget* parent_window, QMenu* menu); - ALWAYS_INLINE QString getPathForInputProfile(const QString& name) const + ALWAYS_INLINE QString getSavePathForInputProfile(const QString& name) const { - return QString::fromStdString(GetPathForInputProfile(name.toUtf8().constData())); - } - ALWAYS_INLINE std::vector> getInputProfileList() const - { - return GetInputProfileList(); + return QString::fromStdString(GetSavePathForInputProfile(name.toUtf8().constData())); } + ALWAYS_INLINE InputProfileList getInputProfileList() const { return GetInputProfileList(); } void saveInputProfile(const QString& profile_path); /// Returns a path relative to the user directory. diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index 3a58db074..55af833fa 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -1358,30 +1358,49 @@ void CommonHostInterface::RegisterAudioHotkeys() }); } -std::string CommonHostInterface::GetPathForInputProfile(const char* name) const +std::string CommonHostInterface::GetSavePathForInputProfile(const char* name) const { return GetUserDirectoryRelativePath("inputprofiles/%s.ini", name); } -std::vector> CommonHostInterface::GetInputProfileList() const +CommonHostInterface::InputProfileList CommonHostInterface::GetInputProfileList() const +{ + InputProfileList profiles; + + const std::string user_dir(GetUserDirectoryRelativePath("inputprofiles")); + const std::string program_dir(GetProgramDirectoryRelativePath("inputprofiles")); + + FindInputProfiles(user_dir, &profiles); + if (user_dir != program_dir) + FindInputProfiles(program_dir, &profiles); + + return profiles; +} + +void CommonHostInterface::FindInputProfiles(const std::string& base_path, InputProfileList* out_list) const { FileSystem::FindResultsArray results; - FileSystem::FindFiles(GetUserDirectoryRelativePath("inputprofiles").c_str(), "*.ini", - FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_RELATIVE_PATHS, &results); + FileSystem::FindFiles(base_path.c_str(), "*.ini", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_RELATIVE_PATHS, &results); - std::vector> profile_names; - profile_names.reserve(results.size()); + out_list->reserve(out_list->size() + results.size()); for (auto& it : results) { if (it.FileName.size() < 4) continue; - std::string profile_name = it.FileName.substr(0, it.FileName.length() - 4); - std::string full_filename = GetUserDirectoryRelativePath("inputprofiles/%s", it.FileName.c_str()); - profile_names.emplace_back(std::move(profile_name), std::move(full_filename)); - } + std::string name(it.FileName.substr(0, it.FileName.length() - 4)); + + // skip duplicates, we prefer the user directory + if (std::any_of(out_list->begin(), out_list->end(), + [&name](const InputProfileEntry& e) { return (e.name == name); })) + { + continue; + } - return profile_names; + std::string filename( + StringUtil::StdStringFromFormat("%s%c%s", base_path.c_str(), FS_OSPATH_SEPERATOR_CHARACTER, it.FileName.c_str())); + out_list->push_back(InputProfileEntry{std::move(name), std::move(filename)}); + } } void CommonHostInterface::ClearAllControllerBindings(SettingsInterface& si) diff --git a/src/frontend-common/common_host_interface.h b/src/frontend-common/common_host_interface.h index 3d4ad0d5c..a16349e80 100644 --- a/src/frontend-common/common_host_interface.h +++ b/src/frontend-common/common_host_interface.h @@ -162,6 +162,13 @@ protected: float duration; }; + struct InputProfileEntry + { + std::string name; + std::string path; + }; + using InputProfileList = std::vector; + CommonHostInterface(); ~CommonHostInterface(); @@ -195,10 +202,10 @@ protected: virtual void UpdateInputMap() = 0; /// Returns a path where an input profile with the specified name would be saved. - std::string GetPathForInputProfile(const char* name) const; + std::string GetSavePathForInputProfile(const char* name) const; /// Returns a list of all input profiles. first - name, second - path - std::vector> GetInputProfileList() const; + InputProfileList GetInputProfileList() const; /// Applies the specified input profile. void ApplyInputProfile(const char* profile_path, SettingsInterface& si); @@ -283,6 +290,7 @@ private: void RegisterGraphicsHotkeys(); void RegisterSaveStateHotkeys(); void RegisterAudioHotkeys(); + void FindInputProfiles(const std::string& base_path, InputProfileList* out_list) const; void UpdateControllerInputMap(SettingsInterface& si); void UpdateHotkeyInputMap(SettingsInterface& si); void ClearAllControllerBindings(SettingsInterface& si);