input_profiles.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project & 2024 suyu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <fmt/format.h>
  4. #include "common/fs/fs.h"
  5. #include "common/fs/path_util.h"
  6. #include "common/logging/log.h"
  7. #include "frontend_common/config.h"
  8. #include "yuzu/configuration/input_profiles.h"
  9. namespace FS = Common::FS;
  10. namespace {
  11. bool ProfileExistsInFilesystem(std::string_view profile_name) {
  12. return FS::Exists(FS::GetSuyuPath(FS::SuyuPath::ConfigDir) / "input" /
  13. fmt::format("{}.ini", profile_name));
  14. }
  15. bool IsINI(const std::filesystem::path& filename) {
  16. return filename.extension() == ".ini";
  17. }
  18. std::filesystem::path GetNameWithoutExtension(std::filesystem::path filename) {
  19. return filename.replace_extension();
  20. }
  21. } // namespace
  22. InputProfiles::InputProfiles() {
  23. const auto input_profile_loc = FS::GetSuyuPath(FS::SuyuPath::ConfigDir) / "input";
  24. if (!FS::IsDir(input_profile_loc)) {
  25. return;
  26. }
  27. FS::IterateDirEntries(
  28. input_profile_loc,
  29. [this](const std::filesystem::path& full_path) {
  30. const auto filename = full_path.filename();
  31. const auto name_without_ext =
  32. Common::FS::PathToUTF8String(GetNameWithoutExtension(filename));
  33. if (IsINI(filename) && IsProfileNameValid(name_without_ext)) {
  34. map_profiles.insert_or_assign(
  35. name_without_ext,
  36. std::make_unique<QtConfig>(name_without_ext, Config::ConfigType::InputProfile));
  37. }
  38. return true;
  39. },
  40. FS::DirEntryFilter::File);
  41. }
  42. InputProfiles::~InputProfiles() = default;
  43. std::vector<std::string> InputProfiles::GetInputProfileNames() {
  44. std::vector<std::string> profile_names;
  45. profile_names.reserve(map_profiles.size());
  46. auto it = map_profiles.cbegin();
  47. while (it != map_profiles.cend()) {
  48. const auto& [profile_name, config] = *it;
  49. if (!ProfileExistsInFilesystem(profile_name)) {
  50. it = map_profiles.erase(it);
  51. continue;
  52. }
  53. profile_names.push_back(profile_name);
  54. ++it;
  55. }
  56. std::stable_sort(profile_names.begin(), profile_names.end());
  57. return profile_names;
  58. }
  59. bool InputProfiles::IsProfileNameValid(std::string_view profile_name) {
  60. return profile_name.find_first_of("<>:;\"/\\|,.!?*") == std::string::npos;
  61. }
  62. bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t player_index) {
  63. if (ProfileExistsInMap(profile_name)) {
  64. return false;
  65. }
  66. map_profiles.insert_or_assign(
  67. profile_name, std::make_unique<QtConfig>(profile_name, Config::ConfigType::InputProfile));
  68. return SaveProfile(profile_name, player_index);
  69. }
  70. bool InputProfiles::DeleteProfile(const std::string& profile_name) {
  71. if (!ProfileExistsInMap(profile_name)) {
  72. return false;
  73. }
  74. if (!ProfileExistsInFilesystem(profile_name) ||
  75. FS::RemoveFile(map_profiles[profile_name]->GetConfigFilePath())) {
  76. map_profiles.erase(profile_name);
  77. }
  78. return !ProfileExistsInMap(profile_name) && !ProfileExistsInFilesystem(profile_name);
  79. }
  80. bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t player_index) {
  81. if (!ProfileExistsInMap(profile_name)) {
  82. return false;
  83. }
  84. if (!ProfileExistsInFilesystem(profile_name)) {
  85. map_profiles.erase(profile_name);
  86. return false;
  87. }
  88. LOG_INFO(Config, "Loading input profile `{}`", profile_name);
  89. map_profiles[profile_name]->ReadQtControlPlayerValues(player_index);
  90. return true;
  91. }
  92. bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t player_index) {
  93. if (!ProfileExistsInMap(profile_name)) {
  94. return false;
  95. }
  96. map_profiles[profile_name]->SaveQtControlPlayerValues(player_index);
  97. return true;
  98. }
  99. bool InputProfiles::ProfileExistsInMap(const std::string& profile_name) const {
  100. return map_profiles.find(profile_name) != map_profiles.end();
  101. }