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.R
|
||||||
import org.citra.citra_emu.features.settings.model.BooleanSetting
|
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.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.model.Settings
|
||||||
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||||
|
|
@ -31,8 +32,16 @@ class ScreenAdjustmentUtil(
|
||||||
BooleanSetting.SWAP_SCREEN.boolean = isEnabled
|
BooleanSetting.SWAP_SCREEN.boolean = isEnabled
|
||||||
settings.saveSetting(BooleanSetting.SWAP_SCREEN, SettingsFile.FILE_NAME_CONFIG)
|
settings.saveSetting(BooleanSetting.SWAP_SCREEN, SettingsFile.FILE_NAME_CONFIG)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cycleLayouts() {
|
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)
|
val portraitValues = context.resources.getIntArray(R.array.portraitValues)
|
||||||
|
|
||||||
if (NativeLibrary.isPortraitMode) {
|
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_INPUT_BINDING = 8
|
||||||
const val TYPE_STRING_INPUT = 9
|
const val TYPE_STRING_INPUT = 9
|
||||||
const val TYPE_FLOAT_INPUT = 10
|
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.AbstractSetting
|
||||||
import org.citra.citra_emu.features.settings.model.AbstractStringSetting
|
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.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.ScaledFloatSetting
|
||||||
import org.citra.citra_emu.features.settings.model.AbstractShortSetting
|
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.DateTimeSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
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.SettingsItem
|
||||||
import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting
|
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.SliderSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.StringInputSetting
|
import org.citra.citra_emu.features.settings.model.view.StringInputSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting
|
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.DateTimeViewHolder
|
||||||
import org.citra.citra_emu.features.settings.ui.viewholder.HeaderViewHolder
|
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.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.RunnableViewHolder
|
||||||
import org.citra.citra_emu.features.settings.ui.viewholder.SettingViewHolder
|
import org.citra.citra_emu.features.settings.ui.viewholder.SettingViewHolder
|
||||||
import org.citra.citra_emu.features.settings.ui.viewholder.SingleChoiceViewHolder
|
import org.citra.citra_emu.features.settings.ui.viewholder.SingleChoiceViewHolder
|
||||||
|
|
@ -72,7 +75,8 @@ import kotlin.math.roundToInt
|
||||||
class SettingsAdapter(
|
class SettingsAdapter(
|
||||||
private val fragmentView: SettingsFragmentView,
|
private val fragmentView: SettingsFragmentView,
|
||||||
public val context: Context
|
public val context: Context
|
||||||
) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener {
|
) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener,
|
||||||
|
DialogInterface.OnMultiChoiceClickListener {
|
||||||
private var settings: ArrayList<SettingsItem>? = null
|
private var settings: ArrayList<SettingsItem>? = null
|
||||||
private var clickedItem: SettingsItem? = null
|
private var clickedItem: SettingsItem? = null
|
||||||
private var clickedPosition: Int
|
private var clickedPosition: Int
|
||||||
|
|
@ -104,6 +108,10 @@ class SettingsAdapter(
|
||||||
SingleChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
SingleChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsItem.TYPE_MULTI_CHOICE -> {
|
||||||
|
MultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||||
|
}
|
||||||
|
|
||||||
SettingsItem.TYPE_SLIDER -> {
|
SettingsItem.TYPE_SLIDER -> {
|
||||||
SliderViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
SliderViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||||
}
|
}
|
||||||
|
|
@ -181,21 +189,30 @@ class SettingsAdapter(
|
||||||
SettingsItem.TYPE_SLIDER -> {
|
SettingsItem.TYPE_SLIDER -> {
|
||||||
(oldItem as SliderSetting).isEnabled == (newItem as SliderSetting).isEnabled
|
(oldItem as SliderSetting).isEnabled == (newItem as SliderSetting).isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsItem.TYPE_SWITCH -> {
|
SettingsItem.TYPE_SWITCH -> {
|
||||||
(oldItem as SwitchSetting).isEnabled == (newItem as SwitchSetting).isEnabled
|
(oldItem as SwitchSetting).isEnabled == (newItem as SwitchSetting).isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsItem.TYPE_SINGLE_CHOICE -> {
|
SettingsItem.TYPE_SINGLE_CHOICE -> {
|
||||||
(oldItem as SingleChoiceSetting).isEnabled == (newItem as SingleChoiceSetting).isEnabled
|
(oldItem as SingleChoiceSetting).isEnabled == (newItem as SingleChoiceSetting).isEnabled
|
||||||
}
|
}
|
||||||
|
SettingsItem.TYPE_MULTI_CHOICE -> {
|
||||||
|
(oldItem as MultiChoiceSetting).isEnabled == (newItem as MultiChoiceSetting).isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
SettingsItem.TYPE_DATETIME_SETTING -> {
|
SettingsItem.TYPE_DATETIME_SETTING -> {
|
||||||
(oldItem as DateTimeSetting).isEnabled == (newItem as DateTimeSetting).isEnabled
|
(oldItem as DateTimeSetting).isEnabled == (newItem as DateTimeSetting).isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {
|
SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {
|
||||||
(oldItem as StringSingleChoiceSetting).isEnabled == (newItem as StringSingleChoiceSetting).isEnabled
|
(oldItem as StringSingleChoiceSetting).isEnabled == (newItem as StringSingleChoiceSetting).isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsItem.TYPE_STRING_INPUT -> {
|
SettingsItem.TYPE_STRING_INPUT -> {
|
||||||
(oldItem as StringInputSetting).isEnabled == (newItem as StringInputSetting).isEnabled
|
(oldItem as StringInputSetting).isEnabled == (newItem as StringInputSetting).isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
oldItem == newItem
|
oldItem == newItem
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +231,7 @@ class SettingsAdapter(
|
||||||
|
|
||||||
// If statement is required otherwise the app will crash on activity recreate ex. theme settings
|
// If statement is required otherwise the app will crash on activity recreate ex. theme settings
|
||||||
if (fragmentView.activityView != null)
|
if (fragmentView.activityView != null)
|
||||||
// Reload the settings list to update the UI
|
// Reload the settings list to update the UI
|
||||||
fragmentView.loadSettingsList()
|
fragmentView.loadSettingsList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,6 +249,21 @@ class SettingsAdapter(
|
||||||
onSingleChoiceClick(item)
|
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) {
|
private fun onStringSingleChoiceClick(item: StringSingleChoiceSetting) {
|
||||||
clickedItem = item
|
clickedItem = item
|
||||||
dialog = context?.let {
|
dialog = context?.let {
|
||||||
|
|
@ -360,14 +392,14 @@ class SettingsAdapter(
|
||||||
sliderString = sliderProgress.roundToInt().toString()
|
sliderString = sliderProgress.roundToInt().toString()
|
||||||
if (textSliderValue?.text.toString() != sliderString) {
|
if (textSliderValue?.text.toString() != sliderString) {
|
||||||
textSliderValue?.setText(sliderString)
|
textSliderValue?.setText(sliderString)
|
||||||
textSliderValue?.setSelection(textSliderValue?.length() ?: 0 )
|
textSliderValue?.setSelection(textSliderValue?.length() ?: 0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val currentText = textSliderValue?.text.toString()
|
val currentText = textSliderValue?.text.toString()
|
||||||
val currentTextValue = currentText.toFloat()
|
val currentTextValue = currentText.toFloat()
|
||||||
if (currentTextValue != sliderProgress) {
|
if (currentTextValue != sliderProgress) {
|
||||||
textSliderValue?.setText(sliderString)
|
textSliderValue?.setText(sliderString)
|
||||||
textSliderValue?.setSelection(textSliderValue?.length() ?: 0 )
|
textSliderValue?.setSelection(textSliderValue?.length() ?: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -447,6 +479,7 @@ class SettingsAdapter(
|
||||||
}
|
}
|
||||||
it.setSelectedValue(value)
|
it.setSelectedValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
is AbstractShortSetting -> {
|
is AbstractShortSetting -> {
|
||||||
val value = getValueForSingleChoiceSelection(it, which).toShort()
|
val value = getValueForSingleChoiceSelection(it, which).toShort()
|
||||||
if (it.selectedValue.toShort() != value) {
|
if (it.selectedValue.toShort() != value) {
|
||||||
|
|
@ -454,6 +487,7 @@ class SettingsAdapter(
|
||||||
}
|
}
|
||||||
it.setSelectedValue(value)
|
it.setSelectedValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
||||||
}
|
}
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
|
|
@ -499,11 +533,12 @@ class SettingsAdapter(
|
||||||
val setting = it.setSelectedValue(value)
|
val setting = it.setSelectedValue(value)
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val setting = it.setSelectedValue(sliderProgress)
|
val setting = it.setSelectedValue(sliderProgress)
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fragmentView.loadSettingsList()
|
fragmentView.loadSettingsList()
|
||||||
closeDialog()
|
closeDialog()
|
||||||
}
|
}
|
||||||
|
|
@ -519,7 +554,7 @@ class SettingsAdapter(
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
fragmentView.loadSettingsList()
|
fragmentView.loadSettingsList()
|
||||||
closeDialog()
|
closeDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clickedItem = null
|
clickedItem = null
|
||||||
|
|
@ -527,6 +562,21 @@ class SettingsAdapter(
|
||||||
textInputValue = ""
|
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 {
|
fun onLongClick(setting: AbstractSetting, position: Int): Boolean {
|
||||||
MaterialAlertDialogBuilder(context)
|
MaterialAlertDialogBuilder(context)
|
||||||
.setMessage(R.string.reset_setting_confirmation)
|
.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 {
|
private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int {
|
||||||
val value = item.selectedValue
|
val value = item.selectedValue
|
||||||
val valuesId = item.valuesId
|
val valuesId = item.valuesId
|
||||||
|
|
@ -632,4 +692,20 @@ class SettingsAdapter(
|
||||||
}
|
}
|
||||||
return -1
|
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 android.text.TextUtils
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import kotlinx.serialization.builtins.IntArraySerializer
|
||||||
import org.citra.citra_emu.CitraApplication
|
import org.citra.citra_emu.CitraApplication
|
||||||
import org.citra.citra_emu.R
|
import org.citra.citra_emu.R
|
||||||
import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting
|
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.BooleanSetting
|
||||||
import org.citra.citra_emu.features.settings.model.FloatSetting
|
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.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.ScaledFloatSetting
|
||||||
import org.citra.citra_emu.features.settings.model.Settings
|
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.StringSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.DateTimeSetting
|
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.HeaderSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
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.RunnableSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
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.SingleChoiceSetting
|
||||||
|
|
@ -1106,6 +1109,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||||
BooleanSetting.UPRIGHT_SCREEN.defaultValue
|
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(
|
add(
|
||||||
SingleChoiceSetting(
|
SingleChoiceSetting(
|
||||||
IntSetting.PORTRAIT_SCREEN_LAYOUT,
|
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.AbstractSetting
|
||||||
import org.citra.citra_emu.features.settings.model.BooleanSetting
|
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.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.IntSetting
|
||||||
import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
|
import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
|
||||||
import org.citra.citra_emu.features.settings.model.SettingSection
|
import org.citra.citra_emu.features.settings.model.SettingSection
|
||||||
|
|
@ -255,6 +256,11 @@ object SettingsFile {
|
||||||
return stringSetting
|
return stringSetting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val intListSetting = IntListSetting.from(key)
|
||||||
|
if (intListSetting != null) {
|
||||||
|
intListSetting.list = value.split(", ").map { it.toInt() }
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -341,6 +341,8 @@
|
||||||
<string name="layout_screen_orientation_landscape_reverse">Reverse Landscape</string>
|
<string name="layout_screen_orientation_landscape_reverse">Reverse Landscape</string>
|
||||||
<string name="layout_screen_orientation_portrait">Portrait</string>
|
<string name="layout_screen_orientation_portrait">Portrait</string>
|
||||||
<string name="layout_screen_orientation_portrait_reverse">Reverse 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_default">Default</string>
|
||||||
<string name="aspect_ratio_16_9">16:9</string>
|
<string name="aspect_ratio_16_9">16:9</string>
|
||||||
<string name="aspect_ratio_4_3">4:3</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.cpp
|
||||||
configuration/configure_layout.h
|
configuration/configure_layout.h
|
||||||
configuration/configure_layout.ui
|
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.cpp
|
||||||
configuration/configure_dialog.h
|
configuration/configure_dialog.h
|
||||||
configuration/configure_general.cpp
|
configuration/configure_general.cpp
|
||||||
|
|
|
||||||
|
|
@ -2694,25 +2694,22 @@ void GMainWindow::AdjustSpeedLimit(bool increase) {
|
||||||
|
|
||||||
void GMainWindow::ToggleScreenLayout() {
|
void GMainWindow::ToggleScreenLayout() {
|
||||||
const Settings::LayoutOption new_layout = []() {
|
const Settings::LayoutOption new_layout = []() {
|
||||||
switch (Settings::values.layout_option.GetValue()) {
|
const Settings::LayoutOption current_layout = Settings::values.layout_option.GetValue();
|
||||||
case Settings::LayoutOption::Default:
|
std::vector<Settings::LayoutOption> layouts_to_cycle =
|
||||||
return Settings::LayoutOption::SingleScreen;
|
Settings::values.layouts_to_cycle.GetValue();
|
||||||
case Settings::LayoutOption::SingleScreen:
|
const auto current_pos =
|
||||||
return Settings::LayoutOption::LargeScreen;
|
distance(layouts_to_cycle.begin(),
|
||||||
case Settings::LayoutOption::LargeScreen:
|
std::find(layouts_to_cycle.begin(), layouts_to_cycle.end(), current_layout));
|
||||||
return Settings::LayoutOption::HybridScreen;
|
// if the layouts_to_cycle setting has somehow been
|
||||||
case Settings::LayoutOption::HybridScreen:
|
// cleared out, add just default back in
|
||||||
return Settings::LayoutOption::SideScreen;
|
if (layouts_to_cycle.size() == 0) {
|
||||||
case Settings::LayoutOption::SideScreen:
|
layouts_to_cycle.push_back(Settings::LayoutOption::Default);
|
||||||
return Settings::LayoutOption::SeparateWindows;
|
}
|
||||||
case Settings::LayoutOption::SeparateWindows:
|
if (current_pos >= layouts_to_cycle.size() - 1) {
|
||||||
return Settings::LayoutOption::CustomLayout;
|
// either this layout wasn't found or it was last so move to the beginning
|
||||||
case Settings::LayoutOption::CustomLayout:
|
return layouts_to_cycle[0];
|
||||||
return Settings::LayoutOption::Default;
|
} else {
|
||||||
default:
|
return layouts_to_cycle[current_pos + 1];
|
||||||
LOG_ERROR(Frontend, "Unknown layout option {}",
|
|
||||||
Settings::values.layout_option.GetValue());
|
|
||||||
return Settings::LayoutOption::Default;
|
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <QKeySequence>
|
#include <QKeySequence>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QVector>
|
||||||
#include "citra_qt/configuration/config.h"
|
#include "citra_qt/configuration/config.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "common/settings.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());
|
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>
|
template <typename Type, bool ranged>
|
||||||
void QtConfig::ReadBasicSetting(Settings::Setting<Type, ranged>& setting) {
|
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();
|
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
|
||||||
setting.SetGlobal(use_global);
|
setting.SetGlobal(use_global);
|
||||||
if (global || !use_global) {
|
if (global || !use_global) {
|
||||||
QVariant default_value{};
|
ReadBasicSetting(setting);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,16 +198,41 @@ template <>
|
||||||
void QtConfig::WriteBasicSetting(const Settings::Setting<std::string>& setting) {
|
void QtConfig::WriteBasicSetting(const Settings::Setting<std::string>& setting) {
|
||||||
const QString name = QString::fromStdString(setting.GetLabel());
|
const QString name = QString::fromStdString(setting.GetLabel());
|
||||||
const std::string& value = setting.GetValue();
|
const std::string& value = setting.GetValue();
|
||||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
if (global)
|
||||||
|
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||||
qt_config->setValue(name, QString::fromStdString(value));
|
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
|
// Explicit u16 definition: Qt would store it as QMetaType otherwise, which is not human-readable
|
||||||
template <>
|
template <>
|
||||||
void QtConfig::WriteBasicSetting(const Settings::Setting<u16>& setting) {
|
void QtConfig::WriteBasicSetting(const Settings::Setting<u16>& setting) {
|
||||||
const QString name = QString::fromStdString(setting.GetLabel());
|
const QString name = QString::fromStdString(setting.GetLabel());
|
||||||
const u16& value = setting.GetValue();
|
const u16& value = setting.GetValue();
|
||||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
if (global)
|
||||||
|
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||||
qt_config->setValue(name, static_cast<u32>(value));
|
qt_config->setValue(name, static_cast<u32>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,7 +240,8 @@ template <typename Type, bool ranged>
|
||||||
void QtConfig::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) {
|
void QtConfig::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) {
|
||||||
const QString name = QString::fromStdString(setting.GetLabel());
|
const QString name = QString::fromStdString(setting.GetLabel());
|
||||||
const Type value = setting.GetValue();
|
const Type value = setting.GetValue();
|
||||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
if (global)
|
||||||
|
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||||
if constexpr (std::is_enum_v<Type>) {
|
if constexpr (std::is_enum_v<Type>) {
|
||||||
qt_config->setValue(name, static_cast<std::underlying_type_t<Type>>(value));
|
qt_config->setValue(name, static_cast<std::underlying_type_t<Type>>(value));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -215,44 +252,11 @@ void QtConfig::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting)
|
||||||
template <typename Type, bool ranged>
|
template <typename Type, bool ranged>
|
||||||
void QtConfig::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) {
|
void QtConfig::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) {
|
||||||
const QString name = QString::fromStdString(setting.GetLabel());
|
const QString name = QString::fromStdString(setting.GetLabel());
|
||||||
const Type& value = setting.GetValue(global);
|
|
||||||
if (!global) {
|
if (!global) {
|
||||||
qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
|
qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
|
||||||
}
|
}
|
||||||
if (global || !setting.UsingGlobal()) {
|
if (global || !setting.UsingGlobal()) {
|
||||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
WriteBasicSetting(setting);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,7 +530,7 @@ void QtConfig::ReadLayoutValues() {
|
||||||
ReadGlobalSetting(Settings::values.large_screen_proportion);
|
ReadGlobalSetting(Settings::values.large_screen_proportion);
|
||||||
ReadGlobalSetting(Settings::values.screen_gap);
|
ReadGlobalSetting(Settings::values.screen_gap);
|
||||||
ReadGlobalSetting(Settings::values.small_screen_position);
|
ReadGlobalSetting(Settings::values.small_screen_position);
|
||||||
|
ReadGlobalSetting(Settings::values.layouts_to_cycle);
|
||||||
if (global) {
|
if (global) {
|
||||||
ReadBasicSetting(Settings::values.mono_render_option);
|
ReadBasicSetting(Settings::values.mono_render_option);
|
||||||
ReadBasicSetting(Settings::values.custom_top_x);
|
ReadBasicSetting(Settings::values.custom_top_x);
|
||||||
|
|
@ -1091,6 +1095,7 @@ void QtConfig::SaveLayoutValues() {
|
||||||
WriteGlobalSetting(Settings::values.large_screen_proportion);
|
WriteGlobalSetting(Settings::values.large_screen_proportion);
|
||||||
WriteGlobalSetting(Settings::values.screen_gap);
|
WriteGlobalSetting(Settings::values.screen_gap);
|
||||||
WriteGlobalSetting(Settings::values.small_screen_position);
|
WriteGlobalSetting(Settings::values.small_screen_position);
|
||||||
|
WriteGlobalSetting(Settings::values.layouts_to_cycle);
|
||||||
if (global) {
|
if (global) {
|
||||||
WriteBasicSetting(Settings::values.mono_render_option);
|
WriteBasicSetting(Settings::values.mono_render_option);
|
||||||
WriteBasicSetting(Settings::values.custom_top_x);
|
WriteBasicSetting(Settings::values.custom_top_x);
|
||||||
|
|
@ -1418,7 +1423,8 @@ void QtConfig::WriteSetting(const QString& name, const QVariant& value) {
|
||||||
|
|
||||||
void QtConfig::WriteSetting(const QString& name, const QVariant& value,
|
void QtConfig::WriteSetting(const QString& name, const QVariant& value,
|
||||||
const QVariant& default_value) {
|
const QVariant& default_value) {
|
||||||
qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
|
if (global)
|
||||||
|
qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
|
||||||
qt_config->setValue(name, value);
|
qt_config->setValue(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,10 @@ private:
|
||||||
template <typename Type, bool ranged>
|
template <typename Type, bool ranged>
|
||||||
void ReadBasicSetting(Settings::Setting<Type, ranged>& setting);
|
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.
|
/** Sets a value from the setting in the qt_config using the setting's label and default value.
|
||||||
*
|
*
|
||||||
* @param The setting
|
* @param The setting
|
||||||
|
|
@ -127,6 +131,9 @@ private:
|
||||||
template <typename Type, bool ranged>
|
template <typename Type, bool ranged>
|
||||||
void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting);
|
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;
|
ConfigType type;
|
||||||
std::unique_ptr<QSettings> qt_config;
|
std::unique_ptr<QSettings> qt_config;
|
||||||
std::string qt_config_loc;
|
std::string qt_config_loc;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include "citra_qt/configuration/configuration_shared.h"
|
#include "citra_qt/configuration/configuration_shared.h"
|
||||||
#include "citra_qt/configuration/configure_layout.h"
|
#include "citra_qt/configuration/configure_layout.h"
|
||||||
|
#include "citra_qt/configuration/configure_layout_cycle.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "ui_configure_layout.h"
|
#include "ui_configure_layout.h"
|
||||||
#ifdef ENABLE_OPENGL
|
#ifdef ENABLE_OPENGL
|
||||||
|
|
@ -111,6 +112,13 @@ ConfigureLayout::ConfigureLayout(QWidget* parent)
|
||||||
ui->bg_button->setIcon(color_icon);
|
ui->bg_button->setIcon(color_icon);
|
||||||
ui->bg_button->setEnabled(true);
|
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;
|
ConfigureLayout::~ConfigureLayout() = default;
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>705</width>
|
<width>659</width>
|
||||||
<height>656</height>
|
<height>662</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
|
|
@ -51,8 +51,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>688</width>
|
<width>646</width>
|
||||||
<height>799</height>
|
<height>824</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
|
@ -130,18 +130,39 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="toggle_swap_screen">
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Swap screens</string>
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
</property>
|
<item>
|
||||||
</widget>
|
<widget class="QCheckBox" name="toggle_upright_screen">
|
||||||
</item>
|
<property name="text">
|
||||||
<item>
|
<string>Rotate screens upright</string>
|
||||||
<widget class="QCheckBox" name="toggle_upright_screen">
|
</property>
|
||||||
<property name="text">
|
</widget>
|
||||||
<string>Rotate screens upright</string>
|
</item>
|
||||||
</property>
|
<item>
|
||||||
</widget>
|
<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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="widget" native="true">
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
|
@ -356,7 +377,7 @@
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QSpinBox" name="custom_top_x">
|
<widget class="QSpinBox" name="custom_top_x">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -376,7 +397,7 @@
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QSpinBox" name="custom_top_y">
|
<widget class="QSpinBox" name="custom_top_y">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -396,7 +417,7 @@
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QSpinBox" name="custom_top_width">
|
<widget class="QSpinBox" name="custom_top_width">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -416,7 +437,7 @@
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="custom_top_height">
|
<widget class="QSpinBox" name="custom_top_height">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -440,6 +461,12 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Bottom Screen</string>
|
<string>Bottom Screen</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_1">
|
<layout class="QGridLayout" name="gridLayout_1">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="lb_bottom_x">
|
<widget class="QLabel" name="lb_bottom_x">
|
||||||
|
|
@ -451,7 +478,7 @@
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QSpinBox" name="custom_bottom_x">
|
<widget class="QSpinBox" name="custom_bottom_x">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -471,7 +498,7 @@
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QSpinBox" name="custom_bottom_y">
|
<widget class="QSpinBox" name="custom_bottom_y">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -491,7 +518,7 @@
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QSpinBox" name="custom_bottom_width">
|
<widget class="QSpinBox" name="custom_bottom_width">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -511,7 +538,7 @@
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="custom_bottom_height">
|
<widget class="QSpinBox" name="custom_bottom_height">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -538,7 +565,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="custom_second_layer_opacity">
|
<widget class="QSpinBox" name="custom_second_layer_opacity">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::PlusMinus</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>10</number>
|
<number>10</number>
|
||||||
|
|
@ -583,7 +610,7 @@
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QSpinBox" name="screen_top_leftright_padding">
|
<widget class="QSpinBox" name="screen_top_leftright_padding">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -610,7 +637,7 @@
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QSpinBox" name="screen_top_topbottom_padding">
|
<widget class="QSpinBox" name="screen_top_topbottom_padding">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -659,7 +686,7 @@
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QSpinBox" name="screen_bottom_leftright_padding">
|
<widget class="QSpinBox" name="screen_bottom_leftright_padding">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -672,7 +699,7 @@
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QSpinBox" name="screen_bottom_topbottom_padding">
|
<widget class="QSpinBox" name="screen_bottom_topbottom_padding">
|
||||||
<property name="buttonSymbols">
|
<property name="buttonSymbols">
|
||||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>px</string>
|
<string>px</string>
|
||||||
|
|
@ -717,9 +744,6 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Orientation::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<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_ScreenGap", values.screen_gap.GetValue());
|
||||||
log_setting("Layout_LargeScreenProportion", values.large_screen_proportion.GetValue());
|
log_setting("Layout_LargeScreenProportion", values.large_screen_proportion.GetValue());
|
||||||
log_setting("Layout_SmallScreenPosition", values.small_screen_position.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_DumpTextures", values.dump_textures.GetValue());
|
||||||
log_setting("Utility_CustomTextures", values.custom_textures.GetValue());
|
log_setting("Utility_CustomTextures", values.custom_textures.GetValue());
|
||||||
log_setting("Utility_PreloadTextures", values.preload_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.layout_option.SetGlobal(true);
|
||||||
values.portrait_layout_option.SetGlobal(true);
|
values.portrait_layout_option.SetGlobal(true);
|
||||||
values.secondary_display_layout.SetGlobal(true);
|
values.secondary_display_layout.SetGlobal(true);
|
||||||
|
values.layouts_to_cycle.SetGlobal(true);
|
||||||
values.swap_screen.SetGlobal(true);
|
values.swap_screen.SetGlobal(true);
|
||||||
values.upright_screen.SetGlobal(true);
|
values.upright_screen.SetGlobal(true);
|
||||||
values.large_screen_proportion.SetGlobal(true);
|
values.large_screen_proportion.SetGlobal(true);
|
||||||
|
|
|
||||||
|
|
@ -522,6 +522,14 @@ struct Values {
|
||||||
SwitchableSetting<bool> upright_screen{false, "upright_screen"};
|
SwitchableSetting<bool> upright_screen{false, "upright_screen"};
|
||||||
SwitchableSetting<SecondaryDisplayLayout> secondary_display_layout{SecondaryDisplayLayout::None,
|
SwitchableSetting<SecondaryDisplayLayout> secondary_display_layout{SecondaryDisplayLayout::None,
|
||||||
"secondary_display_layout"};
|
"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,
|
SwitchableSetting<float, true> large_screen_proportion{4.f, 1.f, 16.f,
|
||||||
"large_screen_proportion"};
|
"large_screen_proportion"};
|
||||||
SwitchableSetting<int> screen_gap{0, "screen_gap"};
|
SwitchableSetting<int> screen_gap{0, "screen_gap"};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue