2024-07-30 11:42:36 +00:00
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
2023-05-25 16:24:01 +00:00
# include "MainWindow.h"
# include "QtHost.h"
# include "QtUtils.h"
# include "Settings/GamePatchSettingsWidget.h"
2024-01-01 00:23:27 +00:00
# include "SettingWidgetBinder.h"
2023-10-14 08:45:09 +00:00
# include "Settings/SettingsWindow.h"
2023-05-25 16:24:01 +00:00
# include "pcsx2/GameList.h"
# include "pcsx2/Patch.h"
2023-10-09 14:16:15 +00:00
# include "common/Assertions.h"
2023-05-25 16:24:01 +00:00
# include <algorithm>
GamePatchDetailsWidget : : GamePatchDetailsWidget ( std : : string name , const std : : string & author ,
2024-12-24 16:09:44 +00:00
const std : : string & description , bool tristate , Qt : : CheckState checkState , SettingsWindow * dialog , QWidget * parent )
2023-05-25 16:24:01 +00:00
: QWidget ( parent )
, m_dialog ( dialog )
, m_name ( name )
{
m_ui . setupUi ( this ) ;
m_ui . name - > setText ( QString : : fromStdString ( name ) ) ;
m_ui . description - > setText (
tr ( " <strong>Author: </strong>%1<br>%2 " )
. arg ( author . empty ( ) ? tr ( " Unknown " ) : QString : : fromStdString ( author ) )
. arg ( description . empty ( ) ? tr ( " No description provided. " ) : QString : : fromStdString ( description ) ) ) ;
pxAssert ( dialog - > getSettingsInterface ( ) ) ;
2024-12-24 16:09:44 +00:00
m_ui . enabled - > setTristate ( tristate ) ;
m_ui . enabled - > setCheckState ( checkState ) ;
2024-04-12 12:22:58 +00:00
connect ( m_ui . enabled , & QCheckBox : : checkStateChanged , this , & GamePatchDetailsWidget : : onEnabledStateChanged ) ;
2023-05-25 16:24:01 +00:00
}
GamePatchDetailsWidget : : ~ GamePatchDetailsWidget ( ) = default ;
void GamePatchDetailsWidget : : onEnabledStateChanged ( int state )
{
SettingsInterface * si = m_dialog - > getSettingsInterface ( ) ;
if ( state = = Qt : : Checked )
2024-12-24 16:09:44 +00:00
{
si - > AddToStringList ( Patch : : PATCHES_CONFIG_SECTION , Patch : : PATCH_ENABLE_CONFIG_KEY , m_name . c_str ( ) ) ;
si - > RemoveFromStringList ( Patch : : PATCHES_CONFIG_SECTION , Patch : : PATCH_DISABLE_CONFIG_KEY , m_name . c_str ( ) ) ;
}
2023-05-25 16:24:01 +00:00
else
2024-12-24 16:09:44 +00:00
{
si - > RemoveFromStringList ( Patch : : PATCHES_CONFIG_SECTION , Patch : : PATCH_ENABLE_CONFIG_KEY , m_name . c_str ( ) ) ;
if ( m_ui . enabled - > isTristate ( ) )
{
if ( state = = Qt : : Unchecked )
{
si - > AddToStringList ( Patch : : PATCHES_CONFIG_SECTION , Patch : : PATCH_DISABLE_CONFIG_KEY , m_name . c_str ( ) ) ;
}
else
{
si - > RemoveFromStringList ( Patch : : PATCHES_CONFIG_SECTION , Patch : : PATCH_DISABLE_CONFIG_KEY , m_name . c_str ( ) ) ;
}
}
}
2023-05-25 16:24:01 +00:00
si - > Save ( ) ;
g_emu_thread - > reloadGameSettings ( ) ;
}
2023-10-14 08:45:09 +00:00
GamePatchSettingsWidget : : GamePatchSettingsWidget ( SettingsWindow * dialog , QWidget * parent )
2023-05-25 16:24:01 +00:00
: m_dialog ( dialog )
{
m_ui . setupUi ( this ) ;
m_ui . scrollArea - > setFrameShape ( QFrame : : WinPanel ) ;
m_ui . scrollArea - > setFrameShadow ( QFrame : : Sunken ) ;
2023-11-26 05:17:41 +00:00
setUnlabeledPatchesWarningVisibility ( false ) ;
2024-12-24 16:09:44 +00:00
setGlobalWsPatchNoteVisibility ( false ) ;
setGlobalNiPatchNoteVisibility ( false ) ;
2023-11-26 05:17:41 +00:00
2024-01-01 00:23:27 +00:00
SettingsInterface * sif = m_dialog - > getSettingsInterface ( ) ;
SettingWidgetBinder : : BindWidgetToBoolSetting ( sif , m_ui . allCRCsCheckbox , " EmuCore " , " ShowPatchesForAllCRCs " , false ) ;
2023-05-25 16:24:01 +00:00
2024-01-07 07:35:41 +00:00
connect ( m_ui . reload , & QPushButton : : clicked , this , & GamePatchSettingsWidget : : onReloadClicked ) ;
2024-04-12 12:22:58 +00:00
connect ( m_ui . allCRCsCheckbox , & QCheckBox : : checkStateChanged , this , & GamePatchSettingsWidget : : reloadList ) ;
2024-12-27 19:22:06 +00:00
connect ( m_dialog , & SettingsWindow : : discSerialChanged , this , & GamePatchSettingsWidget : : reloadList ) ;
2024-01-07 07:35:41 +00:00
2024-01-09 23:52:24 +00:00
dialog - > registerWidgetHelp ( m_ui . allCRCsCheckbox , tr ( " Show Patches For All CRCs " ) , tr ( " Checked " ) ,
tr ( " Toggles scanning patch files for all CRCs of the game. With this enabled available patches for the game serial with different CRCs will also be loaded. " ) ) ;
2023-05-25 16:24:01 +00:00
reloadList ( ) ;
}
GamePatchSettingsWidget : : ~ GamePatchSettingsWidget ( ) = default ;
void GamePatchSettingsWidget : : onReloadClicked ( )
{
reloadList ( ) ;
// reload it on the emu thread too, so it picks up any changes
g_emu_thread - > reloadPatches ( ) ;
}
2024-01-01 02:40:14 +00:00
void GamePatchSettingsWidget : : disableAllPatches ( )
{
SettingsInterface * si = m_dialog - > getSettingsInterface ( ) ;
si - > ClearSection ( Patch : : PATCHES_CONFIG_SECTION ) ;
si - > Save ( ) ;
}
2023-05-25 16:24:01 +00:00
void GamePatchSettingsWidget : : reloadList ( )
{
2024-12-24 16:09:44 +00:00
const SettingsInterface * si = m_dialog - > getSettingsInterface ( ) ;
2023-05-25 16:24:01 +00:00
// Patches shouldn't have any unlabelled patch groups, because they're new.
2023-11-28 22:17:08 +00:00
u32 number_of_unlabeled_patches = 0 ;
2024-01-01 00:23:27 +00:00
bool showAllCRCS = m_ui . allCRCsCheckbox - > isChecked ( ) ;
std : : vector < Patch : : PatchInfo > patches = Patch : : GetPatchInfo ( m_dialog - > getSerial ( ) , m_dialog - > getDiscCRC ( ) , false , showAllCRCS , & number_of_unlabeled_patches ) ;
2023-05-25 16:24:01 +00:00
std : : vector < std : : string > enabled_list =
2024-12-24 16:09:44 +00:00
si - > GetStringList ( Patch : : PATCHES_CONFIG_SECTION , Patch : : PATCH_ENABLE_CONFIG_KEY ) ;
std : : vector < std : : string > disabled_list =
si - > GetStringList ( Patch : : PATCHES_CONFIG_SECTION , Patch : : PATCH_DISABLE_CONFIG_KEY ) ;
const bool ws_patches_enabled_globally = m_dialog - > getEffectiveBoolValue ( " EmuCore " , " EnableWideScreenPatches " , false ) ;
const bool ni_patches_enabled_globally = m_dialog - > getEffectiveBoolValue ( " EmuCore " , " EnableNoInterlacingPatches " , false ) ;
2023-05-25 16:24:01 +00:00
2023-11-28 22:17:08 +00:00
setUnlabeledPatchesWarningVisibility ( number_of_unlabeled_patches > 0 ) ;
2024-12-24 16:09:44 +00:00
setGlobalWsPatchNoteVisibility ( ws_patches_enabled_globally ) ;
setGlobalNiPatchNoteVisibility ( ni_patches_enabled_globally ) ;
2023-05-25 16:24:01 +00:00
delete m_ui . scrollArea - > takeWidget ( ) ;
2024-12-27 18:24:37 +00:00
m_ui . allCRCsCheckbox - > setEnabled ( ! m_dialog - > getSerial ( ) . empty ( ) ) ;
2023-05-25 16:24:01 +00:00
QWidget * container = new QWidget ( m_ui . scrollArea ) ;
QVBoxLayout * layout = new QVBoxLayout ( container ) ;
layout - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
if ( ! patches . empty ( ) )
{
bool first = true ;
2024-12-24 16:09:44 +00:00
for ( const Patch : : PatchInfo & pi : patches )
2023-05-25 16:24:01 +00:00
{
if ( ! first )
{
QFrame * frame = new QFrame ( container ) ;
frame - > setFrameShape ( QFrame : : HLine ) ;
frame - > setFrameShadow ( QFrame : : Sunken ) ;
layout - > addWidget ( frame ) ;
}
else
{
first = false ;
}
2024-12-24 16:09:44 +00:00
const bool is_on_enable_list = std : : find ( enabled_list . begin ( ) , enabled_list . end ( ) , pi . name ) ! = enabled_list . end ( ) ;
const bool is_on_disable_list = std : : find ( disabled_list . begin ( ) , disabled_list . end ( ) , pi . name ) ! = disabled_list . end ( ) ;
const bool globally_toggleable_option = Patch : : IsGloballyToggleablePatch ( pi ) ;
Qt : : CheckState check_state ;
if ( ! globally_toggleable_option )
{
// Normal patches
check_state = is_on_enable_list & & ! is_on_disable_list ? Qt : : CheckState : : Checked : Qt : : CheckState : : Unchecked ;
}
else
{
// WS/NI patches
if ( is_on_disable_list )
{
check_state = Qt : : CheckState : : Unchecked ;
}
else if ( is_on_enable_list )
{
check_state = Qt : : CheckState : : Checked ;
}
else
{
check_state = Qt : : CheckState : : PartiallyChecked ;
}
}
2023-05-25 16:24:01 +00:00
GamePatchDetailsWidget * it =
2024-12-24 16:09:44 +00:00
new GamePatchDetailsWidget ( std : : move ( pi . name ) , pi . author , pi . description , globally_toggleable_option , check_state , m_dialog , container ) ;
2023-05-25 16:24:01 +00:00
layout - > addWidget ( it ) ;
}
}
else
{
QLabel * label = new QLabel ( tr ( " There are no patches available for this game. " ) , container ) ;
layout - > addWidget ( label ) ;
}
layout - > addStretch ( 1 ) ;
m_ui . scrollArea - > setWidget ( container ) ;
}
2023-11-26 05:17:41 +00:00
2024-01-07 07:35:41 +00:00
void GamePatchSettingsWidget : : setUnlabeledPatchesWarningVisibility ( bool visible )
{
2023-11-26 05:17:41 +00:00
m_ui . unlabeledPatchWarning - > setVisible ( visible ) ;
2024-01-07 07:35:41 +00:00
}
2024-12-24 16:09:44 +00:00
void GamePatchSettingsWidget : : setGlobalWsPatchNoteVisibility ( bool visible )
{
m_ui . globalWsPatchState - > setVisible ( visible ) ;
}
void GamePatchSettingsWidget : : setGlobalNiPatchNoteVisibility ( bool visible )
{
m_ui . globalNiPatchState - > setVisible ( visible ) ;
}