mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-06 03:25:36 +00:00
Qt: Add search and sorting to cheat list
This commit is contained in:
parent
0dc257abe4
commit
991405ce06
@ -18,16 +18,19 @@
|
||||
|
||||
#include <QtCore/QSignalBlocker>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QStandardItem>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
#include <QtWidgets/QStyledItemDelegate>
|
||||
|
||||
LOG_CHANNEL(Cheats);
|
||||
|
||||
namespace {
|
||||
|
||||
class CheatListOptionDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
CheatListOptionDelegate(GameCheatSettingsWidget* parent, QTreeWidget* treeview);
|
||||
CheatListOptionDelegate(GameCheatSettingsWidget* parent, QTreeView* treeview);
|
||||
|
||||
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
@ -39,11 +42,11 @@ private:
|
||||
const Cheats::CodeInfo* getCodeInfoForRow(const QModelIndex& index) const;
|
||||
|
||||
GameCheatSettingsWidget* m_parent;
|
||||
QTreeWidget* m_treeview;
|
||||
QTreeView* m_treeview;
|
||||
};
|
||||
}; // namespace
|
||||
|
||||
CheatListOptionDelegate::CheatListOptionDelegate(GameCheatSettingsWidget* parent, QTreeWidget* treeview)
|
||||
CheatListOptionDelegate::CheatListOptionDelegate(GameCheatSettingsWidget* parent, QTreeView* treeview)
|
||||
: QStyledItemDelegate(parent), m_parent(parent), m_treeview(treeview)
|
||||
{
|
||||
}
|
||||
@ -149,7 +152,7 @@ void CheatListOptionDelegate::paint(QPainter* painter, const QStyleOptionViewIte
|
||||
if (index.column() == 0)
|
||||
{
|
||||
// skip for editable rows
|
||||
if (index.flags() & Qt::ItemIsEditable)
|
||||
if (index.data(Qt::UserRole + 1).toBool())
|
||||
return QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
// expand the width to full for those without options
|
||||
@ -173,25 +176,37 @@ void CheatListOptionDelegate::paint(QPainter* painter, const QStyleOptionViewIte
|
||||
|
||||
GameCheatSettingsWidget::GameCheatSettingsWidget(SettingsWindow* dialog, QWidget* parent) : m_dialog(dialog)
|
||||
{
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
const bool sorting_enabled = sif->GetBoolValue("Cheats", "SortList", false);
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_codes_model = new QStandardItemModel(this);
|
||||
m_sort_model = new QSortFilterProxyModel(m_codes_model);
|
||||
m_sort_model->setSourceModel(m_codes_model);
|
||||
m_sort_model->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_sort_model->setRecursiveFilteringEnabled(true);
|
||||
m_sort_model->setAutoAcceptChildRows(true);
|
||||
m_sort_model->sort(sorting_enabled ? 0 : -1, Qt::AscendingOrder);
|
||||
m_ui.cheatList->setModel(m_sort_model);
|
||||
m_ui.cheatList->setItemDelegate(new CheatListOptionDelegate(this, m_ui.cheatList));
|
||||
|
||||
reloadList();
|
||||
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
|
||||
// We don't use the binder here, because they're binary - either enabled, or not in the file.
|
||||
m_ui.enableCheats->setChecked(sif->GetBoolValue("Cheats", "EnableCheats", false));
|
||||
m_ui.loadDatabaseCheats->setChecked(sif->GetBoolValue("Cheats", "LoadCheatsFromDatabase", true));
|
||||
m_ui.sortCheats->setChecked(sorting_enabled);
|
||||
|
||||
connect(m_ui.enableCheats, &QCheckBox::checkStateChanged, this, &GameCheatSettingsWidget::onEnableCheatsChanged);
|
||||
connect(m_ui.sortCheats, &QPushButton::toggled, this, &GameCheatSettingsWidget::onSortCheatsToggled);
|
||||
connect(m_ui.search, &QLineEdit::textChanged, this, &GameCheatSettingsWidget::onSearchFilterChanged);
|
||||
connect(m_ui.loadDatabaseCheats, &QCheckBox::checkStateChanged, this,
|
||||
&GameCheatSettingsWidget::onLoadDatabaseCheatsChanged);
|
||||
connect(m_ui.cheatList, &QTreeWidget::itemDoubleClicked, this,
|
||||
&GameCheatSettingsWidget::onCheatListItemDoubleClicked);
|
||||
connect(m_ui.cheatList, &QTreeWidget::customContextMenuRequested, this,
|
||||
connect(m_ui.cheatList, &QTreeView::doubleClicked, this, &GameCheatSettingsWidget::onCheatListItemDoubleClicked);
|
||||
connect(m_ui.cheatList, &QTreeView::customContextMenuRequested, this,
|
||||
&GameCheatSettingsWidget::onCheatListContextMenuRequested);
|
||||
connect(m_ui.cheatList, &QTreeWidget::itemChanged, this, &GameCheatSettingsWidget::onCheatListItemChanged);
|
||||
connect(m_codes_model, &QStandardItemModel::itemChanged, this, &GameCheatSettingsWidget::onCheatListItemChanged);
|
||||
connect(m_ui.add, &QToolButton::clicked, this, &GameCheatSettingsWidget::newCode);
|
||||
connect(m_ui.remove, &QToolButton::clicked, this, &GameCheatSettingsWidget::onRemoveCodeClicked);
|
||||
connect(m_ui.disableAll, &QToolButton::clicked, this, &GameCheatSettingsWidget::disableAllCheats);
|
||||
@ -255,6 +270,27 @@ void GameCheatSettingsWidget::onEnableCheatsChanged(Qt::CheckState state)
|
||||
m_dialog->saveAndReloadGameSettings();
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::onSortCheatsToggled(bool checked)
|
||||
{
|
||||
m_sort_model->sort(checked ? 0 : -1, Qt::AscendingOrder);
|
||||
|
||||
if (checked)
|
||||
m_dialog->getSettingsInterface()->SetBoolValue("Cheats", "SortList", true);
|
||||
else
|
||||
m_dialog->getSettingsInterface()->DeleteValue("Cheats", "SortList");
|
||||
|
||||
m_dialog->saveAndReloadGameSettings();
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::onSearchFilterChanged(const QString& text)
|
||||
{
|
||||
m_sort_model->setFilterFixedString(text);
|
||||
|
||||
// if we're clearing search, re-expand everything, since sorting collapses them
|
||||
if (text.isEmpty())
|
||||
expandAllItems();
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::onLoadDatabaseCheatsChanged(Qt::CheckState state)
|
||||
{
|
||||
// Default is enabled.
|
||||
@ -266,25 +302,33 @@ void GameCheatSettingsWidget::onLoadDatabaseCheatsChanged(Qt::CheckState state)
|
||||
reloadList();
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::onCheatListItemDoubleClicked(QTreeWidgetItem* item, int column)
|
||||
void GameCheatSettingsWidget::onCheatListItemDoubleClicked(const QModelIndex& index)
|
||||
{
|
||||
const QVariant item_data = item->data(0, Qt::UserRole);
|
||||
const QModelIndex col0 = m_sort_model->mapToSource(index.siblingAtColumn(0));
|
||||
if (!col0.isValid())
|
||||
return;
|
||||
|
||||
const QStandardItem* item = m_codes_model->itemFromIndex(col0);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
const QVariant item_data = item->data(Qt::UserRole);
|
||||
if (!item_data.isValid())
|
||||
return;
|
||||
|
||||
editCode(item_data.toString().toStdString());
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::onCheatListItemChanged(QTreeWidgetItem* item, int column)
|
||||
void GameCheatSettingsWidget::onCheatListItemChanged(QStandardItem* item)
|
||||
{
|
||||
const QVariant item_data = item->data(0, Qt::UserRole);
|
||||
const QVariant item_data = item->data(Qt::UserRole);
|
||||
if (!item_data.isValid())
|
||||
return;
|
||||
|
||||
std::string cheat_name = item_data.toString().toStdString();
|
||||
const bool current_enabled =
|
||||
(std::find(m_enabled_codes.begin(), m_enabled_codes.end(), cheat_name) != m_enabled_codes.end());
|
||||
const bool current_checked = (item->checkState(0) == Qt::Checked);
|
||||
const bool current_checked = (item->checkState() == Qt::Checked);
|
||||
if (current_enabled == current_checked)
|
||||
return;
|
||||
|
||||
@ -369,11 +413,15 @@ void GameCheatSettingsWidget::checkForMasterDisable()
|
||||
|
||||
Cheats::CodeInfo* GameCheatSettingsWidget::getSelectedCode()
|
||||
{
|
||||
const QList<QTreeWidgetItem*> selected = m_ui.cheatList->selectedItems();
|
||||
const QList<QModelIndex> selected = m_ui.cheatList->selectionModel()->selectedRows();
|
||||
if (selected.size() != 1)
|
||||
return nullptr;
|
||||
|
||||
const QVariant item_data = selected[0]->data(0, Qt::UserRole);
|
||||
const QStandardItem* item = m_codes_model->itemFromIndex(m_sort_model->mapToSource(selected[0]));
|
||||
if (!item)
|
||||
return nullptr;
|
||||
|
||||
const QVariant item_data = item->data(Qt::UserRole);
|
||||
if (!item_data.isValid())
|
||||
return nullptr;
|
||||
|
||||
@ -415,43 +463,47 @@ void GameCheatSettingsWidget::setCheatEnabled(std::string name, bool enabled, bo
|
||||
|
||||
void GameCheatSettingsWidget::setStateForAll(bool enabled)
|
||||
{
|
||||
QSignalBlocker sb(m_ui.cheatList);
|
||||
setStateRecursively(nullptr, enabled);
|
||||
setStateRecursively(m_codes_model->invisibleRootItem(), enabled);
|
||||
m_dialog->saveAndReloadGameSettings();
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::setStateRecursively(QTreeWidgetItem* parent, bool enabled)
|
||||
void GameCheatSettingsWidget::setStateRecursively(QStandardItem* parent, bool enabled)
|
||||
{
|
||||
const int count = parent ? parent->childCount() : m_ui.cheatList->topLevelItemCount();
|
||||
const int count = parent->rowCount();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
QTreeWidgetItem* item = parent ? parent->child(i) : m_ui.cheatList->topLevelItem(i);
|
||||
const QVariant item_data = item->data(0, Qt::UserRole);
|
||||
QStandardItem* child = parent->child(i);
|
||||
if (child->hasChildren())
|
||||
{
|
||||
setStateRecursively(child, enabled);
|
||||
continue;
|
||||
}
|
||||
|
||||
// found a code to toggle
|
||||
const QVariant item_data = child->data(Qt::UserRole);
|
||||
if (item_data.isValid())
|
||||
{
|
||||
if ((item->checkState(0) == Qt::Checked) != enabled)
|
||||
if ((child->checkState() == Qt::Checked) != enabled)
|
||||
{
|
||||
item->setCheckState(0, enabled ? Qt::Checked : Qt::Unchecked);
|
||||
// set state first, so the signal doesn't change it
|
||||
// can't use a signal blocker here, because otherwise the view doesn't update
|
||||
setCheatEnabled(item_data.toString().toStdString(), enabled, false);
|
||||
child->setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setStateRecursively(item, enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::reloadList()
|
||||
{
|
||||
// Show all hashes, since the ini is shared.
|
||||
m_codes = Cheats::GetCodeInfoList(m_dialog->getGameSerial(), std::nullopt, true, shouldLoadFromDatabase(), true);
|
||||
m_codes = Cheats::GetCodeInfoList(m_dialog->getGameSerial(), std::nullopt, true, shouldLoadFromDatabase(), false);
|
||||
m_enabled_codes =
|
||||
m_dialog->getSettingsInterface()->GetStringList(Cheats::CHEATS_CONFIG_SECTION, Cheats::PATCH_ENABLE_CONFIG_KEY);
|
||||
|
||||
m_parent_map.clear();
|
||||
while (m_ui.cheatList->topLevelItemCount() > 0)
|
||||
delete m_ui.cheatList->takeTopLevelItem(0);
|
||||
m_codes_model->clear();
|
||||
m_codes_model->invisibleRootItem()->setColumnCount(2);
|
||||
|
||||
for (const Cheats::CodeInfo& ci : m_codes)
|
||||
{
|
||||
@ -459,17 +511,21 @@ void GameCheatSettingsWidget::reloadList()
|
||||
|
||||
const std::string_view parent_part = ci.GetNameParentPart();
|
||||
|
||||
QTreeWidgetItem* parent = getTreeWidgetParent(parent_part);
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
populateTreeWidgetItem(item, ci, enabled);
|
||||
if (parent)
|
||||
parent->addChild(item);
|
||||
else
|
||||
m_ui.cheatList->addTopLevelItem(item);
|
||||
QStandardItem* parent = getTreeWidgetParent(parent_part);
|
||||
populateTreeWidgetItem(parent, ci, enabled);
|
||||
}
|
||||
|
||||
// Hide root indicator when there's no groups, frees up some whitespace.
|
||||
m_ui.cheatList->setRootIsDecorated(!m_parent_map.empty());
|
||||
|
||||
// Expand all items.
|
||||
expandAllItems();
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::expandAllItems()
|
||||
{
|
||||
for (const auto& it : m_parent_map)
|
||||
m_ui.cheatList->setExpanded(m_sort_model->mapFromSource(it.second->index()), true);
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::onImportClicked()
|
||||
@ -630,17 +686,17 @@ void GameCheatSettingsWidget::onClearClicked()
|
||||
reloadList();
|
||||
}
|
||||
|
||||
QTreeWidgetItem* GameCheatSettingsWidget::getTreeWidgetParent(const std::string_view parent)
|
||||
QStandardItem* GameCheatSettingsWidget::getTreeWidgetParent(const std::string_view parent)
|
||||
{
|
||||
if (parent.empty())
|
||||
return nullptr;
|
||||
return m_codes_model->invisibleRootItem();
|
||||
|
||||
auto it = m_parent_map.find(parent);
|
||||
if (it != m_parent_map.end())
|
||||
return it->second;
|
||||
|
||||
std::string_view this_part = parent;
|
||||
QTreeWidgetItem* parent_to_this = nullptr;
|
||||
QStandardItem* parent_to_this = nullptr;
|
||||
const std::string_view::size_type pos = parent.rfind('\\');
|
||||
if (pos != std::string::npos && pos != (parent.size() - 1))
|
||||
{
|
||||
@ -648,45 +704,63 @@ QTreeWidgetItem* GameCheatSettingsWidget::getTreeWidgetParent(const std::string_
|
||||
parent_to_this = getTreeWidgetParent(parent.substr(0, pos));
|
||||
this_part = parent.substr(pos + 1);
|
||||
}
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0, QString::fromUtf8(this_part.data(), this_part.length()));
|
||||
|
||||
if (parent_to_this)
|
||||
parent_to_this->addChild(item);
|
||||
else
|
||||
m_ui.cheatList->addTopLevelItem(item);
|
||||
{
|
||||
parent_to_this = m_codes_model->invisibleRootItem();
|
||||
}
|
||||
|
||||
QStandardItem* item = new QStandardItem();
|
||||
item->setText(QString::fromUtf8(this_part.data(), this_part.length()));
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
parent_to_this->appendRow(item);
|
||||
|
||||
// Must be called after adding.
|
||||
item->setExpanded(true);
|
||||
m_parent_map.emplace(parent, item);
|
||||
return item;
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::populateTreeWidgetItem(QTreeWidgetItem* item, const Cheats::CodeInfo& pi, bool enabled)
|
||||
void GameCheatSettingsWidget::populateTreeWidgetItem(QStandardItem* parent, const Cheats::CodeInfo& pi, bool enabled)
|
||||
{
|
||||
const std::string_view name_part = pi.GetNamePart();
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemNeverHasChildren);
|
||||
item->setCheckState(0, enabled ? Qt::Checked : Qt::Unchecked);
|
||||
item->setData(0, Qt::UserRole, QString::fromStdString(pi.name));
|
||||
if (!pi.description.empty())
|
||||
item->setToolTip(0, QString::fromStdString(pi.description));
|
||||
if (!name_part.empty())
|
||||
item->setText(0, QtUtils::StringViewToQString(name_part));
|
||||
QStandardItem* label = new QStandardItem();
|
||||
label->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemNeverHasChildren);
|
||||
label->setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
|
||||
label->setData(QString::fromStdString(pi.name), Qt::UserRole);
|
||||
|
||||
if (pi.HasOptionChoices())
|
||||
// Why?
|
||||
|
||||
if (!pi.description.empty())
|
||||
label->setToolTip(QString::fromStdString(pi.description));
|
||||
if (!name_part.empty())
|
||||
label->setText(QtUtils::StringViewToQString(name_part));
|
||||
|
||||
const int index = parent->rowCount();
|
||||
parent->appendRow(label);
|
||||
|
||||
if (pi.HasOptionChoices() || pi.HasOptionRange())
|
||||
{
|
||||
// need to resolve the value back to a name
|
||||
const std::string_view option_name =
|
||||
pi.MapOptionValueToName(m_dialog->getSettingsInterface()->GetTinyStringValue("Cheats", pi.name.c_str()));
|
||||
item->setData(1, Qt::UserRole, QtUtils::StringViewToQString(option_name));
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
}
|
||||
else if (pi.HasOptionRange())
|
||||
{
|
||||
const u32 value = m_dialog->getSettingsInterface()->GetUIntValue("Cheats", pi.name.c_str(), pi.option_range_start);
|
||||
item->setData(1, Qt::UserRole, static_cast<uint>(value));
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
QStandardItem* value_col = new QStandardItem();
|
||||
value_col->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
|
||||
|
||||
if (pi.HasOptionChoices())
|
||||
{
|
||||
// need to resolve the value back to a name
|
||||
const std::string_view option_name =
|
||||
pi.MapOptionValueToName(m_dialog->getSettingsInterface()->GetTinyStringValue("Cheats", pi.name.c_str()));
|
||||
value_col->setData(QtUtils::StringViewToQString(option_name), Qt::UserRole);
|
||||
}
|
||||
else if (pi.HasOptionRange())
|
||||
{
|
||||
const u32 value =
|
||||
m_dialog->getSettingsInterface()->GetUIntValue("Cheats", pi.name.c_str(), pi.option_range_start);
|
||||
value_col->setData(static_cast<uint>(value), Qt::UserRole);
|
||||
}
|
||||
|
||||
parent->setChild(index, 1, value_col);
|
||||
|
||||
// Why are we doing this on the label item? Qt seems to return these oddball QStandardItem values
|
||||
// for columns that don't exist that have all flags set, so we can't use it in the drawing delegate
|
||||
// to determine whether the label should span the entire width or not.
|
||||
label->setData(true, Qt::UserRole + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,9 @@ struct Entry;
|
||||
|
||||
class SettingsWindow;
|
||||
|
||||
class QStandardItem;
|
||||
class QStandardItemModel;
|
||||
|
||||
class GameCheatSettingsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -45,9 +48,11 @@ protected:
|
||||
|
||||
private Q_SLOTS:
|
||||
void onEnableCheatsChanged(Qt::CheckState state);
|
||||
void onSortCheatsToggled(bool checked);
|
||||
void onSearchFilterChanged(const QString& text);
|
||||
void onLoadDatabaseCheatsChanged(Qt::CheckState state);
|
||||
void onCheatListItemDoubleClicked(QTreeWidgetItem* item, int column);
|
||||
void onCheatListItemChanged(QTreeWidgetItem* item, int column);
|
||||
void onCheatListItemDoubleClicked(const QModelIndex& index);
|
||||
void onCheatListItemChanged(QStandardItem* item);
|
||||
void onCheatListContextMenuRequested(const QPoint& pos);
|
||||
void onRemoveCodeClicked();
|
||||
void onReloadClicked();
|
||||
@ -63,11 +68,13 @@ private:
|
||||
void checkForMasterDisable();
|
||||
|
||||
Cheats::CodeInfo* getSelectedCode();
|
||||
QTreeWidgetItem* getTreeWidgetParent(const std::string_view parent);
|
||||
void populateTreeWidgetItem(QTreeWidgetItem* item, const Cheats::CodeInfo& pi, bool enabled);
|
||||
QStandardItem* getTreeWidgetParent(const std::string_view parent);
|
||||
void populateTreeWidgetItem(QStandardItem* parent, const Cheats::CodeInfo& pi, bool enabled);
|
||||
void expandAllItems();
|
||||
|
||||
void setCheatEnabled(std::string name, bool enabled, bool save_and_reload_settings);
|
||||
void setStateForAll(bool enabled);
|
||||
void setStateRecursively(QTreeWidgetItem* parent, bool enabled);
|
||||
void setStateRecursively(QStandardItem* parent, bool enabled);
|
||||
void importCodes(const std::string& file_contents);
|
||||
void newCode();
|
||||
void editCode(const std::string_view code_name);
|
||||
@ -76,8 +83,10 @@ private:
|
||||
Ui::GameCheatSettingsWidget m_ui;
|
||||
SettingsWindow* m_dialog;
|
||||
|
||||
UnorderedStringMap<QTreeWidgetItem*> m_parent_map;
|
||||
UnorderedStringMap<QStandardItem*> m_parent_map;
|
||||
Cheats::CodeInfoList m_codes;
|
||||
QStandardItemModel* m_codes_model;
|
||||
QSortFilterProxyModel* m_sort_model;
|
||||
std::vector<std::string> m_enabled_codes;
|
||||
|
||||
bool m_master_enable_ignored = false;
|
||||
|
@ -24,7 +24,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0,0,0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0,0,0,0,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableCheats">
|
||||
<property name="text">
|
||||
@ -32,6 +32,35 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Search...</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="sortCheats">
|
||||
<property name="toolTip">
|
||||
<string>Reload Cheats</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="sort-alphabet-asc"/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="add">
|
||||
<property name="sizePolicy">
|
||||
@ -93,7 +122,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="cheatList">
|
||||
<widget class="QTreeView" name="cheatList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ContextMenuPolicy::CustomContextMenu</enum>
|
||||
</property>
|
||||
@ -112,16 +141,9 @@
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -101,6 +101,7 @@
|
||||
<file>icons/black/svg/screenshot-2-line.svg</file>
|
||||
<file>icons/black/svg/settings-3-line.svg</file>
|
||||
<file>icons/black/svg/shut-down-line.svg</file>
|
||||
<file>icons/black/svg/sort-alphabet-asc.svg</file>
|
||||
<file>icons/black/svg/sparkle-fill.svg</file>
|
||||
<file>icons/black/svg/sparkling-line.svg</file>
|
||||
<file>icons/black/svg/sun-fill.svg</file>
|
||||
@ -319,6 +320,7 @@
|
||||
<file>icons/white/svg/screenshot-2-line.svg</file>
|
||||
<file>icons/white/svg/settings-3-line.svg</file>
|
||||
<file>icons/white/svg/shut-down-line.svg</file>
|
||||
<file>icons/white/svg/sort-alphabet-asc.svg</file>
|
||||
<file>icons/white/svg/sparkle-fill.svg</file>
|
||||
<file>icons/white/svg/sparkling-line.svg</file>
|
||||
<file>icons/white/svg/sun-fill.svg</file>
|
||||
|
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000"><path d="M4.86885 11H2.6665L6 3H8L11.3334 11H9.13113L8.7213 10H5.27869L4.86885 11ZM6.09836 8H7.90163L7 5.8L6.09836 8ZM18.9999 16V3H16.9999V16H13.9999L17.9999 21L21.9999 16H18.9999ZM10.9999 13H2.99992V15H7.85414L2.99992 19V21H10.9999V19H6.14605L10.9999 15V13Z"></path></svg>
|
After Width: | Height: | Size: 348 B |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ffffff"><path d="M4.86885 11H2.6665L6 3H8L11.3334 11H9.13113L8.7213 10H5.27869L4.86885 11ZM6.09836 8H7.90163L7 5.8L6.09836 8ZM18.9999 16V3H16.9999V16H13.9999L17.9999 21L21.9999 16H18.9999ZM10.9999 13H2.99992V15H7.85414L2.99992 19V21H10.9999V19H6.14605L10.9999 15V13Z"></path></svg>
|
After Width: | Height: | Size: 348 B |
Loading…
x
Reference in New Issue
Block a user