Merge e8debf292d into 67f6735f02
This commit is contained in:
commit
ba507b7413
21 changed files with 784 additions and 118 deletions
|
|
@ -12,6 +12,7 @@ import org.citra.citra_emu.NativeLibrary
|
|||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.features.settings.model.BooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntListSetting
|
||||
import org.citra.citra_emu.features.settings.model.Settings
|
||||
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||
|
|
@ -31,8 +32,16 @@ class ScreenAdjustmentUtil(
|
|||
BooleanSetting.SWAP_SCREEN.boolean = isEnabled
|
||||
settings.saveSetting(BooleanSetting.SWAP_SCREEN, SettingsFile.FILE_NAME_CONFIG)
|
||||
}
|
||||
|
||||
fun cycleLayouts() {
|
||||
val landscapeValues = context.resources.getIntArray(R.array.landscapeValues)
|
||||
|
||||
val landscapeLayoutsToCycle = IntListSetting.LAYOUTS_TO_CYCLE.list;
|
||||
val landscapeValues =
|
||||
if (landscapeLayoutsToCycle.isNotEmpty())
|
||||
landscapeLayoutsToCycle.toIntArray()
|
||||
else context.resources.getIntArray(
|
||||
R.array.landscapeValues
|
||||
)
|
||||
val portraitValues = context.resources.getIntArray(R.array.portraitValues)
|
||||
|
||||
if (NativeLibrary.isPortraitMode) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model
|
||||
|
||||
interface AbstractListSetting<E> : AbstractSetting {
|
||||
var list: List<E>
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model
|
||||
|
||||
enum class IntListSetting(
|
||||
override val key: String,
|
||||
override val section: String,
|
||||
override val defaultValue: List<Int>
|
||||
) : AbstractListSetting<Int> {
|
||||
LAYOUTS_TO_CYCLE("layouts_to_cycle", Settings.SECTION_LAYOUT, listOf(0,1,2,3,4,5));
|
||||
|
||||
override var list: List<Int> = defaultValue
|
||||
|
||||
override val valueAsString: String
|
||||
get() = list.joinToString()
|
||||
|
||||
|
||||
override val isRuntimeEditable: Boolean
|
||||
get() {
|
||||
for (setting in NOT_RUNTIME_EDITABLE) {
|
||||
if (setting == this) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val NOT_RUNTIME_EDITABLE:List<IntListSetting> = listOf();
|
||||
|
||||
|
||||
fun from(key: String): IntListSetting? =
|
||||
values().firstOrNull { it.key == key }
|
||||
|
||||
fun clear() = values().forEach { it.list = it.defaultValue }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model.view
|
||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntListSetting
|
||||
class MultiChoiceSetting(
|
||||
setting: AbstractSetting?,
|
||||
titleId: Int,
|
||||
descriptionId: Int,
|
||||
val choicesId: Int,
|
||||
val valuesId: Int,
|
||||
val key: String? = null,
|
||||
val defaultValue: List<Int>? = null,
|
||||
override var isEnabled: Boolean = true
|
||||
) : SettingsItem(setting, titleId, descriptionId) {
|
||||
override val type = TYPE_MULTI_CHOICE
|
||||
|
||||
val selectedValues: List<Int>
|
||||
get() {
|
||||
if (setting == null) {
|
||||
return defaultValue!!
|
||||
}
|
||||
try {
|
||||
val setting = setting as IntListSetting
|
||||
return setting.list
|
||||
}catch (_: ClassCastException) {
|
||||
}
|
||||
return defaultValue!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value to the backing list. If that int was previously null,
|
||||
* initializes a new one and returns it, so it can be added to the Hashmap.
|
||||
*
|
||||
* @param selection New value of the int.
|
||||
* @return the existing setting with the new value applied.
|
||||
*/
|
||||
fun setSelectedValue(selection: List<Int>): IntListSetting {
|
||||
val intSetting = setting as IntListSetting
|
||||
intSetting.list = selection
|
||||
return intSetting
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -47,5 +47,6 @@ abstract class SettingsItem(
|
|||
const val TYPE_INPUT_BINDING = 8
|
||||
const val TYPE_STRING_INPUT = 9
|
||||
const val TYPE_FLOAT_INPUT = 10
|
||||
const val TYPE_MULTI_CHOICE = 11
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,12 +41,14 @@ import org.citra.citra_emu.features.settings.model.AbstractIntSetting
|
|||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractStringSetting
|
||||
import org.citra.citra_emu.features.settings.model.FloatSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntListSetting
|
||||
import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractShortSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.DateTimeSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
||||
import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SliderSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.StringInputSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting
|
||||
|
|
@ -55,6 +57,7 @@ import org.citra.citra_emu.features.settings.model.view.SwitchSetting
|
|||
import org.citra.citra_emu.features.settings.ui.viewholder.DateTimeViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.HeaderViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.InputBindingSettingViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.MultiChoiceViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.RunnableViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.SettingViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.SingleChoiceViewHolder
|
||||
|
|
@ -72,7 +75,8 @@ import kotlin.math.roundToInt
|
|||
class SettingsAdapter(
|
||||
private val fragmentView: SettingsFragmentView,
|
||||
public val context: Context
|
||||
) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener {
|
||||
) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener,
|
||||
DialogInterface.OnMultiChoiceClickListener {
|
||||
private var settings: ArrayList<SettingsItem>? = null
|
||||
private var clickedItem: SettingsItem? = null
|
||||
private var clickedPosition: Int
|
||||
|
|
@ -104,6 +108,10 @@ class SettingsAdapter(
|
|||
SingleChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_MULTI_CHOICE -> {
|
||||
MultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_SLIDER -> {
|
||||
SliderViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||
}
|
||||
|
|
@ -181,21 +189,30 @@ class SettingsAdapter(
|
|||
SettingsItem.TYPE_SLIDER -> {
|
||||
(oldItem as SliderSetting).isEnabled == (newItem as SliderSetting).isEnabled
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_SWITCH -> {
|
||||
(oldItem as SwitchSetting).isEnabled == (newItem as SwitchSetting).isEnabled
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_SINGLE_CHOICE -> {
|
||||
(oldItem as SingleChoiceSetting).isEnabled == (newItem as SingleChoiceSetting).isEnabled
|
||||
}
|
||||
SettingsItem.TYPE_MULTI_CHOICE -> {
|
||||
(oldItem as MultiChoiceSetting).isEnabled == (newItem as MultiChoiceSetting).isEnabled
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_DATETIME_SETTING -> {
|
||||
(oldItem as DateTimeSetting).isEnabled == (newItem as DateTimeSetting).isEnabled
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {
|
||||
(oldItem as StringSingleChoiceSetting).isEnabled == (newItem as StringSingleChoiceSetting).isEnabled
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_STRING_INPUT -> {
|
||||
(oldItem as StringInputSetting).isEnabled == (newItem as StringInputSetting).isEnabled
|
||||
}
|
||||
|
||||
else -> {
|
||||
oldItem == newItem
|
||||
}
|
||||
|
|
@ -232,6 +249,21 @@ class SettingsAdapter(
|
|||
onSingleChoiceClick(item)
|
||||
}
|
||||
|
||||
private fun onMultiChoiceClick(item: MultiChoiceSetting) {
|
||||
clickedItem = item
|
||||
|
||||
val value: BooleanArray = getSelectionForMultiChoiceValue(item);
|
||||
dialog = MaterialAlertDialogBuilder(context)
|
||||
.setTitle(item.nameId)
|
||||
.setMultiChoiceItems(item.choicesId, value, this)
|
||||
.show()
|
||||
}
|
||||
|
||||
fun onMultiChoiceClick(item: MultiChoiceSetting, position: Int) {
|
||||
clickedPosition = position
|
||||
onMultiChoiceClick(item)
|
||||
}
|
||||
|
||||
private fun onStringSingleChoiceClick(item: StringSingleChoiceSetting) {
|
||||
clickedItem = item
|
||||
dialog = context?.let {
|
||||
|
|
@ -447,6 +479,7 @@ class SettingsAdapter(
|
|||
}
|
||||
it.setSelectedValue(value)
|
||||
}
|
||||
|
||||
is AbstractShortSetting -> {
|
||||
val value = getValueForSingleChoiceSelection(it, which).toShort()
|
||||
if (it.selectedValue.toShort() != value) {
|
||||
|
|
@ -454,6 +487,7 @@ class SettingsAdapter(
|
|||
}
|
||||
it.setSelectedValue(value)
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
||||
}
|
||||
fragmentView?.putSetting(setting)
|
||||
|
|
@ -499,6 +533,7 @@ class SettingsAdapter(
|
|||
val setting = it.setSelectedValue(value)
|
||||
fragmentView?.putSetting(setting)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val setting = it.setSelectedValue(sliderProgress)
|
||||
fragmentView?.putSetting(setting)
|
||||
|
|
@ -527,6 +562,21 @@ class SettingsAdapter(
|
|||
textInputValue = ""
|
||||
}
|
||||
|
||||
//onclick for multichoice
|
||||
override fun onClick(dialog: DialogInterface?, which: Int, isChecked: Boolean) {
|
||||
val mcsetting = clickedItem as? MultiChoiceSetting
|
||||
mcsetting?.let {
|
||||
val value = getValueForMultiChoiceSelection(it, which)
|
||||
if (it.selectedValues.contains(value) != isChecked) {
|
||||
val setting = it.setSelectedValue((if (isChecked) it.selectedValues + value else it.selectedValues - value).sorted())
|
||||
fragmentView?.putSetting(setting)
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
fragmentView.loadSettingsList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun onLongClick(setting: AbstractSetting, position: Int): Boolean {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setMessage(R.string.reset_setting_confirmation)
|
||||
|
|
@ -616,6 +666,16 @@ class SettingsAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getValueForMultiChoiceSelection(item: MultiChoiceSetting, which: Int): Int {
|
||||
val valuesId = item.valuesId
|
||||
return if (valuesId > 0) {
|
||||
val valuesArray = context.resources.getIntArray(valuesId)
|
||||
valuesArray[which]
|
||||
} else {
|
||||
which
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int {
|
||||
val value = item.selectedValue
|
||||
val valuesId = item.valuesId
|
||||
|
|
@ -632,4 +692,20 @@ class SettingsAdapter(
|
|||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
private fun getSelectionForMultiChoiceValue(item: MultiChoiceSetting): BooleanArray {
|
||||
val value = item.selectedValues;
|
||||
val valuesId = item.valuesId;
|
||||
if (valuesId > 0) {
|
||||
val valuesArray = context.resources.getIntArray(valuesId);
|
||||
val res = BooleanArray(valuesArray.size){false}
|
||||
for (index in valuesArray.indices) {
|
||||
if (value.contains(valuesArray[index])) {
|
||||
res[index] = true;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return BooleanArray(1){false};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import android.os.Build
|
|||
import android.text.TextUtils
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.serialization.builtins.IntArraySerializer
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting
|
||||
|
|
@ -24,12 +25,14 @@ import org.citra.citra_emu.features.settings.model.AbstractStringSetting
|
|||
import org.citra.citra_emu.features.settings.model.BooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.FloatSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntListSetting
|
||||
import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
|
||||
import org.citra.citra_emu.features.settings.model.Settings
|
||||
import org.citra.citra_emu.features.settings.model.StringSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.DateTimeSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.HeaderSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.RunnableSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
||||
import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting
|
||||
|
|
@ -1106,6 +1109,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||
BooleanSetting.UPRIGHT_SCREEN.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
MultiChoiceSetting(
|
||||
IntListSetting.LAYOUTS_TO_CYCLE,
|
||||
R.string.layouts_to_cycle,
|
||||
R.string.layouts_to_cycle_description,
|
||||
R.array.landscapeLayouts,
|
||||
R.array.landscapeLayoutValues,
|
||||
IntListSetting.LAYOUTS_TO_CYCLE.key,
|
||||
IntListSetting.LAYOUTS_TO_CYCLE.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.PORTRAIT_SCREEN_LAYOUT,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.view.View
|
||||
import org.citra.citra_emu.databinding.ListItemSettingBinding
|
||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
||||
import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter
|
||||
|
||||
class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
||||
SettingViewHolder(binding.root, adapter) {
|
||||
private lateinit var setting: SettingsItem
|
||||
|
||||
override fun bind(item: SettingsItem) {
|
||||
setting = item
|
||||
binding.textSettingName.setText(item.nameId)
|
||||
if (item.descriptionId != 0) {
|
||||
binding.textSettingDescription.visibility = View.VISIBLE
|
||||
binding.textSettingDescription.setText(item.descriptionId)
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
binding.textSettingValue.visibility = View.VISIBLE
|
||||
binding.textSettingValue.text = getTextSetting()
|
||||
|
||||
if (setting.isActive) {
|
||||
binding.textSettingName.alpha = 1f
|
||||
binding.textSettingDescription.alpha = 1f
|
||||
binding.textSettingValue.alpha = 1f
|
||||
} else {
|
||||
binding.textSettingName.alpha = 0.5f
|
||||
binding.textSettingDescription.alpha = 0.5f
|
||||
binding.textSettingValue.alpha = 0.5f
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTextSetting(): String {
|
||||
when (val item = setting) {
|
||||
is MultiChoiceSetting -> {
|
||||
val resMgr = binding.textSettingDescription.context.resources
|
||||
val values = resMgr.getIntArray(item.valuesId)
|
||||
var resList:List<String> = emptyList();
|
||||
values.forEachIndexed { i: Int, value: Int ->
|
||||
if ((setting as MultiChoiceSetting).selectedValues.contains(value)) {
|
||||
resList = resList + resMgr.getStringArray(item.choicesId)[i];
|
||||
}
|
||||
}
|
||||
return resList.joinToString();
|
||||
}
|
||||
|
||||
else -> return ""
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
if (!setting.isEditable || !setting.isEnabled) {
|
||||
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||
return
|
||||
}
|
||||
|
||||
if (setting is MultiChoiceSetting) {
|
||||
adapter.onMultiChoiceClick(
|
||||
(setting as MultiChoiceSetting),
|
||||
bindingAdapterPosition
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLongClick(clicked: View): Boolean {
|
||||
if (setting.isActive) {
|
||||
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||
} else {
|
||||
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import org.citra.citra_emu.R
|
|||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
import org.citra.citra_emu.features.settings.model.BooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.FloatSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntListSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntSetting
|
||||
import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
|
||||
import org.citra.citra_emu.features.settings.model.SettingSection
|
||||
|
|
@ -255,6 +256,11 @@ object SettingsFile {
|
|||
return stringSetting
|
||||
}
|
||||
|
||||
val intListSetting = IntListSetting.from(key)
|
||||
if (intListSetting != null) {
|
||||
intListSetting.list = value.split(", ").map { it.toInt() }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -341,6 +341,8 @@
|
|||
<string name="layout_screen_orientation_landscape_reverse">Reverse Landscape</string>
|
||||
<string name="layout_screen_orientation_portrait">Portrait</string>
|
||||
<string name="layout_screen_orientation_portrait_reverse">Reverse Portrait</string>
|
||||
<string name="layouts_to_cycle">Layouts to Cycle</string>
|
||||
<string name="layouts_to_cycle_description">Which layouts are cycled by the Cycle Layout hotkey</string>
|
||||
<string name="aspect_ratio_default">Default</string>
|
||||
<string name="aspect_ratio_16_9">16:9</string>
|
||||
<string name="aspect_ratio_4_3">4:3</string>
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ add_library(citra_qt STATIC EXCLUDE_FROM_ALL
|
|||
configuration/configure_layout.cpp
|
||||
configuration/configure_layout.h
|
||||
configuration/configure_layout.ui
|
||||
configuration/configure_layout_cycle.cpp
|
||||
configuration/configure_layout_cycle.h
|
||||
configuration/configure_layout_cycle.ui
|
||||
configuration/configure_dialog.cpp
|
||||
configuration/configure_dialog.h
|
||||
configuration/configure_general.cpp
|
||||
|
|
|
|||
|
|
@ -2694,25 +2694,22 @@ void GMainWindow::AdjustSpeedLimit(bool increase) {
|
|||
|
||||
void GMainWindow::ToggleScreenLayout() {
|
||||
const Settings::LayoutOption new_layout = []() {
|
||||
switch (Settings::values.layout_option.GetValue()) {
|
||||
case Settings::LayoutOption::Default:
|
||||
return Settings::LayoutOption::SingleScreen;
|
||||
case Settings::LayoutOption::SingleScreen:
|
||||
return Settings::LayoutOption::LargeScreen;
|
||||
case Settings::LayoutOption::LargeScreen:
|
||||
return Settings::LayoutOption::HybridScreen;
|
||||
case Settings::LayoutOption::HybridScreen:
|
||||
return Settings::LayoutOption::SideScreen;
|
||||
case Settings::LayoutOption::SideScreen:
|
||||
return Settings::LayoutOption::SeparateWindows;
|
||||
case Settings::LayoutOption::SeparateWindows:
|
||||
return Settings::LayoutOption::CustomLayout;
|
||||
case Settings::LayoutOption::CustomLayout:
|
||||
return Settings::LayoutOption::Default;
|
||||
default:
|
||||
LOG_ERROR(Frontend, "Unknown layout option {}",
|
||||
Settings::values.layout_option.GetValue());
|
||||
return Settings::LayoutOption::Default;
|
||||
const Settings::LayoutOption current_layout = Settings::values.layout_option.GetValue();
|
||||
std::vector<Settings::LayoutOption> layouts_to_cycle =
|
||||
Settings::values.layouts_to_cycle.GetValue();
|
||||
const auto current_pos =
|
||||
distance(layouts_to_cycle.begin(),
|
||||
std::find(layouts_to_cycle.begin(), layouts_to_cycle.end(), current_layout));
|
||||
// if the layouts_to_cycle setting has somehow been
|
||||
// cleared out, add just default back in
|
||||
if (layouts_to_cycle.size() == 0) {
|
||||
layouts_to_cycle.push_back(Settings::LayoutOption::Default);
|
||||
}
|
||||
if (current_pos >= layouts_to_cycle.size() - 1) {
|
||||
// either this layout wasn't found or it was last so move to the beginning
|
||||
return layouts_to_cycle[0];
|
||||
} else {
|
||||
return layouts_to_cycle[current_pos + 1];
|
||||
}
|
||||
}();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include <array>
|
||||
#include <QKeySequence>
|
||||
#include <QSettings>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include "citra_qt/configuration/config.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/settings.h"
|
||||
|
|
@ -132,6 +134,35 @@ void QtConfig::ReadBasicSetting(Settings::Setting<std::string>& setting) {
|
|||
setting.SetValue(qt_config->value(name, default_value).toString().toStdString());
|
||||
}
|
||||
}
|
||||
// definition for vectors of enums
|
||||
template <typename Type, bool ranged>
|
||||
void QtConfig::ReadBasicSetting(Settings::Setting<std::vector<Type>, ranged>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const std::vector<Type> default_value = setting.GetDefault();
|
||||
QStringList stringList = qt_config->value(name).toStringList();
|
||||
|
||||
if (qt_config->value(name + QStringLiteral("/default"), false).toBool() ||
|
||||
stringList.size() < 1) {
|
||||
setting.SetValue(default_value);
|
||||
} else {
|
||||
if (stringList.size() < 1) {
|
||||
setting.SetValue(default_value);
|
||||
} else {
|
||||
std::vector<Type> newValue;
|
||||
for (const QString& str : stringList) {
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
using TypeU = std::underlying_type_t<Type>;
|
||||
newValue.push_back(static_cast<Type>(str.toInt()));
|
||||
} else if constexpr (std::is_integral_v<Type>) {
|
||||
newValue.push_back(str.toInt());
|
||||
} else {
|
||||
newValue.push_back(str.toStdString());
|
||||
}
|
||||
}
|
||||
setting.SetValue(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type, bool ranged>
|
||||
void QtConfig::ReadBasicSetting(Settings::Setting<Type, ranged>& setting) {
|
||||
|
|
@ -158,27 +189,7 @@ void QtConfig::ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& sett
|
|||
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
|
||||
setting.SetGlobal(use_global);
|
||||
if (global || !use_global) {
|
||||
QVariant default_value{};
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
using TypeU = std::underlying_type_t<Type>;
|
||||
default_value = QVariant::fromValue<TypeU>(static_cast<TypeU>(setting.GetDefault()));
|
||||
setting.SetValue(static_cast<Type>(ReadSetting(name, default_value).value<TypeU>()));
|
||||
} else {
|
||||
default_value = QVariant::fromValue<Type>(setting.GetDefault());
|
||||
setting.SetValue(ReadSetting(name, default_value).value<Type>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void QtConfig::ReadGlobalSetting(Settings::SwitchableSetting<std::string>& setting) {
|
||||
QString name = QString::fromStdString(setting.GetLabel());
|
||||
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
|
||||
setting.SetGlobal(use_global);
|
||||
if (global || !use_global) {
|
||||
const QString default_value = QString::fromStdString(setting.GetDefault());
|
||||
setting.SetValue(
|
||||
ReadSetting(name, QVariant::fromValue(default_value)).toString().toStdString());
|
||||
ReadBasicSetting(setting);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,15 +198,40 @@ template <>
|
|||
void QtConfig::WriteBasicSetting(const Settings::Setting<std::string>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const std::string& value = setting.GetValue();
|
||||
if (global)
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
qt_config->setValue(name, QString::fromStdString(value));
|
||||
}
|
||||
|
||||
template <typename Type, bool ranged>
|
||||
void QtConfig::WriteBasicSetting(const Settings::Setting<std::vector<Type>, ranged>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const std::vector<Type>& value = setting.GetValue();
|
||||
|
||||
if (global)
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
|
||||
QStringList stringList;
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
// For enums, convert to underlying integer type strings
|
||||
using TypeU = std::underlying_type_t<Type>;
|
||||
for (const Type& item : value) {
|
||||
stringList.append(QString::number(static_cast<TypeU>(item)));
|
||||
}
|
||||
} else {
|
||||
// For non-enum types (assuming numeric)
|
||||
for (const Type& item : value) {
|
||||
stringList.append(QString::number(item));
|
||||
}
|
||||
}
|
||||
qt_config->setValue(name, stringList);
|
||||
}
|
||||
// Explicit u16 definition: Qt would store it as QMetaType otherwise, which is not human-readable
|
||||
template <>
|
||||
void QtConfig::WriteBasicSetting(const Settings::Setting<u16>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const u16& value = setting.GetValue();
|
||||
if (global)
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
qt_config->setValue(name, static_cast<u32>(value));
|
||||
}
|
||||
|
|
@ -204,6 +240,7 @@ template <typename Type, bool ranged>
|
|||
void QtConfig::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const Type value = setting.GetValue();
|
||||
if (global)
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
qt_config->setValue(name, static_cast<std::underlying_type_t<Type>>(value));
|
||||
|
|
@ -215,44 +252,11 @@ void QtConfig::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting)
|
|||
template <typename Type, bool ranged>
|
||||
void QtConfig::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const Type& value = setting.GetValue(global);
|
||||
if (!global) {
|
||||
qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
|
||||
}
|
||||
if (global || !setting.UsingGlobal()) {
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
qt_config->setValue(name, static_cast<std::underlying_type_t<Type>>(value));
|
||||
} else {
|
||||
qt_config->setValue(name, QVariant::fromValue(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void QtConfig::WriteGlobalSetting(const Settings::SwitchableSetting<std::string>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const std::string& value = setting.GetValue(global);
|
||||
if (!global) {
|
||||
qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
|
||||
}
|
||||
if (global || !setting.UsingGlobal()) {
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
qt_config->setValue(name, QString::fromStdString(value));
|
||||
}
|
||||
}
|
||||
|
||||
// Explicit u16 definition: Qt would store it as QMetaType otherwise, which is not human-readable
|
||||
template <>
|
||||
void QtConfig::WriteGlobalSetting(const Settings::SwitchableSetting<u16, true>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const u16& value = setting.GetValue(global);
|
||||
if (!global) {
|
||||
qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
|
||||
}
|
||||
if (global || !setting.UsingGlobal()) {
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
qt_config->setValue(name, static_cast<u32>(value));
|
||||
WriteBasicSetting(setting);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -526,7 +530,7 @@ void QtConfig::ReadLayoutValues() {
|
|||
ReadGlobalSetting(Settings::values.large_screen_proportion);
|
||||
ReadGlobalSetting(Settings::values.screen_gap);
|
||||
ReadGlobalSetting(Settings::values.small_screen_position);
|
||||
|
||||
ReadGlobalSetting(Settings::values.layouts_to_cycle);
|
||||
if (global) {
|
||||
ReadBasicSetting(Settings::values.mono_render_option);
|
||||
ReadBasicSetting(Settings::values.custom_top_x);
|
||||
|
|
@ -1091,6 +1095,7 @@ void QtConfig::SaveLayoutValues() {
|
|||
WriteGlobalSetting(Settings::values.large_screen_proportion);
|
||||
WriteGlobalSetting(Settings::values.screen_gap);
|
||||
WriteGlobalSetting(Settings::values.small_screen_position);
|
||||
WriteGlobalSetting(Settings::values.layouts_to_cycle);
|
||||
if (global) {
|
||||
WriteBasicSetting(Settings::values.mono_render_option);
|
||||
WriteBasicSetting(Settings::values.custom_top_x);
|
||||
|
|
@ -1418,6 +1423,7 @@ void QtConfig::WriteSetting(const QString& name, const QVariant& value) {
|
|||
|
||||
void QtConfig::WriteSetting(const QString& name, const QVariant& value,
|
||||
const QVariant& default_value) {
|
||||
if (global)
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
|
||||
qt_config->setValue(name, value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,10 @@ private:
|
|||
template <typename Type, bool ranged>
|
||||
void ReadBasicSetting(Settings::Setting<Type, ranged>& setting);
|
||||
|
||||
// Add overload for vectors
|
||||
template <typename Type, bool ranged>
|
||||
void ReadBasicSetting(Settings::Setting<std::vector<Type>, ranged>& setting);
|
||||
|
||||
/** Sets a value from the setting in the qt_config using the setting's label and default value.
|
||||
*
|
||||
* @param The setting
|
||||
|
|
@ -127,6 +131,9 @@ private:
|
|||
template <typename Type, bool ranged>
|
||||
void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting);
|
||||
|
||||
template <typename Type, bool ranged>
|
||||
void WriteBasicSetting(const Settings::Setting<std::vector<Type>, ranged>& setting);
|
||||
|
||||
ConfigType type;
|
||||
std::unique_ptr<QSettings> qt_config;
|
||||
std::string qt_config_loc;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <QtGlobal>
|
||||
#include "citra_qt/configuration/configuration_shared.h"
|
||||
#include "citra_qt/configuration/configure_layout.h"
|
||||
#include "citra_qt/configuration/configure_layout_cycle.h"
|
||||
#include "common/settings.h"
|
||||
#include "ui_configure_layout.h"
|
||||
#ifdef ENABLE_OPENGL
|
||||
|
|
@ -111,6 +112,13 @@ ConfigureLayout::ConfigureLayout(QWidget* parent)
|
|||
ui->bg_button->setIcon(color_icon);
|
||||
ui->bg_button->setEnabled(true);
|
||||
});
|
||||
|
||||
connect(ui->customize_layouts_to_cycle, &QPushButton::clicked, this, [this] {
|
||||
ui->customize_layouts_to_cycle->setEnabled(false);
|
||||
QDialog* layout_cycle_dialog = new ConfigureLayoutCycle(this);
|
||||
layout_cycle_dialog->exec();
|
||||
ui->customize_layouts_to_cycle->setEnabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
ConfigureLayout::~ConfigureLayout() = default;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>705</width>
|
||||
<height>656</height>
|
||||
<width>659</width>
|
||||
<height>662</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
|
|
@ -51,8 +51,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>688</width>
|
||||
<height>799</height>
|
||||
<width>646</width>
|
||||
<height>824</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
|
|
@ -130,12 +130,9 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_swap_screen">
|
||||
<property name="text">
|
||||
<string>Swap screens</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_upright_screen">
|
||||
<property name="text">
|
||||
|
|
@ -143,6 +140,30 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_swap_screen">
|
||||
<property name="text">
|
||||
<string>Swap screens</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="customize_layouts_to_cycle">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Customize layout cycling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="screen_gap_layout">
|
||||
|
|
@ -356,7 +377,7 @@
|
|||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="custom_top_x">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -376,7 +397,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="custom_top_y">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -396,7 +417,7 @@
|
|||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="custom_top_width">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -416,7 +437,7 @@
|
|||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="custom_top_height">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -440,6 +461,12 @@
|
|||
<property name="title">
|
||||
<string>Bottom Screen</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lb_bottom_x">
|
||||
|
|
@ -451,7 +478,7 @@
|
|||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="custom_bottom_x">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -471,7 +498,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="custom_bottom_y">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -491,7 +518,7 @@
|
|||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="custom_bottom_width">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -511,7 +538,7 @@
|
|||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="custom_bottom_height">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -538,7 +565,7 @@
|
|||
<item>
|
||||
<widget class="QSpinBox" name="custom_second_layer_opacity">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::PlusMinus</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
|
|
@ -583,7 +610,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="screen_top_leftright_padding">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -610,7 +637,7 @@
|
|||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="screen_top_topbottom_padding">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -659,7 +686,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="screen_bottom_leftright_padding">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -672,7 +699,7 @@
|
|||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="screen_bottom_topbottom_padding">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
|
|
@ -717,9 +744,6 @@
|
|||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
|
|
|
|||
81
src/citra_qt/configuration/configure_layout_cycle.cpp
Normal file
81
src/citra_qt/configuration/configure_layout_cycle.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include <QCloseEvent>
|
||||
#include <QDialog>
|
||||
#include "citra_qt/configuration/configure_layout_cycle.h"
|
||||
#include "ui_configure_layout_cycle.h"
|
||||
|
||||
ConfigureLayoutCycle::ConfigureLayoutCycle(QWidget* parent)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::ConfigureLayoutCycle>()) {
|
||||
ui->setupUi(this);
|
||||
SetConfiguration();
|
||||
ConnectEvents();
|
||||
}
|
||||
|
||||
// You MUST define the destructor in the .cpp file
|
||||
ConfigureLayoutCycle::~ConfigureLayoutCycle() = default;
|
||||
|
||||
void ConfigureLayoutCycle::ConnectEvents() {
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
|
||||
&ConfigureLayoutCycle::ApplyConfiguration);
|
||||
connect(ui->globalCheck, &QCheckBox::stateChanged, this, &ConfigureLayoutCycle::UpdateGlobal);
|
||||
}
|
||||
|
||||
void ConfigureLayoutCycle::SetConfiguration() {
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
ui->globalCheck->setChecked(true);
|
||||
ui->globalCheck->setVisible(false);
|
||||
} else {
|
||||
ui->globalCheck->setChecked(Settings::values.layouts_to_cycle.UsingGlobal());
|
||||
ui->checkGroup->setDisabled(Settings::values.layouts_to_cycle.UsingGlobal());
|
||||
}
|
||||
for (auto option : Settings::values.layouts_to_cycle.GetValue()) {
|
||||
switch (option) {
|
||||
case Settings::LayoutOption::Default:
|
||||
ui->defaultCheck->setChecked(true);
|
||||
break;
|
||||
case Settings::LayoutOption::SingleScreen:
|
||||
ui->singleCheck->setChecked(true);
|
||||
break;
|
||||
case Settings::LayoutOption::LargeScreen:
|
||||
ui->largeCheck->setChecked(true);
|
||||
break;
|
||||
case Settings::LayoutOption::SideScreen:
|
||||
ui->sidebysideCheck->setChecked(true);
|
||||
break;
|
||||
case Settings::LayoutOption::SeparateWindows:
|
||||
ui->separateCheck->setChecked(true);
|
||||
break;
|
||||
case Settings::LayoutOption::HybridScreen:
|
||||
ui->hybridCheck->setChecked(true);
|
||||
break;
|
||||
case Settings::LayoutOption::CustomLayout:
|
||||
ui->customCheck->setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureLayoutCycle::ApplyConfiguration() {
|
||||
std::vector<Settings::LayoutOption> newSetting{};
|
||||
if (ui->defaultCheck->isChecked())
|
||||
newSetting.push_back(Settings::LayoutOption::Default);
|
||||
if (ui->singleCheck->isChecked())
|
||||
newSetting.push_back(Settings::LayoutOption::SingleScreen);
|
||||
if (ui->sidebysideCheck->isChecked())
|
||||
newSetting.push_back(Settings::LayoutOption::SideScreen);
|
||||
if (ui->largeCheck->isChecked())
|
||||
newSetting.push_back(Settings::LayoutOption::LargeScreen);
|
||||
if (ui->separateCheck->isChecked())
|
||||
newSetting.push_back(Settings::LayoutOption::SeparateWindows);
|
||||
if (ui->hybridCheck->isChecked())
|
||||
newSetting.push_back(Settings::LayoutOption::HybridScreen);
|
||||
if (ui->customCheck->isChecked())
|
||||
newSetting.push_back(Settings::LayoutOption::CustomLayout);
|
||||
Settings::values.layouts_to_cycle = newSetting;
|
||||
accept();
|
||||
}
|
||||
|
||||
void ConfigureLayoutCycle::UpdateGlobal() {
|
||||
Settings::values.layouts_to_cycle.SetGlobal(ui->globalCheck->isChecked());
|
||||
ui->checkGroup->setDisabled(ui->globalCheck->isChecked());
|
||||
ui->checkGroup->repaint(); // Force visual update
|
||||
}
|
||||
32
src/citra_qt/configuration/configure_layout_cycle.h
Normal file
32
src/citra_qt/configuration/configure_layout_cycle.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2018 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <QDialog>
|
||||
#include "common/settings.h"
|
||||
|
||||
namespace Ui {
|
||||
class ConfigureLayoutCycle;
|
||||
}
|
||||
|
||||
class ConfigureLayoutCycle : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureLayoutCycle(QWidget* parent = nullptr);
|
||||
~ConfigureLayoutCycle() override;
|
||||
|
||||
public slots:
|
||||
void ApplyConfiguration();
|
||||
|
||||
private slots:
|
||||
|
||||
private:
|
||||
void SetConfiguration();
|
||||
void ConnectEvents();
|
||||
void UpdateGlobal();
|
||||
|
||||
std::unique_ptr<Ui::ConfigureLayoutCycle> ui;
|
||||
};
|
||||
216
src/citra_qt/configuration/configure_layout_cycle.ui
Normal file
216
src/citra_qt/configuration/configure_layout_cycle.ui
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConfigureLayoutCycle</class>
|
||||
<widget class="QDialog" name="ConfigureLayoutCycle">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>395</width>
|
||||
<height>334</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Layout Cycling</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>381</width>
|
||||
<height>323</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,0,0,1">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Screen Layout Cycling Customization</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="instructions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select which screen layout options should be cycled with the "Toggle Screen Layout" hotkey</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="globalCheck">
|
||||
<property name="text">
|
||||
<string>Use Global Value</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="checkGroup">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vertLayout">
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="defaultCheck">
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="singleCheck">
|
||||
<property name="text">
|
||||
<string>Single Screen</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="largeCheck">
|
||||
<property name="text">
|
||||
<string>Large Screen</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="sidebysideCheck">
|
||||
<property name="text">
|
||||
<string>Side by Side</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="separateCheck">
|
||||
<property name="text">
|
||||
<string>Separate Windows</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="hybridCheck">
|
||||
<property name="text">
|
||||
<string>Hybrid</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="customCheck">
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureLayoutCycle</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureLayoutCycle</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
@ -120,6 +120,7 @@ void LogSettings() {
|
|||
log_setting("Layout_ScreenGap", values.screen_gap.GetValue());
|
||||
log_setting("Layout_LargeScreenProportion", values.large_screen_proportion.GetValue());
|
||||
log_setting("Layout_SmallScreenPosition", values.small_screen_position.GetValue());
|
||||
// log_setting("Layout_LayoutsToCycle",values.layouts_to_cycle.GetValue());
|
||||
log_setting("Utility_DumpTextures", values.dump_textures.GetValue());
|
||||
log_setting("Utility_CustomTextures", values.custom_textures.GetValue());
|
||||
log_setting("Utility_PreloadTextures", values.preload_textures.GetValue());
|
||||
|
|
@ -209,6 +210,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
|||
values.layout_option.SetGlobal(true);
|
||||
values.portrait_layout_option.SetGlobal(true);
|
||||
values.secondary_display_layout.SetGlobal(true);
|
||||
values.layouts_to_cycle.SetGlobal(true);
|
||||
values.swap_screen.SetGlobal(true);
|
||||
values.upright_screen.SetGlobal(true);
|
||||
values.large_screen_proportion.SetGlobal(true);
|
||||
|
|
|
|||
|
|
@ -522,6 +522,14 @@ struct Values {
|
|||
SwitchableSetting<bool> upright_screen{false, "upright_screen"};
|
||||
SwitchableSetting<SecondaryDisplayLayout> secondary_display_layout{SecondaryDisplayLayout::None,
|
||||
"secondary_display_layout"};
|
||||
SwitchableSetting<std::vector<LayoutOption>> layouts_to_cycle{
|
||||
{LayoutOption::Default, LayoutOption::SingleScreen, LayoutOption::LargeScreen,
|
||||
LayoutOption::SideScreen,
|
||||
#ifndef ANDROID
|
||||
LayoutOption::SeparateWindows,
|
||||
#endif
|
||||
LayoutOption::HybridScreen, LayoutOption::CustomLayout},
|
||||
"layouts_to_cycle"};
|
||||
SwitchableSetting<float, true> large_screen_proportion{4.f, 1.f, 16.f,
|
||||
"large_screen_proportion"};
|
||||
SwitchableSetting<int> screen_gap{0, "screen_gap"};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue