mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Add cheats in per game configuration (#6379)
This commit is contained in:
		
							parent
							
								
									ea649263b7
								
							
						
					
					
						commit
						7327c334ca
					
				
					 13 changed files with 86 additions and 122 deletions
				
			
		|  | @ -28,9 +28,6 @@ add_executable(citra-qt | |||
|     camera/qt_camera_base.h | ||||
|     camera/qt_multimedia_camera.cpp | ||||
|     camera/qt_multimedia_camera.h | ||||
|     cheats.cpp | ||||
|     cheats.h | ||||
|     cheats.ui | ||||
|     citra-qt.rc | ||||
|     compatdb.cpp | ||||
|     compatdb.h | ||||
|  | @ -88,6 +85,9 @@ add_executable(citra-qt | |||
|     configuration/configure_web.cpp | ||||
|     configuration/configure_web.h | ||||
|     configuration/configure_web.ui | ||||
|     configuration/configure_cheats.cpp | ||||
|     configuration/configure_cheats.h | ||||
|     configuration/configure_cheats.ui | ||||
|     debugger/console.h | ||||
|     debugger/console.cpp | ||||
|     debugger/graphics/graphics.cpp | ||||
|  |  | |||
|  | @ -5,16 +5,16 @@ | |||
| #include <QCheckBox> | ||||
| #include <QMessageBox> | ||||
| #include <QTableWidgetItem> | ||||
| #include "citra_qt/cheats.h" | ||||
| #include "configure_cheats.h" | ||||
| #include "core/cheats/cheat_base.h" | ||||
| #include "core/cheats/cheats.h" | ||||
| #include "core/cheats/gateway_cheat.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "ui_cheats.h" | ||||
| #include "ui_configure_cheats.h" | ||||
| 
 | ||||
| CheatDialog::CheatDialog(QWidget* parent) | ||||
|     : QDialog(parent), ui(std::make_unique<Ui::CheatDialog>()) { | ||||
| ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureCheats>()), title_id{title_id_} { | ||||
|     // Setup gui control settings
 | ||||
|     ui->setupUi(this); | ||||
|     ui->tableCheats->setColumnWidth(0, 30); | ||||
|  | @ -25,28 +25,26 @@ CheatDialog::CheatDialog(QWidget* parent) | |||
|     ui->lineName->setEnabled(false); | ||||
|     ui->textCode->setEnabled(false); | ||||
|     ui->textNotes->setEnabled(false); | ||||
|     const auto game_id = fmt::format( | ||||
|         "{:016X}", Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id); | ||||
|     ui->labelTitle->setText(tr("Title ID: %1").arg(QString::fromStdString(game_id))); | ||||
| 
 | ||||
|     connect(ui->buttonClose, &QPushButton::clicked, this, &CheatDialog::OnCancel); | ||||
|     connect(ui->buttonAddCheat, &QPushButton::clicked, this, &CheatDialog::OnAddCheat); | ||||
|     connect(ui->tableCheats, &QTableWidget::cellClicked, this, &CheatDialog::OnRowSelected); | ||||
|     connect(ui->lineName, &QLineEdit::textEdited, this, &CheatDialog::OnTextEdited); | ||||
|     connect(ui->textNotes, &QPlainTextEdit::textChanged, this, &CheatDialog::OnTextEdited); | ||||
|     connect(ui->textCode, &QPlainTextEdit::textChanged, this, &CheatDialog::OnTextEdited); | ||||
|     connect(ui->buttonAddCheat, &QPushButton::clicked, this, &ConfigureCheats::OnAddCheat); | ||||
|     connect(ui->tableCheats, &QTableWidget::cellClicked, this, &ConfigureCheats::OnRowSelected); | ||||
|     connect(ui->lineName, &QLineEdit::textEdited, this, &ConfigureCheats::OnTextEdited); | ||||
|     connect(ui->textNotes, &QPlainTextEdit::textChanged, this, &ConfigureCheats::OnTextEdited); | ||||
|     connect(ui->textCode, &QPlainTextEdit::textChanged, this, &ConfigureCheats::OnTextEdited); | ||||
| 
 | ||||
|     connect(ui->buttonSave, &QPushButton::clicked, this, | ||||
|             [this] { SaveCheat(ui->tableCheats->currentRow()); }); | ||||
|     connect(ui->buttonDelete, &QPushButton::clicked, this, &CheatDialog::OnDeleteCheat); | ||||
|     connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat); | ||||
| 
 | ||||
|     cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, Core::System::GetInstance()); | ||||
| 
 | ||||
|     LoadCheats(); | ||||
| } | ||||
| 
 | ||||
| CheatDialog::~CheatDialog() = default; | ||||
| ConfigureCheats::~ConfigureCheats() = default; | ||||
| 
 | ||||
| void CheatDialog::LoadCheats() { | ||||
|     cheats = Core::System::GetInstance().CheatEngine().GetCheats(); | ||||
| void ConfigureCheats::LoadCheats() { | ||||
|     cheats = cheat_engine->GetCheats(); | ||||
|     const int cheats_count = static_cast<int>(cheats.size()); | ||||
| 
 | ||||
|     ui->tableCheats->setRowCount(cheats_count); | ||||
|  | @ -63,11 +61,11 @@ void CheatDialog::LoadCheats() { | |||
|             i, 2, new QTableWidgetItem(QString::fromStdString(cheats[i]->GetType()))); | ||||
|         enabled->setProperty("row", static_cast<int>(i)); | ||||
| 
 | ||||
|         connect(enabled, &QCheckBox::stateChanged, this, &CheatDialog::OnCheckChanged); | ||||
|         connect(enabled, &QCheckBox::stateChanged, this, &ConfigureCheats::OnCheckChanged); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool CheatDialog::CheckSaveCheat() { | ||||
| bool ConfigureCheats::CheckSaveCheat() { | ||||
|     auto answer = QMessageBox::warning( | ||||
|         this, tr("Cheats"), tr("Would you like to save the current cheat?"), | ||||
|         QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel); | ||||
|  | @ -79,7 +77,7 @@ bool CheatDialog::CheckSaveCheat() { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool CheatDialog::SaveCheat(int row) { | ||||
| bool ConfigureCheats::SaveCheat(int row) { | ||||
|     if (ui->lineName->text().isEmpty()) { | ||||
|         QMessageBox::critical(this, tr("Save Cheat"), tr("Please enter a cheat name.")); | ||||
|         return false; | ||||
|  | @ -110,12 +108,12 @@ bool CheatDialog::SaveCheat(int row) { | |||
|                                                         ui->textNotes->toPlainText().toStdString()); | ||||
| 
 | ||||
|     if (newly_created) { | ||||
|         Core::System::GetInstance().CheatEngine().AddCheat(cheat); | ||||
|         cheat_engine->AddCheat(cheat); | ||||
|         newly_created = false; | ||||
|     } else { | ||||
|         Core::System::GetInstance().CheatEngine().UpdateCheat(row, cheat); | ||||
|         cheat_engine->UpdateCheat(row, cheat); | ||||
|     } | ||||
|     Core::System::GetInstance().CheatEngine().SaveCheatFile(); | ||||
|     cheat_engine->SaveCheatFile(); | ||||
| 
 | ||||
|     int previous_row = ui->tableCheats->currentRow(); | ||||
|     int previous_col = ui->tableCheats->currentColumn(); | ||||
|  | @ -128,19 +126,7 @@ bool CheatDialog::SaveCheat(int row) { | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void CheatDialog::closeEvent(QCloseEvent* event) { | ||||
|     if (edited && !CheckSaveCheat()) { | ||||
|         event->ignore(); | ||||
|         return; | ||||
|     } | ||||
|     event->accept(); | ||||
| } | ||||
| 
 | ||||
| void CheatDialog::OnCancel() { | ||||
|     close(); | ||||
| } | ||||
| 
 | ||||
| void CheatDialog::OnRowSelected(int row, int column) { | ||||
| void ConfigureCheats::OnRowSelected(int row, int column) { | ||||
|     if (row == last_row) { | ||||
|         return; | ||||
|     } | ||||
|  | @ -173,25 +159,24 @@ void CheatDialog::OnRowSelected(int row, int column) { | |||
|     last_col = column; | ||||
| } | ||||
| 
 | ||||
| void CheatDialog::OnCheckChanged(int state) { | ||||
| void ConfigureCheats::OnCheckChanged(int state) { | ||||
|     const QCheckBox* checkbox = qobject_cast<QCheckBox*>(sender()); | ||||
|     int row = static_cast<int>(checkbox->property("row").toInt()); | ||||
|     cheats[row]->SetEnabled(state); | ||||
|     Core::System::GetInstance().CheatEngine().SaveCheatFile(); | ||||
|     cheat_engine->SaveCheatFile(); | ||||
| } | ||||
| 
 | ||||
| void CheatDialog::OnTextEdited() { | ||||
| void ConfigureCheats::OnTextEdited() { | ||||
|     edited = true; | ||||
|     ui->buttonSave->setEnabled(true); | ||||
| } | ||||
| 
 | ||||
| void CheatDialog::OnDeleteCheat() { | ||||
| void ConfigureCheats::OnDeleteCheat() { | ||||
|     if (newly_created) { | ||||
|         newly_created = false; | ||||
|     } else { | ||||
|         auto& cheat_engine = Core::System::GetInstance().CheatEngine(); | ||||
|         cheat_engine.RemoveCheat(ui->tableCheats->currentRow()); | ||||
|         cheat_engine.SaveCheatFile(); | ||||
|         cheat_engine->RemoveCheat(ui->tableCheats->currentRow()); | ||||
|         cheat_engine->SaveCheatFile(); | ||||
|     } | ||||
| 
 | ||||
|     LoadCheats(); | ||||
|  | @ -221,7 +206,14 @@ void CheatDialog::OnDeleteCheat() { | |||
|     ui->buttonAddCheat->setEnabled(true); | ||||
| } | ||||
| 
 | ||||
| void CheatDialog::OnAddCheat() { | ||||
| bool ConfigureCheats::ApplyConfiguration() { | ||||
|     if (edited) { | ||||
|         return SaveCheat(ui->tableCheats->currentRow()); | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void ConfigureCheats::OnAddCheat() { | ||||
|     if (edited && !CheckSaveCheat()) { | ||||
|         return; | ||||
|     } | ||||
|  | @ -5,22 +5,24 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QDialog> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Cheats { | ||||
| class CheatBase; | ||||
| } | ||||
| class CheatEngine; | ||||
| } // namespace Cheats
 | ||||
| 
 | ||||
| namespace Ui { | ||||
| class CheatDialog; | ||||
| class ConfigureCheats; | ||||
| } // namespace Ui
 | ||||
| 
 | ||||
| class CheatDialog : public QDialog { | ||||
| class ConfigureCheats : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit CheatDialog(QWidget* parent = nullptr); | ||||
|     ~CheatDialog(); | ||||
|     explicit ConfigureCheats(u64 title_id_, QWidget* parent = nullptr); | ||||
|     ~ConfigureCheats(); | ||||
|     bool ApplyConfiguration(); | ||||
| 
 | ||||
| private: | ||||
|     /**
 | ||||
|  | @ -42,10 +44,7 @@ private: | |||
|      */ | ||||
|     bool SaveCheat(int row); | ||||
| 
 | ||||
|     void closeEvent(QCloseEvent* event) override; | ||||
| 
 | ||||
| private slots: | ||||
|     void OnCancel(); | ||||
|     void OnRowSelected(int row, int column); | ||||
|     void OnCheckChanged(int state); | ||||
|     void OnTextEdited(); | ||||
|  | @ -53,8 +52,10 @@ private slots: | |||
|     void OnAddCheat(); | ||||
| 
 | ||||
| private: | ||||
|     std::unique_ptr<Ui::CheatDialog> ui; | ||||
|     std::unique_ptr<Ui::ConfigureCheats> ui; | ||||
|     std::vector<std::shared_ptr<Cheats::CheatBase>> cheats; | ||||
|     bool edited = false, newly_created = false; | ||||
|     int last_row = -1, last_col = -1; | ||||
|     u64 title_id; | ||||
|     std::unique_ptr<Cheats::CheatEngine> cheat_engine; | ||||
| }; | ||||
|  | @ -1,7 +1,7 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>CheatDialog</class> | ||||
|  <widget class="QDialog" name="CheatDialog"> | ||||
|  <class>ConfigureCheats</class> | ||||
|  <widget class="QWidget" name="ConfigureCheats"> | ||||
|   <property name="windowModality"> | ||||
|    <enum>Qt::ApplicationModal</enum> | ||||
|   </property> | ||||
|  | @ -25,18 +25,6 @@ | |||
|   <layout class="QVBoxLayout"> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout"> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="labelTitle"> | ||||
|        <property name="font"> | ||||
|         <font> | ||||
|          <pointsize>10</pointsize> | ||||
|         </font> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>Title ID:</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <spacer> | ||||
|        <property name="orientation"> | ||||
|  | @ -208,13 +196,6 @@ | |||
|        </property> | ||||
|       </spacer> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QPushButton" name="buttonClose"> | ||||
|        <property name="text"> | ||||
|         <string>Close</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|   </layout> | ||||
|  | @ -227,7 +208,6 @@ | |||
|   <tabstop>textCode</tabstop> | ||||
|   <tabstop>buttonSave</tabstop> | ||||
|   <tabstop>buttonDelete</tabstop> | ||||
|   <tabstop>buttonClose</tabstop> | ||||
|  </tabstops> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
|  | @ -9,6 +9,7 @@ | |||
| #include <fmt/format.h> | ||||
| #include "citra_qt/configuration/config.h" | ||||
| #include "citra_qt/configuration/configure_audio.h" | ||||
| #include "citra_qt/configuration/configure_cheats.h" | ||||
| #include "citra_qt/configuration/configure_debug.h" | ||||
| #include "citra_qt/configuration/configure_enhancements.h" | ||||
| #include "citra_qt/configuration/configure_general.h" | ||||
|  | @ -35,6 +36,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString | |||
|     graphics_tab = std::make_unique<ConfigureGraphics>(this); | ||||
|     system_tab = std::make_unique<ConfigureSystem>(this); | ||||
|     debug_tab = std::make_unique<ConfigureDebug>(this); | ||||
|     cheat_tab = std::make_unique<ConfigureCheats>(title_id, this); | ||||
| 
 | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|  | @ -44,6 +46,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString | |||
|     ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); | ||||
|     ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); | ||||
|     ui->tabWidget->addTab(debug_tab.get(), tr("Debug")); | ||||
|     ui->tabWidget->addTab(cheat_tab.get(), tr("Cheats")); | ||||
| 
 | ||||
|     setFocusPolicy(Qt::ClickFocus); | ||||
|     setWindowTitle(tr("Properties")); | ||||
|  | @ -60,6 +63,9 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString | |||
|     connect(ui->button_reset_per_game, &QPushButton::clicked, this, | ||||
|             &ConfigurePerGame::ResetDefaults); | ||||
| 
 | ||||
|     connect(ui->buttonBox, &QDialogButtonBox::accepted, this, | ||||
|             &ConfigurePerGame::HandleAcceptedEvent); | ||||
| 
 | ||||
|     LoadConfiguration(); | ||||
| } | ||||
| 
 | ||||
|  | @ -81,6 +87,13 @@ void ConfigurePerGame::ResetDefaults() { | |||
|     close(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurePerGame::HandleAcceptedEvent() { | ||||
|     if (ui->tabWidget->currentWidget() == cheat_tab.get()) { | ||||
|         cheat_tab->ApplyConfiguration(); | ||||
|     } | ||||
|     accept(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurePerGame::ApplyConfiguration() { | ||||
|     general_tab->ApplyConfiguration(); | ||||
|     system_tab->ApplyConfiguration(); | ||||
|  | @ -109,6 +122,9 @@ void ConfigurePerGame::RetranslateUI() { | |||
| 
 | ||||
| void ConfigurePerGame::HandleApplyButtonClicked() { | ||||
|     ApplyConfiguration(); | ||||
|     if (ui->tabWidget->currentWidget() == cheat_tab.get()) { | ||||
|         cheat_tab->ApplyConfiguration(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static QPixmap GetQPixmapFromSMDH(std::vector<u8>& smdh_data) { | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ class ConfigureEnhancements; | |||
| class ConfigureGraphics; | ||||
| class ConfigureSystem; | ||||
| class ConfigureDebug; | ||||
| class ConfigureCheats; | ||||
| 
 | ||||
| class QGraphicsScene; | ||||
| class QStandardItem; | ||||
|  | @ -51,6 +52,7 @@ public: | |||
| private: | ||||
|     void changeEvent(QEvent* event) override; | ||||
|     void RetranslateUI(); | ||||
|     void HandleAcceptedEvent(); | ||||
| 
 | ||||
|     void HandleApplyButtonClicked(); | ||||
| 
 | ||||
|  | @ -70,4 +72,5 @@ private: | |||
|     std::unique_ptr<ConfigureGraphics> graphics_tab; | ||||
|     std::unique_ptr<ConfigureSystem> system_tab; | ||||
|     std::unique_ptr<ConfigureDebug> debug_tab; | ||||
|     std::unique_ptr<ConfigureCheats> cheat_tab; | ||||
| }; | ||||
|  |  | |||
|  | @ -235,22 +235,6 @@ | |||
|  </widget> | ||||
|  <resources/> | ||||
|  <connections> | ||||
|   <connection> | ||||
|    <sender>buttonBox</sender> | ||||
|    <signal>accepted()</signal> | ||||
|    <receiver>ConfigurePerGame</receiver> | ||||
|    <slot>accept()</slot> | ||||
|    <hints> | ||||
|     <hint type="sourcelabel"> | ||||
|      <x>20</x> | ||||
|      <y>20</y> | ||||
|     </hint> | ||||
|     <hint type="destinationlabel"> | ||||
|      <x>20</x> | ||||
|      <y>20</y> | ||||
|     </hint> | ||||
|    </hints> | ||||
|   </connection> | ||||
|   <connection> | ||||
|    <sender>buttonBox</sender> | ||||
|    <signal>rejected()</signal> | ||||
|  |  | |||
|  | @ -34,7 +34,6 @@ | |||
| #include "citra_qt/bootmanager.h" | ||||
| #include "citra_qt/camera/qt_multimedia_camera.h" | ||||
| #include "citra_qt/camera/still_image_camera.h" | ||||
| #include "citra_qt/cheats.h" | ||||
| #include "citra_qt/compatdb.h" | ||||
| #include "citra_qt/compatibility_list.h" | ||||
| #include "citra_qt/configuration/config.h" | ||||
|  | @ -663,7 +662,6 @@ void GMainWindow::RestoreUIState() { | |||
|     microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); | ||||
|     microProfileDialog->setVisible(UISettings::values.microprofile_visible.GetValue()); | ||||
| #endif | ||||
|     ui->action_Cheats->setEnabled(false); | ||||
| 
 | ||||
|     game_list->LoadInterfaceLayout(); | ||||
| 
 | ||||
|  | @ -765,7 +763,6 @@ void GMainWindow::ConnectMenuEvents() { | |||
|     connect_menu(ui->action_Report_Compatibility, &GMainWindow::OnMenuReportCompatibility); | ||||
|     connect_menu(ui->action_Configure, &GMainWindow::OnConfigure); | ||||
|     connect_menu(ui->action_Configure_Current_Game, &GMainWindow::OnConfigurePerGame); | ||||
|     connect_menu(ui->action_Cheats, &GMainWindow::OnCheats); | ||||
| 
 | ||||
|     // View
 | ||||
|     connect_menu(ui->action_Single_Window_Mode, &GMainWindow::ToggleWindowMode); | ||||
|  | @ -851,7 +848,6 @@ void GMainWindow::UpdateMenuState() { | |||
|         ui->action_Load_Amiibo, | ||||
|         ui->action_Remove_Amiibo, | ||||
|         ui->action_Pause, | ||||
|         ui->action_Cheats, | ||||
|         ui->action_Advance_Frame, | ||||
|     }; | ||||
| 
 | ||||
|  | @ -1937,11 +1933,6 @@ void GMainWindow::TriggerRotateScreens() { | |||
|     ui->action_Screen_Layout_Upright_Screens->trigger(); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnCheats() { | ||||
|     CheatDialog cheat_dialog(this); | ||||
|     cheat_dialog.exec(); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnSaveState() { | ||||
|     QAction* action = qobject_cast<QAction*>(sender()); | ||||
|     assert(action); | ||||
|  |  | |||
|  | @ -217,7 +217,6 @@ private slots: | |||
|     void OnRotateScreens(); | ||||
|     void TriggerSwapScreens(); | ||||
|     void TriggerRotateScreens(); | ||||
|     void OnCheats(); | ||||
|     void ShowFullscreen(); | ||||
|     void HideFullscreen(); | ||||
|     void ToggleWindowMode(); | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ | |||
|      <x>0</x> | ||||
|      <y>0</y> | ||||
|      <width>1081</width> | ||||
|      <height>25</height> | ||||
|      <height>22</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <widget class="QMenu" name="menu_File"> | ||||
|  | @ -115,7 +115,6 @@ | |||
|     <addaction name="separator"/> | ||||
|     <addaction name="action_Configure"/> | ||||
|     <addaction name="action_Configure_Current_Game"/> | ||||
|     <addaction name="action_Cheats"/> | ||||
|    </widget> | ||||
|    <widget class="QMenu" name="menu_View"> | ||||
|     <property name="title"> | ||||
|  | @ -333,11 +332,6 @@ | |||
|     <enum>QAction::PreferencesRole</enum> | ||||
|    </property> | ||||
|   </action> | ||||
|   <action name="action_Cheats"> | ||||
|    <property name="text"> | ||||
|     <string>Cheats...</string> | ||||
|    </property> | ||||
|   </action> | ||||
|   <action name="action_Display_Dock_Widget_Headers"> | ||||
|    <property name="checkable"> | ||||
|     <bool>true</bool> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue