2021-12-13 12:12:54 +00:00
/* PCSX2 - PS2 Emulator for PCs
* Copyright ( C ) 2002 - 2022 PCSX2 Dev Team
*
* PCSX2 is free software : you can redistribute it and / or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found -
* ation , either version 3 of the License , or ( at your option ) any later version .
*
* PCSX2 is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along with PCSX2 .
* If not , see < http : //www.gnu.org/licenses/>.
*/
# pragma once
2022-03-04 08:02:24 +00:00
2021-12-13 12:12:54 +00:00
# include <optional>
# include <type_traits>
2022-03-04 08:02:24 +00:00
# include <QtCore/QtCore>
2021-12-13 12:12:54 +00:00
# include <QtGui/QAction>
2023-01-01 12:46:07 +00:00
# include <QtGui/QFont>
2022-06-14 10:05:11 +00:00
# include <QtWidgets/QAbstractButton>
2021-12-13 12:12:54 +00:00
# include <QtWidgets/QCheckBox>
# include <QtWidgets/QComboBox>
# include <QtWidgets/QDoubleSpinBox>
2022-06-14 10:05:11 +00:00
# include <QtWidgets/QFileDialog>
2023-01-01 12:46:07 +00:00
# include <QtWidgets/QLabel>
2021-12-13 12:12:54 +00:00
# include <QtWidgets/QLineEdit>
2022-08-05 12:44:01 +00:00
# include <QtWidgets/QMenu>
2021-12-13 12:12:54 +00:00
# include <QtWidgets/QSlider>
# include <QtWidgets/QSpinBox>
2022-06-14 10:05:11 +00:00
# include "common/Path.h"
# include "pcsx2/Config.h"
2023-05-13 04:30:41 +00:00
# include "pcsx2/Host.h"
2022-05-24 12:37:44 +00:00
2021-12-13 12:12:54 +00:00
# include "QtHost.h"
2022-06-14 10:05:11 +00:00
# include "QtUtils.h"
2022-02-22 18:52:52 +00:00
# include "Settings/SettingsDialog.h"
2021-12-13 12:12:54 +00:00
namespace SettingWidgetBinder
{
2022-08-05 12:44:01 +00:00
static constexpr const char * NULLABLE_PROPERTY = " SettingWidgetBinder_isNullable " ;
static constexpr const char * IS_NULL_PROPERTY = " SettingWidgetBinder_isNull " ;
static constexpr const char * GLOBAL_VALUE_PROPERTY = " SettingWidgetBinder_globalValue " ;
2021-12-13 12:12:54 +00:00
template < typename T >
struct SettingAccessor
{
static bool getBoolValue ( const T * widget ) ;
static void setBoolValue ( T * widget , bool value ) ;
2022-02-15 14:29:18 +00:00
static void makeNullableBool ( T * widget , bool globalValue ) ;
static std : : optional < bool > getNullableBoolValue ( const T * widget ) ;
static void setNullableBoolValue ( T * widget , std : : optional < bool > value ) ;
2021-12-13 12:12:54 +00:00
static int getIntValue ( const T * widget ) ;
2022-02-15 14:29:18 +00:00
static void setIntValue ( T * widget , bool nullable , int value ) ;
static void makeNullableInt ( T * widget , int globalValue ) ;
static std : : optional < int > getNullableIntValue ( const T * widget ) ;
static void setNullableIntValue ( T * widget , std : : optional < int > value ) ;
2021-12-13 12:12:54 +00:00
static int getFloatValue ( const T * widget ) ;
static void setFloatValue ( T * widget , int value ) ;
2022-02-15 14:29:18 +00:00
static void makeNullableFloat ( T * widget , float globalValue ) ;
static std : : optional < float > getNullableFloatValue ( const T * widget ) ;
static void setNullableFloatValue ( T * widget , std : : optional < float > value ) ;
2021-12-13 12:12:54 +00:00
static QString getStringValue ( const T * widget ) ;
static void setStringValue ( T * widget , const QString & value ) ;
2022-02-15 14:29:18 +00:00
static void makeNullableString ( T * widget , const QString & globalValue ) ;
static std : : optional < QString > getNullableStringValue ( const T * widget ) ;
static void setNullableFloatValue ( T * widget , std : : optional < QString > value ) ;
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( T * widget , F func ) ;
} ;
template < >
struct SettingAccessor < QLineEdit >
{
static bool getBoolValue ( const QLineEdit * widget ) { return widget - > text ( ) . toInt ( ) ! = 0 ; }
2022-02-15 14:29:18 +00:00
static void setBoolValue ( QLineEdit * widget , bool value ) { widget - > setText ( value ? QStringLiteral ( " 1 " ) : QStringLiteral ( " 0 " ) ) ; }
static void makeNullableBool ( QLineEdit * widget , bool globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < bool > getNullableBoolValue ( const QLineEdit * widget ) { return getBoolValue ( widget ) ; }
static void setNullableBoolValue ( QLineEdit * widget , std : : optional < bool > value ) { setBoolValue ( widget , value . value_or ( false ) ) ; }
2021-12-13 12:12:54 +00:00
static int getIntValue ( const QLineEdit * widget ) { return widget - > text ( ) . toInt ( ) ; }
static void setIntValue ( QLineEdit * widget , int value ) { widget - > setText ( QString : : number ( value ) ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableInt ( QLineEdit * widget , int globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < int > getNullableIntValue ( const QLineEdit * widget ) { return getIntValue ( widget ) ; }
static void setNullableIntValue ( QLineEdit * widget , std : : optional < int > value ) { setIntValue ( widget , value . value_or ( 0 ) ) ; }
2021-12-13 12:12:54 +00:00
static float getFloatValue ( const QLineEdit * widget ) { return widget - > text ( ) . toFloat ( ) ; }
static void setFloatValue ( QLineEdit * widget , float value ) { widget - > setText ( QString : : number ( value ) ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableFloat ( QLineEdit * widget , float globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < float > getNullableFloatValue ( const QLineEdit * widget ) { return getFloatValue ( widget ) ; }
static void setNullableFloatValue ( QLineEdit * widget , std : : optional < float > value ) { setFloatValue ( widget , value . value_or ( 0.0f ) ) ; }
2021-12-13 12:12:54 +00:00
static QString getStringValue ( const QLineEdit * widget ) { return widget - > text ( ) ; }
static void setStringValue ( QLineEdit * widget , const QString & value ) { widget - > setText ( value ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableString ( QLineEdit * widget , const QString & globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < QString > getNullableStringValue ( const QLineEdit * widget ) { return getStringValue ( widget ) ; }
2023-01-01 12:46:07 +00:00
static void setNullableStringValue ( QLineEdit * widget , std : : optional < QString > value )
{
setStringValue ( widget , value . value_or ( QString ( ) ) ) ;
}
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( QLineEdit * widget , F func )
{
widget - > connect ( widget , & QLineEdit : : textChanged , func ) ;
}
} ;
template < >
struct SettingAccessor < QComboBox >
{
2022-02-15 14:29:18 +00:00
static bool isNullValue ( const QComboBox * widget ) { return ( widget - > currentIndex ( ) = = 0 ) ; }
2021-12-13 12:12:54 +00:00
static bool getBoolValue ( const QComboBox * widget ) { return widget - > currentIndex ( ) > 0 ; }
static void setBoolValue ( QComboBox * widget , bool value ) { widget - > setCurrentIndex ( value ? 1 : 0 ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableBool ( QComboBox * widget , bool globalValue )
{
2023-03-18 21:14:55 +00:00
//: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Enabled]: the text must be translated.
2022-02-15 14:29:18 +00:00
widget - > insertItem ( 0 , globalValue ? qApp - > translate ( " SettingsDialog " , " Use Global Setting [Enabled] " ) :
2023-03-18 21:14:55 +00:00
//: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Disabled]: the text must be translated.
2023-01-01 12:46:07 +00:00
qApp - > translate ( " SettingsDialog " , " Use Global Setting [Disabled] " ) ) ;
2022-02-15 14:29:18 +00:00
}
2021-12-13 12:12:54 +00:00
static int getIntValue ( const QComboBox * widget ) { return widget - > currentIndex ( ) ; }
static void setIntValue ( QComboBox * widget , int value ) { widget - > setCurrentIndex ( value ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableInt ( QComboBox * widget , int globalValue )
{
2023-01-01 12:46:07 +00:00
widget - > insertItem (
0 , qApp - > translate ( " SettingsDialog " , " Use Global Setting [%1] " )
. arg ( ( globalValue > = 0 & & globalValue < widget - > count ( ) ) ? widget - > itemText ( globalValue ) : QString ( ) ) ) ;
2022-02-15 14:29:18 +00:00
}
static std : : optional < int > getNullableIntValue ( const QComboBox * widget )
{
2022-03-07 10:09:37 +00:00
return isNullValue ( widget ) ? std : : nullopt : std : : optional < int > ( widget - > currentIndex ( ) - 1 ) ;
2022-02-15 14:29:18 +00:00
}
static void setNullableIntValue ( QComboBox * widget , std : : optional < int > value )
{
widget - > setCurrentIndex ( value . has_value ( ) ? ( value . value ( ) + 1 ) : 0 ) ;
}
2021-12-13 12:12:54 +00:00
static float getFloatValue ( const QComboBox * widget ) { return static_cast < float > ( widget - > currentIndex ( ) ) ; }
static void setFloatValue ( QComboBox * widget , float value ) { widget - > setCurrentIndex ( static_cast < int > ( value ) ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableFloat ( QComboBox * widget , float globalValue )
{
2023-01-01 12:46:07 +00:00
widget - > insertItem ( 0 , qApp - > translate ( " SettingsDialog " , " Use Global Setting [%1] " )
. arg ( ( globalValue > = 0.0f & & static_cast < int > ( globalValue ) < widget - > count ( ) ) ?
widget - > itemText ( static_cast < int > ( globalValue ) ) :
QString ( ) ) ) ;
2022-02-15 14:29:18 +00:00
}
static std : : optional < float > getNullableFloatValue ( const QComboBox * widget )
{
return isNullValue ( widget ) ? std : : nullopt : std : : optional < float > ( static_cast < float > ( widget - > currentIndex ( ) + 1 ) ) ;
}
static void setNullableFloatValue ( QComboBox * widget , std : : optional < float > value )
{
widget - > setCurrentIndex ( value . has_value ( ) ? static_cast < int > ( value . value ( ) + 1.0f ) : 0 ) ;
}
2021-12-13 12:12:54 +00:00
static QString getStringValue ( const QComboBox * widget )
{
const QVariant currentData ( widget - > currentData ( ) ) ;
if ( currentData . metaType ( ) . id ( ) = = QMetaType : : QString )
return currentData . toString ( ) ;
return widget - > currentText ( ) ;
}
static void setStringValue ( QComboBox * widget , const QString & value )
{
const int index = widget - > findData ( value ) ;
if ( index > = 0 )
{
widget - > setCurrentIndex ( index ) ;
return ;
}
widget - > setCurrentText ( value ) ;
}
2023-01-01 12:46:07 +00:00
static void makeNullableString ( QComboBox * widget , const QString & globalValue )
{
makeNullableInt ( widget , widget - > findData ( globalValue ) ) ;
}
2022-02-15 14:29:18 +00:00
static std : : optional < QString > getNullableStringValue ( const QComboBox * widget )
{
return isNullValue ( widget ) ? std : : nullopt : std : : optional < QString > ( getStringValue ( widget ) ) ;
}
static void setNullableStringValue ( QComboBox * widget , std : : optional < QString > value )
{
2022-08-05 12:44:01 +00:00
value . has_value ( ) ? setStringValue ( widget , value . value ( ) ) : widget - > setCurrentIndex ( 0 ) ;
2022-02-15 14:29:18 +00:00
}
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( QComboBox * widget , F func )
{
widget - > connect ( widget , static_cast < void ( QComboBox : : * ) ( int ) > ( & QComboBox : : currentIndexChanged ) , func ) ;
}
} ;
template < >
struct SettingAccessor < QCheckBox >
{
static bool getBoolValue ( const QCheckBox * widget ) { return widget - > isChecked ( ) ; }
static void setBoolValue ( QCheckBox * widget , bool value ) { widget - > setChecked ( value ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableBool ( QCheckBox * widget , bool globalValue ) { widget - > setTristate ( true ) ; }
static std : : optional < bool > getNullableBoolValue ( const QCheckBox * widget )
{
return ( widget - > checkState ( ) = = Qt : : PartiallyChecked ) ? std : : nullopt : std : : optional < bool > ( widget - > isChecked ( ) ) ;
}
static void setNullableBoolValue ( QCheckBox * widget , std : : optional < bool > value )
{
widget - > setCheckState ( value . has_value ( ) ? ( value . value ( ) ? Qt : : Checked : Qt : : Unchecked ) : Qt : : PartiallyChecked ) ;
}
2021-12-13 12:12:54 +00:00
static int getIntValue ( const QCheckBox * widget ) { return widget - > isChecked ( ) ? 1 : 0 ; }
static void setIntValue ( QCheckBox * widget , int value ) { widget - > setChecked ( value ! = 0 ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableInt ( QCheckBox * widget , int globalValue ) { widget - > setTristate ( true ) ; }
static std : : optional < int > getNullableIntValue ( const QCheckBox * widget )
{
return ( widget - > checkState ( ) = = Qt : : PartiallyChecked ) ? std : : nullopt : std : : optional < int > ( widget - > isChecked ( ) ? 1 : 0 ) ;
}
static void setNullableIntValue ( QCheckBox * widget , std : : optional < int > value )
{
widget - > setCheckState ( value . has_value ( ) ? ( ( value . value ( ) ! = 0 ) ? Qt : : Checked : Qt : : Unchecked ) : Qt : : PartiallyChecked ) ;
}
2021-12-13 12:12:54 +00:00
static float getFloatValue ( const QCheckBox * widget ) { return widget - > isChecked ( ) ? 1.0f : 0.0f ; }
static void setFloatValue ( QCheckBox * widget , float value ) { widget - > setChecked ( value ! = 0.0f ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableFloat ( QCheckBox * widget , float globalValue ) { widget - > setTristate ( true ) ; }
static std : : optional < float > getNullableFloatValue ( const QCheckBox * widget )
{
return ( widget - > checkState ( ) = = Qt : : PartiallyChecked ) ? std : : nullopt : std : : optional < float > ( widget - > isChecked ( ) ? 1.0f : 0.0f ) ;
}
static void setNullableFloatValue ( QCheckBox * widget , std : : optional < float > value )
2021-12-13 12:12:54 +00:00
{
2022-02-15 14:29:18 +00:00
widget - > setCheckState ( value . has_value ( ) ? ( ( value . value ( ) ! = 0.0f ) ? Qt : : Checked : Qt : : Unchecked ) : Qt : : PartiallyChecked ) ;
2021-12-13 12:12:54 +00:00
}
2022-02-15 14:29:18 +00:00
static QString getStringValue ( const QCheckBox * widget ) { return widget - > isChecked ( ) ? QStringLiteral ( " 1 " ) : QStringLiteral ( " 0 " ) ; }
2021-12-13 12:12:54 +00:00
static void setStringValue ( QCheckBox * widget , const QString & value ) { widget - > setChecked ( value . toInt ( ) ! = 0 ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableString ( QCheckBox * widget , const QString & globalValue ) { widget - > setTristate ( true ) ; }
static std : : optional < QString > getNullableStringValue ( const QCheckBox * widget )
{
return ( widget - > checkState ( ) = = Qt : : PartiallyChecked ) ?
2022-06-14 10:05:11 +00:00
std : : nullopt :
2023-01-01 12:46:07 +00:00
std : : optional < QString > ( widget - > isChecked ( ) ? QStringLiteral ( " 1 " ) : QStringLiteral ( " 0 " ) ) ;
2022-02-15 14:29:18 +00:00
}
static void setNullableStringValue ( QCheckBox * widget , std : : optional < QString > value )
{
widget - > setCheckState ( value . has_value ( ) ? ( ( value - > toInt ( ) ! = 0 ) ? Qt : : Checked : Qt : : Unchecked ) : Qt : : PartiallyChecked ) ;
}
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( QCheckBox * widget , F func )
{
widget - > connect ( widget , & QCheckBox : : stateChanged , func ) ;
}
} ;
template < >
struct SettingAccessor < QSlider >
{
static bool getBoolValue ( const QSlider * widget ) { return widget - > value ( ) > 0 ; }
static void setBoolValue ( QSlider * widget , bool value ) { widget - > setValue ( value ? 1 : 0 ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableBool ( QSlider * widget , bool globalSetting ) { widget - > setEnabled ( false ) ; }
static std : : optional < bool > getNullableBoolValue ( const QSlider * widget ) { return getBoolValue ( widget ) ; }
static void setNullableBoolValue ( QSlider * widget , std : : optional < bool > value ) { setBoolValue ( widget , value . value_or ( false ) ) ; }
2021-12-13 12:12:54 +00:00
static int getIntValue ( const QSlider * widget ) { return widget - > value ( ) ; }
static void setIntValue ( QSlider * widget , int value ) { widget - > setValue ( value ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableInt ( QSlider * widget , int globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < int > getNullableIntValue ( const QSlider * widget ) { return getIntValue ( widget ) ; }
static void setNullableIntValue ( QSlider * widget , std : : optional < int > value ) { setIntValue ( widget , value . value_or ( 0 ) ) ; }
2021-12-13 12:12:54 +00:00
static float getFloatValue ( const QSlider * widget ) { return static_cast < float > ( widget - > value ( ) ) ; }
static void setFloatValue ( QSlider * widget , float value ) { widget - > setValue ( static_cast < int > ( value ) ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableFloat ( QSlider * widget , float globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < float > getNullableFloatValue ( const QSlider * widget ) { return getFloatValue ( widget ) ; }
static void setNullableFloatValue ( QSlider * widget , std : : optional < float > value ) { setFloatValue ( widget , value . value_or ( 0.0f ) ) ; }
2021-12-13 12:12:54 +00:00
static QString getStringValue ( const QSlider * widget ) { return QString : : number ( widget - > value ( ) ) ; }
static void setStringValue ( QSlider * widget , const QString & value ) { widget - > setValue ( value . toInt ( ) ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableString ( QSlider * widget , const QString & globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < QString > getNullableStringValue ( const QSlider * widget ) { return getStringValue ( widget ) ; }
2023-01-01 12:46:07 +00:00
static void setNullableStringValue ( QSlider * widget , std : : optional < QString > value )
{
setStringValue ( widget , value . value_or ( QString ( ) ) ) ;
}
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( QSlider * widget , F func )
{
widget - > connect ( widget , & QSlider : : valueChanged , func ) ;
}
} ;
template < >
struct SettingAccessor < QSpinBox >
{
2022-08-05 12:44:01 +00:00
static bool isNullable ( const QSpinBox * widget ) { return widget - > property ( NULLABLE_PROPERTY ) . toBool ( ) ; }
static void updateNullState ( QSpinBox * widget , bool isNull )
{
widget - > setPrefix ( isNull ? qApp - > translate ( " SettingWidgetBinder " , " Default: " ) : QString ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static bool getBoolValue ( const QSpinBox * widget ) { return widget - > value ( ) > 0 ; }
static void setBoolValue ( QSpinBox * widget , bool value ) { widget - > setValue ( value ? 1 : 0 ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableBool ( QSpinBox * widget , bool globalSetting )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalSetting ) ) ;
}
static std : : optional < bool > getNullableBoolValue ( const QSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getBoolValue ( widget ) ;
}
static void setNullableBoolValue ( QSpinBox * widget , std : : optional < bool > value )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setBoolValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toBool ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static int getIntValue ( const QSpinBox * widget ) { return widget - > value ( ) ; }
static void setIntValue ( QSpinBox * widget , int value ) { widget - > setValue ( value ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableInt ( QSpinBox * widget , int globalValue )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalValue ) ) ;
}
static std : : optional < int > getNullableIntValue ( const QSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getIntValue ( widget ) ;
}
static void setNullableIntValue ( QSpinBox * widget , std : : optional < int > value )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setIntValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toInt ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static float getFloatValue ( const QSpinBox * widget ) { return static_cast < float > ( widget - > value ( ) ) ; }
static void setFloatValue ( QSpinBox * widget , float value ) { widget - > setValue ( static_cast < int > ( value ) ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableFloat ( QSpinBox * widget , float globalValue )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalValue ) ) ;
}
static std : : optional < float > getNullableFloatValue ( const QSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getFloatValue ( widget ) ;
}
static void setNullableFloatValue ( QSpinBox * widget , std : : optional < float > value )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setFloatValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toFloat ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static QString getStringValue ( const QSpinBox * widget ) { return QString : : number ( widget - > value ( ) ) ; }
static void setStringValue ( QSpinBox * widget , const QString & value ) { widget - > setValue ( value . toInt ( ) ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableString ( QSpinBox * widget , const QString & globalValue )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalValue ) ) ;
}
static std : : optional < QString > getNullableStringValue ( const QSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getStringValue ( widget ) ;
}
static void setNullableStringValue ( QSpinBox * widget , std : : optional < QString > value )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setStringValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toString ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
}
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( QSpinBox * widget , F func )
{
2022-08-05 12:44:01 +00:00
if ( ! isNullable ( widget ) )
{
widget - > connect ( widget , QOverload < int > : : of ( & QSpinBox : : valueChanged ) , func ) ;
}
else
{
widget - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
widget - > connect ( widget , & QSpinBox : : customContextMenuRequested , widget , [ widget , func ] ( const QPoint & pt ) {
QMenu menu ( widget ) ;
widget - > connect ( menu . addAction ( qApp - > translate ( " SettingWidgetBinder " , " Reset " ) ) , & QAction : : triggered , widget ,
[ widget , func = std : : move ( func ) ] ( ) {
const bool old = widget - > blockSignals ( true ) ;
setNullableIntValue ( widget , std : : nullopt ) ;
widget - > blockSignals ( old ) ;
updateNullState ( widget , true ) ;
func ( ) ;
} ) ;
menu . exec ( widget - > mapToGlobal ( pt ) ) ;
} ) ;
widget - > connect ( widget , & QSpinBox : : valueChanged , widget , [ widget , func = std : : move ( func ) ] ( ) {
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( false ) ) ;
updateNullState ( widget , false ) ;
}
func ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
} ;
template < >
struct SettingAccessor < QDoubleSpinBox >
{
2022-08-05 12:44:01 +00:00
static bool isNullable ( const QDoubleSpinBox * widget ) { return widget - > property ( NULLABLE_PROPERTY ) . toBool ( ) ; }
static void updateNullState ( QDoubleSpinBox * widget , bool isNull )
{
widget - > setPrefix ( isNull ? qApp - > translate ( " SettingWidgetBinder " , " Default: " ) : QString ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static bool getBoolValue ( const QDoubleSpinBox * widget ) { return widget - > value ( ) > 0.0 ; }
static void setBoolValue ( QDoubleSpinBox * widget , bool value ) { widget - > setValue ( value ? 1.0 : 0.0 ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableBool ( QDoubleSpinBox * widget , bool globalSetting )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalSetting ) ) ;
}
static std : : optional < bool > getNullableBoolValue ( const QDoubleSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getBoolValue ( widget ) ;
}
static void setNullableBoolValue ( QDoubleSpinBox * widget , std : : optional < bool > value )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setBoolValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toBool ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static int getIntValue ( const QDoubleSpinBox * widget ) { return static_cast < int > ( widget - > value ( ) ) ; }
static void setIntValue ( QDoubleSpinBox * widget , int value ) { widget - > setValue ( static_cast < double > ( value ) ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableInt ( QDoubleSpinBox * widget , int globalValue )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalValue ) ) ;
}
static std : : optional < int > getNullableIntValue ( const QDoubleSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getIntValue ( widget ) ;
}
static void setNullableIntValue ( QDoubleSpinBox * widget , std : : optional < int > value )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setIntValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toInt ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static float getFloatValue ( const QDoubleSpinBox * widget ) { return static_cast < float > ( widget - > value ( ) ) ; }
static void setFloatValue ( QDoubleSpinBox * widget , float value ) { widget - > setValue ( static_cast < double > ( value ) ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableFloat ( QDoubleSpinBox * widget , float globalValue )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalValue ) ) ;
}
static std : : optional < float > getNullableFloatValue ( const QDoubleSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getFloatValue ( widget ) ;
}
static void setNullableFloatValue ( QDoubleSpinBox * widget , std : : optional < float > value )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setFloatValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toFloat ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
}
2021-12-13 12:12:54 +00:00
static QString getStringValue ( const QDoubleSpinBox * widget ) { return QString : : number ( widget - > value ( ) ) ; }
static void setStringValue ( QDoubleSpinBox * widget , const QString & value ) { widget - > setValue ( value . toDouble ( ) ) ; }
2022-08-05 12:44:01 +00:00
static void makeNullableString ( QDoubleSpinBox * widget , const QString & globalValue )
{
widget - > setProperty ( NULLABLE_PROPERTY , QVariant ( true ) ) ;
widget - > setProperty ( GLOBAL_VALUE_PROPERTY , QVariant ( globalValue ) ) ;
}
static std : : optional < QString > getNullableStringValue ( const QDoubleSpinBox * widget )
{
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
return std : : nullopt ;
return getStringValue ( widget ) ;
}
2022-02-15 14:29:18 +00:00
static void setNullableStringValue ( QDoubleSpinBox * widget , std : : optional < QString > value )
{
2022-08-05 12:44:01 +00:00
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( ! value . has_value ( ) ) ) ;
setStringValue ( widget , value . has_value ( ) ? value . value ( ) : widget - > property ( GLOBAL_VALUE_PROPERTY ) . toString ( ) ) ;
updateNullState ( widget , ! value . has_value ( ) ) ;
2022-02-15 14:29:18 +00:00
}
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( QDoubleSpinBox * widget , F func )
{
2022-08-05 12:44:01 +00:00
if ( ! isNullable ( widget ) )
{
widget - > connect ( widget , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , func ) ;
}
else
{
widget - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
widget - > connect ( widget , & QDoubleSpinBox : : customContextMenuRequested , widget , [ widget , func ] ( const QPoint & pt ) {
QMenu menu ( widget ) ;
widget - > connect ( menu . addAction ( qApp - > translate ( " SettingWidgetBinder " , " Reset " ) ) , & QAction : : triggered , widget ,
[ widget , func = std : : move ( func ) ] ( ) {
const bool old = widget - > blockSignals ( true ) ;
setNullableFloatValue ( widget , std : : nullopt ) ;
widget - > blockSignals ( old ) ;
updateNullState ( widget , true ) ;
func ( ) ;
} ) ;
menu . exec ( widget - > mapToGlobal ( pt ) ) ;
} ) ;
widget - > connect ( widget , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , widget , [ widget , func = std : : move ( func ) ] ( ) {
if ( widget - > property ( IS_NULL_PROPERTY ) . toBool ( ) )
{
widget - > setProperty ( IS_NULL_PROPERTY , QVariant ( false ) ) ;
updateNullState ( widget , false ) ;
}
func ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
} ;
template < >
struct SettingAccessor < QAction >
{
static bool getBoolValue ( const QAction * widget ) { return widget - > isChecked ( ) ; }
static void setBoolValue ( QAction * widget , bool value ) { widget - > setChecked ( value ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableBool ( QAction * widget , bool globalSetting ) { widget - > setEnabled ( false ) ; }
static std : : optional < bool > getNullableBoolValue ( const QAction * widget ) { return getBoolValue ( widget ) ; }
static void setNullableBoolValue ( QAction * widget , std : : optional < bool > value ) { setBoolValue ( widget , value . value_or ( false ) ) ; }
2021-12-13 12:12:54 +00:00
static int getIntValue ( const QAction * widget ) { return widget - > isChecked ( ) ? 1 : 0 ; }
static void setIntValue ( QAction * widget , int value ) { widget - > setChecked ( value ! = 0 ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableInt ( QAction * widget , int globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < int > getNullableIntValue ( const QAction * widget ) { return getIntValue ( widget ) ; }
static void setNullableIntValue ( QAction * widget , std : : optional < int > value ) { setIntValue ( widget , value . value_or ( 0 ) ) ; }
2021-12-13 12:12:54 +00:00
static float getFloatValue ( const QAction * widget ) { return widget - > isChecked ( ) ? 1.0f : 0.0f ; }
static void setFloatValue ( QAction * widget , float value ) { widget - > setChecked ( value ! = 0.0f ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableFloat ( QAction * widget , float globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < float > getNullableFloatValue ( const QAction * widget ) { return getFloatValue ( widget ) ; }
static void setNullableFloatValue ( QAction * widget , std : : optional < float > value ) { setFloatValue ( widget , value . value_or ( 0.0f ) ) ; }
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
static QString getStringValue ( const QAction * widget ) { return widget - > isChecked ( ) ? QStringLiteral ( " 1 " ) : QStringLiteral ( " 0 " ) ; }
2021-12-13 12:12:54 +00:00
static void setStringValue ( QAction * widget , const QString & value ) { widget - > setChecked ( value . toInt ( ) ! = 0 ) ; }
2022-02-15 14:29:18 +00:00
static void makeNullableString ( QAction * widget , const QString & globalValue ) { widget - > setEnabled ( false ) ; }
static std : : optional < QString > getNullableStringValue ( const QAction * widget ) { return getStringValue ( widget ) ; }
2023-01-01 12:46:07 +00:00
static void setNullableStringValue ( QAction * widget , std : : optional < QString > value )
{
setStringValue ( widget , value . value_or ( QString ( ) ) ) ;
}
2021-12-13 12:12:54 +00:00
template < typename F >
static void connectValueChanged ( QAction * widget , F func )
{
widget - > connect ( widget , & QAction : : toggled , func ) ;
}
} ;
/// Binds a widget's value to a setting, updating it when the value changes.
template < typename WidgetType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToBoolSetting (
2023-01-01 12:46:07 +00:00
SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key , bool default_value )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
2022-05-24 12:37:44 +00:00
const bool value = Host : : GetBaseBoolSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value ) ;
2022-02-15 14:29:18 +00:00
if ( sif )
{
Accessor : : makeNullableBool ( widget , value ) ;
bool sif_value ;
if ( sif - > GetBoolValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
Accessor : : setNullableBoolValue ( widget , sif_value ) ;
else
Accessor : : setNullableBoolValue ( widget , std : : nullopt ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ sif , widget , section = std : : move ( section ) , key = std : : move ( key ) ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < bool > new_value = Accessor : : getNullableBoolValue ( widget ) ; new_value . has_value ( ) )
sif - > SetBoolValue ( section . c_str ( ) , key . c_str ( ) , new_value . value ( ) ) ;
else
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
else
{
Accessor : : setBoolValue ( widget , value ) ;
2021-12-13 12:12:54 +00:00
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) ] ( ) {
2022-02-15 14:29:18 +00:00
const bool new_value = Accessor : : getBoolValue ( widget ) ;
2022-09-07 07:44:10 +00:00
Host : : SetBaseBoolSettingValue ( section . c_str ( ) , key . c_str ( ) , new_value ) ;
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
template < typename WidgetType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToIntSetting (
2022-02-15 14:29:18 +00:00
SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key , int default_value , int option_offset = 0 )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
2022-05-24 12:37:44 +00:00
const s32 value = Host : : GetBaseIntSettingValue ( section . c_str ( ) , key . c_str ( ) , static_cast < s32 > ( default_value ) ) - option_offset ;
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
if ( sif )
{
Accessor : : makeNullableInt ( widget , value ) ;
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
int sif_value ;
if ( sif - > GetIntValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
2022-03-15 20:31:52 +00:00
Accessor : : setNullableIntValue ( widget , sif_value - option_offset ) ;
2022-02-15 14:29:18 +00:00
else
Accessor : : setNullableIntValue ( widget , std : : nullopt ) ;
2022-03-07 10:09:37 +00:00
Accessor : : connectValueChanged ( widget , [ sif , widget , section = std : : move ( section ) , key = std : : move ( key ) , option_offset ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < int > new_value = Accessor : : getNullableIntValue ( widget ) ; new_value . has_value ( ) )
2022-03-07 10:09:37 +00:00
sif - > SetIntValue ( section . c_str ( ) , key . c_str ( ) , new_value . value ( ) + option_offset ) ;
2022-02-15 14:29:18 +00:00
else
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
else
{
Accessor : : setIntValue ( widget , static_cast < int > ( value ) ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) , option_offset ] ( ) {
2022-02-15 14:29:18 +00:00
const int new_value = Accessor : : getIntValue ( widget ) ;
2022-09-07 07:44:10 +00:00
Host : : SetBaseIntSettingValue ( section . c_str ( ) , key . c_str ( ) , new_value + option_offset ) ;
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
template < typename WidgetType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToFloatSetting (
2023-01-01 12:46:07 +00:00
SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key , float default_value )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
2022-05-24 12:37:44 +00:00
const float value = Host : : GetBaseFloatSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value ) ;
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
if ( sif )
{
Accessor : : makeNullableFloat ( widget , value ) ;
float sif_value ;
if ( sif - > GetFloatValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
Accessor : : setNullableFloatValue ( widget , sif_value ) ;
else
Accessor : : setNullableFloatValue ( widget , std : : nullopt ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ sif , widget , section = std : : move ( section ) , key = std : : move ( key ) ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < float > new_value = Accessor : : getNullableFloatValue ( widget ) ; new_value . has_value ( ) )
sif - > SetFloatValue ( section . c_str ( ) , key . c_str ( ) , new_value . value ( ) ) ;
else
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
else
{
Accessor : : setFloatValue ( widget , value ) ;
2021-12-13 12:12:54 +00:00
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) ] ( ) {
2022-02-15 14:29:18 +00:00
const float new_value = Accessor : : getFloatValue ( widget ) ;
2022-09-07 07:44:10 +00:00
Host : : SetBaseFloatSettingValue ( section . c_str ( ) , key . c_str ( ) , new_value ) ;
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
template < typename WidgetType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToNormalizedSetting (
2022-02-15 14:29:18 +00:00
SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key , float range , float default_value )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
2022-05-24 12:37:44 +00:00
const float value = Host : : GetBaseFloatSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value ) ;
2022-02-15 14:29:18 +00:00
if ( sif )
{
Accessor : : makeNullableInt ( widget , static_cast < int > ( value * range ) ) ;
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
float sif_value ;
if ( sif - > GetFloatValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
Accessor : : setNullableIntValue ( widget , static_cast < int > ( sif_value * range ) ) ;
else
Accessor : : setNullableIntValue ( widget , std : : nullopt ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ sif , widget , section = std : : move ( section ) , key = std : : move ( key ) , range ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < int > new_value = Accessor : : getNullableIntValue ( widget ) ; new_value . has_value ( ) )
sif - > SetFloatValue ( section . c_str ( ) , key . c_str ( ) , static_cast < float > ( new_value . value ( ) ) / range ) ;
else
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
else
{
Accessor : : setIntValue ( widget , static_cast < int > ( value * range ) ) ;
2021-12-13 12:12:54 +00:00
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) , range ] ( ) {
2022-02-15 14:29:18 +00:00
const float new_value = ( static_cast < float > ( Accessor : : getIntValue ( widget ) ) / range ) ;
2022-09-07 07:44:10 +00:00
Host : : SetBaseFloatSettingValue ( section . c_str ( ) , key . c_str ( ) , new_value ) ;
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
template < typename WidgetType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToStringSetting (
2022-02-15 14:29:18 +00:00
SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key , std : : string default_value = std : : string ( ) )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
2022-05-24 12:37:44 +00:00
const QString value ( QString : : fromStdString ( Host : : GetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value . c_str ( ) ) ) ) ;
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
if ( sif )
{
Accessor : : makeNullableString ( widget , value ) ;
2021-12-13 12:12:54 +00:00
2022-02-15 14:29:18 +00:00
std : : string sif_value ;
if ( sif - > GetStringValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
Accessor : : setNullableStringValue ( widget , QString : : fromStdString ( sif_value ) ) ;
2021-12-13 12:12:54 +00:00
else
2022-02-15 14:29:18 +00:00
Accessor : : setNullableStringValue ( widget , std : : nullopt ) ;
2021-12-13 12:12:54 +00:00
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , sif , section = std : : move ( section ) , key = std : : move ( key ) ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < QString > new_value = Accessor : : getNullableStringValue ( widget ) ; new_value . has_value ( ) )
sif - > SetStringValue ( section . c_str ( ) , key . c_str ( ) , new_value - > toUtf8 ( ) . constData ( ) ) ;
else
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
else
{
Accessor : : setStringValue ( widget , value ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) ] ( ) {
2022-02-15 14:29:18 +00:00
const QString new_value = Accessor : : getStringValue ( widget ) ;
if ( ! new_value . isEmpty ( ) )
2022-09-07 07:44:10 +00:00
Host : : SetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , new_value . toUtf8 ( ) . constData ( ) ) ;
2022-02-15 14:29:18 +00:00
else
2022-09-07 07:44:10 +00:00
Host : : RemoveBaseSettingValue ( section . c_str ( ) , key . c_str ( ) ) ;
2022-02-15 14:29:18 +00:00
2022-09-07 07:44:10 +00:00
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
template < typename WidgetType , typename DataType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToEnumSetting ( SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key ,
2023-01-01 12:46:07 +00:00
std : : optional < DataType > ( * from_string_function ) ( const char * str ) , const char * ( * to_string_function ) ( DataType value ) ,
DataType default_value )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
using UnderlyingType = std : : underlying_type_t < DataType > ;
2022-05-24 12:37:44 +00:00
const std : : string value ( Host : : GetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , to_string_function ( default_value ) ) ) ;
2022-02-15 14:29:18 +00:00
const std : : optional < DataType > typed_value = from_string_function ( value . c_str ( ) ) ;
if ( sif )
{
2023-01-01 12:46:07 +00:00
Accessor : : makeNullableInt (
widget , typed_value . has_value ( ) ? static_cast < int > ( static_cast < UnderlyingType > ( typed_value . value ( ) ) ) : 0 ) ;
2022-02-15 14:29:18 +00:00
std : : string sif_value ;
if ( sif - > GetStringValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
{
const std : : optional < DataType > old_setting_value = from_string_function ( sif_value . c_str ( ) ) ;
if ( old_setting_value . has_value ( ) )
Accessor : : setNullableIntValue ( widget , static_cast < int > ( static_cast < UnderlyingType > ( old_setting_value . value ( ) ) ) ) ;
else
Accessor : : setNullableIntValue ( widget , std : : nullopt ) ;
}
else
{
Accessor : : setNullableIntValue ( widget , std : : nullopt ) ;
}
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ sif , widget , section = std : : move ( section ) , key = std : : move ( key ) , to_string_function ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < int > new_value = Accessor : : getNullableIntValue ( widget ) ; new_value . has_value ( ) )
{
const char * string_value = to_string_function ( static_cast < DataType > ( static_cast < UnderlyingType > ( new_value . value ( ) ) ) ) ;
sif - > SetStringValue ( section . c_str ( ) , key . c_str ( ) , string_value ) ;
}
else
{
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
}
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
2021-12-13 12:12:54 +00:00
else
2022-02-15 14:29:18 +00:00
{
if ( typed_value . has_value ( ) )
Accessor : : setIntValue ( widget , static_cast < int > ( static_cast < UnderlyingType > ( typed_value . value ( ) ) ) ) ;
else
Accessor : : setIntValue ( widget , static_cast < int > ( static_cast < UnderlyingType > ( default_value ) ) ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) , to_string_function ] ( ) {
2022-02-15 14:29:18 +00:00
const DataType value = static_cast < DataType > ( static_cast < UnderlyingType > ( Accessor : : getIntValue ( widget ) ) ) ;
const char * string_value = to_string_function ( value ) ;
2022-09-07 07:44:10 +00:00
Host : : SetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , string_value ) ;
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
template < typename WidgetType , typename DataType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToEnumSetting (
2022-02-15 14:29:18 +00:00
SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key , const char * * enum_names , DataType default_value )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
using UnderlyingType = std : : underlying_type_t < DataType > ;
2022-02-15 14:29:18 +00:00
const std : : string value (
2022-05-24 12:37:44 +00:00
Host : : GetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , enum_names [ static_cast < UnderlyingType > ( default_value ) ] ) ) ;
2021-12-13 12:12:54 +00:00
UnderlyingType enum_index = static_cast < UnderlyingType > ( default_value ) ;
for ( UnderlyingType i = 0 ; enum_names [ i ] ! = nullptr ; i + + )
{
2022-02-15 14:29:18 +00:00
if ( value = = enum_names [ i ] )
2021-12-13 12:12:54 +00:00
{
enum_index = i ;
break ;
}
}
2022-02-15 14:29:18 +00:00
if ( sif )
{
Accessor : : makeNullableInt ( widget , static_cast < int > ( enum_index ) ) ;
std : : string sif_value ;
std : : optional < int > sif_int_value ;
if ( sif - > GetStringValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
{
for ( UnderlyingType i = 0 ; enum_names [ i ] ! = nullptr ; i + + )
{
if ( sif_value = = enum_names [ i ] )
{
sif_int_value = static_cast < int > ( i ) ;
break ;
}
}
}
Accessor : : setNullableIntValue ( widget , sif_int_value ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ sif , widget , section = std : : move ( section ) , key = std : : move ( key ) , enum_names ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < int > new_value = Accessor : : getNullableIntValue ( widget ) ; new_value . has_value ( ) )
sif - > SetStringValue ( section . c_str ( ) , key . c_str ( ) , enum_names [ new_value . value ( ) ] ) ;
else
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
else
{
Accessor : : setIntValue ( widget , static_cast < int > ( enum_index ) ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) , enum_names ] ( ) {
2022-02-15 14:29:18 +00:00
const UnderlyingType value = static_cast < UnderlyingType > ( Accessor : : getIntValue ( widget ) ) ;
2022-09-07 07:44:10 +00:00
Host : : SetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , enum_names [ value ] ) ;
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
template < typename WidgetType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToEnumSetting ( SettingsInterface * sif , WidgetType * widget , std : : string section , std : : string key ,
2023-01-01 12:46:07 +00:00
const char * * enum_names , const char * * enum_values , const char * default_value )
2021-12-13 12:12:54 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
2022-05-24 12:37:44 +00:00
const std : : string value = Host : : GetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value ) ;
2021-12-13 12:12:54 +00:00
for ( int i = 0 ; enum_names [ i ] ! = nullptr ; i + + )
widget - > addItem ( QString : : fromUtf8 ( enum_names [ i ] ) ) ;
int enum_index = - 1 ;
for ( int i = 0 ; enum_values [ i ] ! = nullptr ; i + + )
{
2022-02-15 14:29:18 +00:00
if ( value = = enum_values [ i ] )
2021-12-13 12:12:54 +00:00
{
enum_index = i ;
break ;
}
}
2022-02-15 14:29:18 +00:00
if ( sif )
{
Accessor : : makeNullableInt ( widget , enum_index ) ;
std : : string sif_value ;
std : : optional < int > sif_int_value ;
if ( sif - > GetStringValue ( section . c_str ( ) , key . c_str ( ) , & sif_value ) )
{
for ( int i = 0 ; enum_values [ i ] ! = nullptr ; i + + )
{
2022-03-15 20:31:52 +00:00
if ( sif_value = = enum_values [ i ] )
2022-02-15 14:29:18 +00:00
{
sif_int_value = i ;
break ;
}
}
}
Accessor : : setNullableIntValue ( widget , sif_int_value ) ;
2022-03-15 20:31:52 +00:00
Accessor : : connectValueChanged ( widget , [ sif , widget , section = std : : move ( section ) , key = std : : move ( key ) , enum_values ] ( ) {
2022-02-15 14:29:18 +00:00
if ( std : : optional < int > new_value = Accessor : : getNullableIntValue ( widget ) ; new_value . has_value ( ) )
2022-03-15 20:31:52 +00:00
sif - > SetStringValue ( section . c_str ( ) , key . c_str ( ) , enum_values [ new_value . value ( ) ] ) ;
2022-02-15 14:29:18 +00:00
else
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
sif - > Save ( ) ;
2022-03-07 09:37:23 +00:00
g_emu_thread - > reloadGameSettings ( ) ;
2022-02-15 14:29:18 +00:00
} ) ;
}
else
{
if ( enum_index > = 0 )
Accessor : : setIntValue ( widget , enum_index ) ;
2022-03-04 08:04:17 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) , enum_values ] ( ) {
2022-02-15 14:29:18 +00:00
const int value = Accessor : : getIntValue ( widget ) ;
2022-09-07 07:44:10 +00:00
Host : : SetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , enum_values [ value ] ) ;
Host : : CommitBaseSettingChanges ( ) ;
2022-02-15 14:29:18 +00:00
g_emu_thread - > applySettings ( ) ;
} ) ;
}
2021-12-13 12:12:54 +00:00
}
2022-06-14 10:05:11 +00:00
template < typename WidgetType >
2023-01-30 10:40:47 +00:00
static inline void BindWidgetToFolderSetting ( SettingsInterface * sif , WidgetType * widget , QAbstractButton * browse_button ,
2023-01-01 12:46:07 +00:00
QAbstractButton * open_button , QAbstractButton * reset_button , std : : string section , std : : string key , std : : string default_value ,
bool use_relative = true )
2022-06-14 10:05:11 +00:00
{
using Accessor = SettingAccessor < WidgetType > ;
std : : string current_path ( Host : : GetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value . c_str ( ) ) ) ;
2022-08-05 12:44:01 +00:00
if ( current_path . empty ( ) )
current_path = default_value ;
2022-12-24 04:11:09 +00:00
else if ( use_relative & & ! Path : : IsAbsolute ( current_path ) )
current_path = Path : : Canonicalize ( Path : : Combine ( EmuFolders : : DataRoot , current_path ) ) ;
2022-06-14 10:05:11 +00:00
const QString value ( QString : : fromStdString ( current_path ) ) ;
Accessor : : setStringValue ( widget , value ) ;
// if we're doing per-game settings, disable the widget, we only allow folder changes in the base config
if ( sif )
{
widget - > setEnabled ( false ) ;
if ( browse_button )
browse_button - > setEnabled ( false ) ;
if ( reset_button )
reset_button - > setEnabled ( false ) ;
return ;
}
2022-12-24 04:11:09 +00:00
Accessor : : connectValueChanged ( widget , [ widget , section = std : : move ( section ) , key = std : : move ( key ) , use_relative ] ( ) {
2022-06-14 10:05:11 +00:00
const std : : string new_value ( Accessor : : getStringValue ( widget ) . toStdString ( ) ) ;
if ( ! new_value . empty ( ) )
{
2022-12-24 04:11:09 +00:00
if ( use_relative )
{
const std : : string relative_path ( Path : : MakeRelative ( new_value , EmuFolders : : DataRoot ) ) ;
Host : : SetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , relative_path . c_str ( ) ) ;
}
else
{
Host : : SetBaseStringSettingValue ( section . c_str ( ) , key . c_str ( ) , new_value . c_str ( ) ) ;
}
2022-06-14 10:05:11 +00:00
}
else
{
2022-09-07 07:44:10 +00:00
Host : : RemoveBaseSettingValue ( section . c_str ( ) , key . c_str ( ) ) ;
2022-06-14 10:05:11 +00:00
}
2022-09-07 07:44:10 +00:00
Host : : CommitBaseSettingChanges ( ) ;
2022-06-14 10:05:11 +00:00
g_emu_thread - > updateEmuFolders ( ) ;
} ) ;
if ( browse_button )
{
QObject : : connect ( browse_button , & QAbstractButton : : clicked , browse_button , [ widget , key ] ( ) {
const QString path ( QDir : : toNativeSeparators ( QFileDialog : : getExistingDirectory ( QtUtils : : GetRootWidget ( widget ) ,
2023-03-18 21:14:55 +00:00
//It seems that the latter half should show the types of folders that can be selected within Settings -> Folders, but right now it's broken. It would be best for localization purposes to duplicate this into multiple lines, each per type of folder.
2022-06-14 10:05:11 +00:00
qApp - > translate ( " SettingWidgetBinder " , " Select folder for %1 " ) . arg ( QString : : fromStdString ( key ) ) ) ) ) ;
if ( path . isEmpty ( ) )
return ;
Accessor : : setStringValue ( widget , path ) ;
} ) ;
}
if ( open_button )
{
QObject : : connect ( open_button , & QAbstractButton : : clicked , open_button , [ widget ] ( ) {
QString path ( Accessor : : getStringValue ( widget ) ) ;
if ( ! path . isEmpty ( ) )
QtUtils : : OpenURL ( QtUtils : : GetRootWidget ( widget ) , QUrl : : fromLocalFile ( path ) ) ;
} ) ;
}
if ( reset_button )
{
2023-01-01 12:46:07 +00:00
QObject : : connect ( reset_button , & QAbstractButton : : clicked , reset_button , [ widget , default_value = std : : move ( default_value ) ] ( ) {
Accessor : : setStringValue ( widget , QString : : fromStdString ( default_value ) ) ;
} ) ;
}
}
2023-01-30 10:40:47 +00:00
static inline void BindSliderToIntSetting ( SettingsInterface * sif , QSlider * slider , QLabel * label , const QString & label_suffix ,
2023-01-01 12:46:07 +00:00
std : : string section , std : : string key , s32 default_value )
{
const s32 global_value = Host : : GetBaseIntSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value ) ;
if ( sif )
{
const QFont orig_font ( label - > font ( ) ) ;
QFont bold_font ( orig_font ) ;
bold_font . setBold ( true ) ;
const s32 current_value = sif - > GetOptionalIntValue ( section . c_str ( ) , key . c_str ( ) ) . value_or ( global_value ) ;
slider - > setValue ( current_value ) ;
label - > setText ( QStringLiteral ( " %1%2 " ) . arg ( current_value ) . arg ( label_suffix ) ) ;
if ( current_value = = global_value )
label - > setFont ( orig_font ) ;
else
label - > setFont ( bold_font ) ;
slider - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
slider - > connect ( slider , & QSpinBox : : customContextMenuRequested , slider ,
[ sif , slider , label , label_suffix , orig_font = std : : move ( orig_font ) , section , key , default_value ] ( const QPoint & pt ) {
QMenu menu ( slider ) ;
slider - > connect ( menu . addAction ( qApp - > translate ( " SettingWidgetBinder " , " Reset " ) ) , & QAction : : triggered , slider ,
2023-01-05 02:22:47 +00:00
[ sif , label , label_suffix , orig_font , section , key , default_value ] ( ) {
2023-01-01 12:46:07 +00:00
const s32 global_value = Host : : GetBaseIntSettingValue ( section . c_str ( ) , key . c_str ( ) , default_value ) ;
label - > setText ( QStringLiteral ( " %1%2 " ) . arg ( global_value ) . arg ( label_suffix ) ) ;
label - > setFont ( orig_font ) ;
if ( sif - > ContainsValue ( section . c_str ( ) , key . c_str ( ) ) )
{
sif - > DeleteValue ( section . c_str ( ) , key . c_str ( ) ) ;
sif - > Save ( ) ;
g_emu_thread - > reloadGameSettings ( ) ;
}
} ) ;
menu . exec ( slider - > mapToGlobal ( pt ) ) ;
} ) ;
slider - > connect ( slider , & QSlider : : valueChanged , slider ,
2023-01-30 10:40:47 +00:00
[ sif , label , label_suffix , section = std : : move ( section ) , key = std : : move ( key ) , orig_font = std : : move ( orig_font ) ,
bold_font = std : : move ( bold_font ) ] ( int value ) {
2023-01-01 12:46:07 +00:00
label - > setText ( QStringLiteral ( " %1%2 " ) . arg ( value ) . arg ( label_suffix ) ) ;
if ( label - > font ( ) ! = bold_font )
label - > setFont ( bold_font ) ;
sif - > SetIntValue ( section . c_str ( ) , key . c_str ( ) , value ) ;
sif - > Save ( ) ;
g_emu_thread - > reloadGameSettings ( ) ;
} ) ;
}
else
{
slider - > setValue ( global_value ) ;
label - > setText ( QStringLiteral ( " %1%2 " ) . arg ( global_value ) . arg ( label_suffix ) ) ;
slider - > connect ( slider , & QSlider : : valueChanged , slider ,
2023-01-05 02:22:47 +00:00
[ label , label_suffix , section = std : : move ( section ) , key = std : : move ( key ) ] ( int value ) {
2023-01-01 12:46:07 +00:00
label - > setText ( QStringLiteral ( " %1%2 " ) . arg ( value ) . arg ( label_suffix ) ) ;
Host : : SetBaseIntSettingValue ( section . c_str ( ) , key . c_str ( ) , value ) ;
Host : : CommitBaseSettingChanges ( ) ;
g_emu_thread - > applySettings ( ) ;
} ) ;
2022-06-14 10:05:11 +00:00
}
}
2021-12-13 12:12:54 +00:00
} // namespace SettingWidgetBinder