configure_system.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // SPDX-FileCopyrightText: 2016 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <chrono>
  4. #include <optional>
  5. #include <vector>
  6. #include <QCheckBox>
  7. #include <QComboBox>
  8. #include <QDateTimeEdit>
  9. #include <QFileDialog>
  10. #include <QGraphicsItem>
  11. #include <QLineEdit>
  12. #include <QMessageBox>
  13. #include <QSpinBox>
  14. #include "common/settings.h"
  15. #include "core/core.h"
  16. #include "suyu/configuration/configuration_shared.h"
  17. #include "suyu/configuration/configure_system.h"
  18. #include "suyu/configuration/shared_widget.h"
  19. #include "ui_configure_system.h"
  20. constexpr std::array<u32, 7> LOCALE_BLOCKLIST{
  21. // pzzefezrpnkzeidfej
  22. // thhsrnhutlohsternp
  23. // BHH4CG U
  24. // Raa1AB S
  25. // nn9
  26. // ts
  27. 0b0100011100001100000, // Japan
  28. 0b0000001101001100100, // Americas
  29. 0b0100110100001000010, // Europe
  30. 0b0100110100001000010, // Australia
  31. 0b0000000000000000000, // China
  32. 0b0100111100001000000, // Korea
  33. 0b0100111100001000000, // Taiwan
  34. };
  35. static bool IsValidLocale(u32 region_index, u32 language_index) {
  36. if (region_index >= LOCALE_BLOCKLIST.size()) {
  37. return false;
  38. }
  39. return ((LOCALE_BLOCKLIST.at(region_index) >> language_index) & 1) == 0;
  40. }
  41. ConfigureSystem::ConfigureSystem(Core::System& system_,
  42. std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
  43. const ConfigurationShared::Builder& builder, QWidget* parent)
  44. : Tab(group_, parent), ui{std::make_unique<Ui::ConfigureSystem>()}, system{system_} {
  45. ui->setupUi(this);
  46. const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
  47. const auto current_time_s =
  48. std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
  49. previous_time = current_time_s + Settings::values.custom_rtc_offset.GetValue();
  50. Setup(builder);
  51. const auto locale_check = [this]() {
  52. const auto region_index = combo_region->currentIndex();
  53. const auto language_index = combo_language->currentIndex();
  54. const bool valid_locale = IsValidLocale(region_index, language_index);
  55. ui->label_warn_invalid_locale->setVisible(!valid_locale);
  56. if (!valid_locale) {
  57. ui->label_warn_invalid_locale->setText(
  58. tr("Warning: \"%1\" is not a valid language for region \"%2\"")
  59. .arg(combo_language->currentText())
  60. .arg(combo_region->currentText()));
  61. }
  62. };
  63. const auto update_date_offset = [this]() {
  64. if (!checkbox_rtc->isChecked()) {
  65. return;
  66. }
  67. auto offset = date_rtc_offset->value();
  68. offset += date_rtc->dateTime().toSecsSinceEpoch() - previous_time;
  69. previous_time = date_rtc->dateTime().toSecsSinceEpoch();
  70. date_rtc_offset->setValue(offset);
  71. };
  72. const auto update_rtc_date = [this]() { UpdateRtcTime(); };
  73. connect(combo_language, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check);
  74. connect(combo_region, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check);
  75. connect(checkbox_rtc, qOverload<int>(&QCheckBox::stateChanged), this, update_rtc_date);
  76. connect(date_rtc_offset, qOverload<int>(&QSpinBox::valueChanged), this, update_rtc_date);
  77. connect(date_rtc, &QDateTimeEdit::dateTimeChanged, this, update_date_offset);
  78. ui->label_warn_invalid_locale->setVisible(false);
  79. locale_check();
  80. SetConfiguration();
  81. UpdateRtcTime();
  82. }
  83. ConfigureSystem::~ConfigureSystem() = default;
  84. void ConfigureSystem::changeEvent(QEvent* event) {
  85. if (event->type() == QEvent::LanguageChange) {
  86. RetranslateUI();
  87. }
  88. QWidget::changeEvent(event);
  89. }
  90. void ConfigureSystem::RetranslateUI() {
  91. ui->retranslateUi(this);
  92. }
  93. void ConfigureSystem::Setup(const ConfigurationShared::Builder& builder) {
  94. auto& core_layout = *ui->core_widget->layout();
  95. auto& system_layout = *ui->system_widget->layout();
  96. std::map<u32, QWidget*> core_hold{};
  97. std::map<u32, QWidget*> system_hold{};
  98. std::vector<Settings::BasicSetting*> settings;
  99. auto push = [&settings](auto& list) {
  100. for (auto setting : list) {
  101. settings.push_back(setting);
  102. }
  103. };
  104. push(Settings::values.linkage.by_category[Settings::Category::Core]);
  105. push(Settings::values.linkage.by_category[Settings::Category::System]);
  106. for (auto setting : settings) {
  107. if (setting->Id() == Settings::values.use_docked_mode.Id() &&
  108. Settings::IsConfiguringGlobal()) {
  109. continue;
  110. }
  111. ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs);
  112. if (widget == nullptr) {
  113. continue;
  114. }
  115. if (!widget->Valid()) {
  116. widget->deleteLater();
  117. continue;
  118. }
  119. // Keep track of the region_index (and language_index) combobox to validate the selected
  120. // settings
  121. if (setting->Id() == Settings::values.region_index.Id()) {
  122. combo_region = widget->combobox;
  123. }
  124. if (setting->Id() == Settings::values.language_index.Id()) {
  125. combo_language = widget->combobox;
  126. }
  127. if (setting->Id() == Settings::values.custom_rtc.Id()) {
  128. checkbox_rtc = widget->checkbox;
  129. }
  130. if (setting->Id() == Settings::values.custom_rtc.Id()) {
  131. date_rtc = widget->date_time_edit;
  132. }
  133. if (setting->Id() == Settings::values.custom_rtc_offset.Id()) {
  134. date_rtc_offset = widget->spinbox;
  135. }
  136. switch (setting->GetCategory()) {
  137. case Settings::Category::Core:
  138. core_hold.emplace(setting->Id(), widget);
  139. break;
  140. case Settings::Category::System:
  141. system_hold.emplace(setting->Id(), widget);
  142. break;
  143. default:
  144. widget->deleteLater();
  145. }
  146. }
  147. for (const auto& [_, widget] : core_hold) {
  148. core_layout.addWidget(widget);
  149. }
  150. for (const auto& [_, widget] : system_hold) {
  151. system_layout.addWidget(widget);
  152. }
  153. }
  154. void ConfigureSystem::UpdateRtcTime() {
  155. const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
  156. previous_time = std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
  157. date_rtc_offset->setEnabled(checkbox_rtc->isChecked());
  158. if (checkbox_rtc->isChecked()) {
  159. previous_time += date_rtc_offset->value();
  160. }
  161. const auto date = QDateTime::fromSecsSinceEpoch(previous_time);
  162. date_rtc->setDateTime(date);
  163. }
  164. void ConfigureSystem::SetConfiguration() {}
  165. void ConfigureSystem::ApplyConfiguration() {
  166. const bool powered_on = system.IsPoweredOn();
  167. for (const auto& func : apply_funcs) {
  168. func(powered_on);
  169. }
  170. UpdateRtcTime();
  171. }