mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-08 20:58:41 +00:00
Log presets feature (#3509)
* Log presets feature - Add “Load Presets…” button in Logger → Log Filter (settings_dialog.ui) - Implement LogPresetsDialog (table: Comment, Filter) - Support add (+), multi-remove (−), load via button or double-click - Persist presets via QSettings at logger_presets/entries (qt_ui.ini) - Wire button to open dialog and set logFilterLineEdit - Update CMakeLists.txt to include new dialog sources * CLang fix * CLang fix again * Log Presets: checkbox selection + tri-state header - Added first column with per-row checkboxes - Implemented header checkbox with tri-state; click toggles select-all/none - Synced checkboxes and row selection in both directions - Header toggle also updates row selection to match - Remove operates on checked rows; falls back to selected rows if none checked - Load uses first checked row; falls back to first selected row - Double-click row triggers the same action as Load - Load button visible only when exactly one row is selected - Remove button visible only when at least one row is selected - Dialog opens with no selected rows and no focused buttons; focus set to table - New rows start editing in the Comment column - Serialization updated for new column indices; checkbox state not persisted - Cleanups: removed unused include and empty helper; pruned temporary comments * Clang * Fix: tri‑state header checkbox visible and aligned - Overlay real QCheckBox in header section 0 (tri‑state) - Align with row checkboxes using SE_ItemViewItemCheckIndicator - Reposition on header resize and geometry changes - Header click + checkbox click toggle select‑all/none - Tri‑state reflects per‑row checkbox states * CLang --------- Co-authored-by: w1naenator <valdis.bogdans@hotmail.com>
This commit is contained in:
@@ -1098,6 +1098,8 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
||||
src/qt_gui/kbm_help_dialog.h
|
||||
src/qt_gui/main_window_themes.cpp
|
||||
src/qt_gui/main_window_themes.h
|
||||
src/qt_gui/log_presets_dialog.cpp
|
||||
src/qt_gui/log_presets_dialog.h
|
||||
src/qt_gui/settings_dialog.cpp
|
||||
src/qt_gui/settings_dialog.h
|
||||
src/qt_gui/settings_dialog.ui
|
||||
|
||||
414
src/qt_gui/log_presets_dialog.cpp
Normal file
414
src/qt_gui/log_presets_dialog.cpp
Normal file
@@ -0,0 +1,414 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "log_presets_dialog.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QItemSelection>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QPushButton>
|
||||
#include <QSet>
|
||||
#include <QSignalBlocker>
|
||||
#include <QStyleOptionViewItem>
|
||||
#include <QTableWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace {
|
||||
constexpr const char* kPresetsGroup = "logger_presets";
|
||||
constexpr const char* kPresetsKey = "entries";
|
||||
|
||||
inline QString MakeEntry(const QString& comment, const QString& filter) {
|
||||
return comment + "\t" + filter;
|
||||
}
|
||||
|
||||
inline void SplitEntry(const QString& entry, QString& comment, QString& filter) {
|
||||
const int idx = entry.indexOf('\t');
|
||||
if (idx < 0) {
|
||||
comment = entry;
|
||||
filter = QString();
|
||||
} else {
|
||||
comment = entry.left(idx);
|
||||
filter = entry.mid(idx + 1);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
LogPresetsDialog::LogPresetsDialog(std::shared_ptr<gui_settings> gui_settings, QWidget* parent)
|
||||
: QDialog(parent), m_gui_settings(std::move(gui_settings)) {
|
||||
setWindowTitle(tr("Log Filter Presets"));
|
||||
resize(640, 360);
|
||||
|
||||
auto* root = new QVBoxLayout(this);
|
||||
|
||||
m_table = new QTableWidget(this);
|
||||
m_table->setColumnCount(3);
|
||||
m_table->horizontalHeader()->setSectionsClickable(true);
|
||||
m_table->horizontalHeader()->setHighlightSections(false);
|
||||
QStringList headers;
|
||||
headers << QString() << tr("Comment") << tr("Filter");
|
||||
m_table->setHorizontalHeaderLabels(headers);
|
||||
m_table->horizontalHeader()->setStretchLastSection(true);
|
||||
m_table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
|
||||
m_table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Interactive);
|
||||
m_table->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeMode::Stretch);
|
||||
m_table->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows);
|
||||
m_table->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
|
||||
m_table->setEditTriggers(QAbstractItemView::EditTrigger::DoubleClicked |
|
||||
QAbstractItemView::EditTrigger::SelectedClicked |
|
||||
QAbstractItemView::EditTrigger::EditKeyPressed);
|
||||
|
||||
connect(m_table, &QTableWidget::cellDoubleClicked, this,
|
||||
[this](int /*row*/, int /*col*/) { LoadSelected(); });
|
||||
|
||||
connect(m_table, &QTableWidget::itemChanged, this, [this](QTableWidgetItem* item) {
|
||||
if (m_updating_checks)
|
||||
return;
|
||||
if (item && item->column() == 0) {
|
||||
m_updating_checks = true;
|
||||
const int row = item->row();
|
||||
auto* sm = m_table->selectionModel();
|
||||
const auto idx = m_table->model()->index(row, 0);
|
||||
const bool check = (item->checkState() == Qt::Checked);
|
||||
sm->select(idx, (check ? QItemSelectionModel::Select : QItemSelectionModel::Deselect) |
|
||||
QItemSelectionModel::Rows);
|
||||
m_updating_checks = false;
|
||||
UpdateHeaderCheckState();
|
||||
UpdateLoadButtonEnabled();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_table->selectionModel(), &QItemSelectionModel::selectionChanged, this,
|
||||
[this](const QItemSelection& selected, const QItemSelection& deselected) {
|
||||
if (m_updating_checks)
|
||||
return;
|
||||
m_updating_checks = true;
|
||||
QSet<int> selRows;
|
||||
for (const auto& idx : selected.indexes())
|
||||
selRows.insert(idx.row());
|
||||
QSet<int> deselRows;
|
||||
for (const auto& idx : deselected.indexes())
|
||||
deselRows.insert(idx.row());
|
||||
for (int r : selRows) {
|
||||
auto* it = m_table->item(r, 0);
|
||||
if (!it) {
|
||||
it = new QTableWidgetItem();
|
||||
it->setFlags((QTableWidgetItem().flags() | Qt::ItemIsUserCheckable) &
|
||||
~Qt::ItemIsEditable);
|
||||
m_table->setItem(r, 0, it);
|
||||
}
|
||||
it->setCheckState(Qt::Checked);
|
||||
}
|
||||
for (int r : deselRows) {
|
||||
auto* it = m_table->item(r, 0);
|
||||
if (it)
|
||||
it->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
m_updating_checks = false;
|
||||
UpdateHeaderCheckState();
|
||||
UpdateLoadButtonEnabled();
|
||||
});
|
||||
|
||||
connect(m_table->horizontalHeader(), &QHeaderView::sectionClicked, this, [this](int section) {
|
||||
if (section != 0)
|
||||
return;
|
||||
const auto next = (m_header_checkbox && m_header_checkbox->checkState() == Qt::Checked)
|
||||
? Qt::Unchecked
|
||||
: Qt::Checked;
|
||||
if (m_header_checkbox)
|
||||
m_header_checkbox->setCheckState(next);
|
||||
SetAllCheckStates(next);
|
||||
UpdateHeaderCheckState();
|
||||
UpdateLoadButtonEnabled();
|
||||
});
|
||||
|
||||
m_header_checkbox = new QCheckBox(m_table->horizontalHeader());
|
||||
m_header_checkbox->setTristate(true);
|
||||
m_header_checkbox->setText(QString());
|
||||
m_header_checkbox->setFocusPolicy(Qt::NoFocus);
|
||||
PositionHeaderCheckbox();
|
||||
QObject::connect(m_table->horizontalHeader(), &QHeaderView::geometriesChanged, this,
|
||||
[this]() { PositionHeaderCheckbox(); });
|
||||
QObject::connect(m_table->horizontalHeader(), &QHeaderView::sectionResized, this,
|
||||
[this](int, int, int) { PositionHeaderCheckbox(); });
|
||||
QObject::connect(m_header_checkbox, &QCheckBox::clicked, this, [this](bool checked) {
|
||||
SetAllCheckStates(checked ? Qt::Checked : Qt::Unchecked);
|
||||
UpdateHeaderCheckState();
|
||||
UpdateLoadButtonEnabled();
|
||||
});
|
||||
|
||||
root->addWidget(m_table);
|
||||
|
||||
auto* buttons_layout = new QHBoxLayout();
|
||||
m_add_btn = new QPushButton(tr("+"), this);
|
||||
m_remove_btn = new QPushButton(tr("-"), this);
|
||||
m_load_btn = new QPushButton(tr("Load"), this);
|
||||
m_close_btn = new QPushButton(tr("Close"), this);
|
||||
|
||||
m_add_btn->setToolTip(tr("Add a new preset after the selected row"));
|
||||
m_remove_btn->setToolTip(tr("Remove selected presets"));
|
||||
m_load_btn->setToolTip(tr("Load the selected preset"));
|
||||
|
||||
buttons_layout->addWidget(m_add_btn);
|
||||
buttons_layout->addWidget(m_remove_btn);
|
||||
buttons_layout->addStretch();
|
||||
buttons_layout->addWidget(m_load_btn);
|
||||
buttons_layout->addWidget(m_close_btn);
|
||||
root->addLayout(buttons_layout);
|
||||
|
||||
m_add_btn->setAutoDefault(false);
|
||||
m_remove_btn->setAutoDefault(false);
|
||||
m_load_btn->setAutoDefault(false);
|
||||
m_close_btn->setAutoDefault(false);
|
||||
m_add_btn->setDefault(false);
|
||||
m_remove_btn->setDefault(false);
|
||||
m_load_btn->setDefault(false);
|
||||
m_close_btn->setDefault(false);
|
||||
|
||||
connect(m_add_btn, &QPushButton::clicked, this, [this]() { AddAfterSelection(); });
|
||||
connect(m_remove_btn, &QPushButton::clicked, this, [this]() { RemoveSelected(); });
|
||||
connect(m_load_btn, &QPushButton::clicked, this, [this]() { LoadSelected(); });
|
||||
connect(m_close_btn, &QPushButton::clicked, this, [this]() { reject(); });
|
||||
|
||||
LoadFromSettings();
|
||||
m_updating_checks = true;
|
||||
m_table->clearSelection();
|
||||
m_table->setCurrentItem(nullptr);
|
||||
m_updating_checks = false;
|
||||
m_table->setFocus(Qt::OtherFocusReason);
|
||||
UpdateLoadButtonEnabled();
|
||||
}
|
||||
|
||||
void LogPresetsDialog::accept() {
|
||||
SaveToSettings();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void LogPresetsDialog::reject() {
|
||||
SaveToSettings();
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void LogPresetsDialog::LoadFromSettings() {
|
||||
if (!m_gui_settings)
|
||||
return;
|
||||
const auto var = m_gui_settings->GetValue(kPresetsGroup, kPresetsKey, QVariant());
|
||||
QList<QString> list;
|
||||
if (var.isValid()) {
|
||||
list = m_gui_settings->Var2List(var);
|
||||
}
|
||||
PopulateFromList(list);
|
||||
}
|
||||
|
||||
void LogPresetsDialog::SaveToSettings() {
|
||||
if (!m_gui_settings)
|
||||
return;
|
||||
const auto list = SerializeTable();
|
||||
m_gui_settings->SetValue(kPresetsGroup, kPresetsKey, m_gui_settings->List2Var(list));
|
||||
}
|
||||
|
||||
QList<QString> LogPresetsDialog::SerializeTable() const {
|
||||
QList<QString> list;
|
||||
const int rows = m_table->rowCount();
|
||||
for (int r = 0; r < rows; ++r) {
|
||||
const auto* comment = m_table->item(r, 1);
|
||||
const auto* filter = m_table->item(r, 2);
|
||||
const QString c = comment ? comment->text() : QString();
|
||||
const QString f = filter ? filter->text() : QString();
|
||||
if (!c.isEmpty() || !f.isEmpty()) {
|
||||
list.push_back(MakeEntry(c, f));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void LogPresetsDialog::PopulateFromList(const QList<QString>& list) {
|
||||
m_table->setRowCount(0);
|
||||
for (const auto& entry : list) {
|
||||
QString c, f;
|
||||
SplitEntry(entry, c, f);
|
||||
const int row = m_table->rowCount();
|
||||
m_table->insertRow(row);
|
||||
auto* chk = new QTableWidgetItem();
|
||||
chk->setFlags((chk->flags() | Qt::ItemIsUserCheckable) & ~Qt::ItemIsEditable);
|
||||
chk->setCheckState(Qt::Unchecked);
|
||||
m_table->setItem(row, 0, chk);
|
||||
|
||||
m_table->setItem(row, 1, new QTableWidgetItem(c));
|
||||
m_table->setItem(row, 2, new QTableWidgetItem(f));
|
||||
}
|
||||
m_updating_checks = true;
|
||||
m_table->clearSelection();
|
||||
m_table->setCurrentItem(nullptr);
|
||||
m_updating_checks = false;
|
||||
UpdateHeaderCheckState();
|
||||
UpdateLoadButtonEnabled();
|
||||
}
|
||||
|
||||
void LogPresetsDialog::AddAfterSelection() {
|
||||
int insert_row = m_table->rowCount();
|
||||
const auto selected = m_table->selectionModel()->selectedRows();
|
||||
if (!selected.isEmpty()) {
|
||||
// place after the last selected row
|
||||
insert_row = selected.last().row() + 1;
|
||||
}
|
||||
m_table->insertRow(insert_row);
|
||||
auto* chk = new QTableWidgetItem();
|
||||
chk->setFlags((chk->flags() | Qt::ItemIsUserCheckable) & ~Qt::ItemIsEditable);
|
||||
chk->setCheckState(Qt::Unchecked);
|
||||
m_table->setItem(insert_row, 0, chk);
|
||||
m_table->setItem(insert_row, 1, new QTableWidgetItem(""));
|
||||
m_table->setItem(insert_row, 2, new QTableWidgetItem(""));
|
||||
UpdateHeaderCheckState();
|
||||
m_table->setCurrentCell(insert_row, 1);
|
||||
m_table->editItem(m_table->item(insert_row, 1));
|
||||
UpdateLoadButtonEnabled();
|
||||
}
|
||||
|
||||
void LogPresetsDialog::RemoveSelected() {
|
||||
// Prefer checked rows; fall back to selected rows if none checked
|
||||
QList<int> to_remove = GetCheckedRows();
|
||||
if (to_remove.isEmpty()) {
|
||||
const auto selected = m_table->selectionModel()->selectedRows();
|
||||
for (const auto& idx : selected)
|
||||
to_remove.push_back(idx.row());
|
||||
}
|
||||
if (to_remove.isEmpty())
|
||||
return;
|
||||
std::sort(to_remove.begin(), to_remove.end(), [](int a, int b) { return a > b; });
|
||||
for (int row : to_remove)
|
||||
m_table->removeRow(row);
|
||||
UpdateHeaderCheckState();
|
||||
UpdateLoadButtonEnabled();
|
||||
}
|
||||
|
||||
void LogPresetsDialog::LoadSelected() {
|
||||
QList<int> rows = GetCheckedRows();
|
||||
if (rows.isEmpty()) {
|
||||
const auto selected = m_table->selectionModel()->selectedRows();
|
||||
if (selected.isEmpty())
|
||||
return;
|
||||
rows.push_back(selected.first().row());
|
||||
}
|
||||
const int row = rows.first();
|
||||
const auto* item = m_table->item(row, 2);
|
||||
if (item) {
|
||||
emit PresetChosen(item->text());
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
void LogPresetsDialog::UpdateHeaderCheckState() {
|
||||
const int rows = m_table->rowCount();
|
||||
if (rows == 0) {
|
||||
if (m_header_checkbox)
|
||||
m_header_checkbox->setCheckState(Qt::Unchecked);
|
||||
return;
|
||||
}
|
||||
int checked = 0;
|
||||
for (int r = 0; r < rows; ++r) {
|
||||
auto* it = m_table->item(r, 0);
|
||||
if (it && it->checkState() == Qt::Checked)
|
||||
++checked;
|
||||
}
|
||||
const auto state = (checked == 0) ? Qt::Unchecked
|
||||
: (checked == rows) ? Qt::Checked
|
||||
: Qt::PartiallyChecked;
|
||||
if (m_header_checkbox)
|
||||
m_header_checkbox->setCheckState(state);
|
||||
}
|
||||
|
||||
void LogPresetsDialog::SetAllCheckStates(Qt::CheckState state) {
|
||||
const QSignalBlocker blocker(m_table);
|
||||
m_updating_checks = true;
|
||||
const int rows = m_table->rowCount();
|
||||
auto* sm = m_table->selectionModel();
|
||||
for (int r = 0; r < rows; ++r) {
|
||||
auto* it = m_table->item(r, 0);
|
||||
if (!it) {
|
||||
it = new QTableWidgetItem();
|
||||
it->setFlags((QTableWidgetItem().flags() | Qt::ItemIsUserCheckable) &
|
||||
~Qt::ItemIsEditable);
|
||||
m_table->setItem(r, 0, it);
|
||||
}
|
||||
it->setCheckState(state);
|
||||
const auto idx = m_table->model()->index(r, 0);
|
||||
sm->select(idx, ((state == Qt::Checked) ? QItemSelectionModel::Select
|
||||
: QItemSelectionModel::Deselect) |
|
||||
QItemSelectionModel::Rows);
|
||||
}
|
||||
m_updating_checks = false;
|
||||
}
|
||||
|
||||
QList<int> LogPresetsDialog::GetCheckedRows() const {
|
||||
QList<int> rows;
|
||||
const int count = m_table->rowCount();
|
||||
for (int r = 0; r < count; ++r) {
|
||||
const auto* it = m_table->item(r, 0);
|
||||
if (it && it->checkState() == Qt::Checked)
|
||||
rows.push_back(r);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
void LogPresetsDialog::UpdateLoadButtonEnabled() {
|
||||
if (!m_table || !m_table->selectionModel())
|
||||
return;
|
||||
const int count = m_table->selectionModel()->selectedRows().size();
|
||||
|
||||
if (m_load_btn) {
|
||||
const bool showLoad = (count == 1);
|
||||
m_load_btn->setVisible(showLoad);
|
||||
m_load_btn->setEnabled(showLoad);
|
||||
}
|
||||
|
||||
if (m_remove_btn) {
|
||||
const bool showRemove = (count >= 1);
|
||||
m_remove_btn->setVisible(showRemove);
|
||||
m_remove_btn->setEnabled(showRemove);
|
||||
}
|
||||
}
|
||||
|
||||
void LogPresetsDialog::PositionHeaderCheckbox() {
|
||||
if (!m_header_checkbox)
|
||||
return;
|
||||
auto* hdr = m_table->horizontalHeader();
|
||||
const int section = 0;
|
||||
const int x = hdr->sectionViewportPosition(section);
|
||||
const int w = hdr->sectionSize(section);
|
||||
const int h = hdr->height();
|
||||
const QSize sz = m_header_checkbox->sizeHint();
|
||||
|
||||
// Try to align horizontally with cell checkbox indicator for this column
|
||||
int left_in_section = 0;
|
||||
if (m_table->model()->rowCount() > 0) {
|
||||
QStyleOptionViewItem opt;
|
||||
opt.initFrom(m_table);
|
||||
opt.features = QStyleOptionViewItem::HasCheckIndicator;
|
||||
// Use a representative cell rect width (section width) and a typical row height
|
||||
const int cell_h = m_table->rowHeight(0) > 0 ? m_table->rowHeight(0) : sz.height();
|
||||
opt.rect = QRect(0, 0, w, cell_h);
|
||||
const QRect ind =
|
||||
m_table->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, m_table);
|
||||
left_in_section = ind.left();
|
||||
// Guard against styles that return empty rects
|
||||
if (ind.isEmpty()) {
|
||||
left_in_section =
|
||||
m_table->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, m_table);
|
||||
}
|
||||
} else {
|
||||
left_in_section =
|
||||
m_table->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, m_table);
|
||||
}
|
||||
|
||||
int cx = x + left_in_section;
|
||||
// Center vertically in header
|
||||
const int cy = (h - sz.height()) / 2;
|
||||
// Ensure checkbox fully visible within the section bounds
|
||||
if (cx + sz.width() > x + w)
|
||||
cx = x + std::max(0, w - sz.width());
|
||||
m_header_checkbox->setGeometry(QRect(QPoint(cx, cy), sz));
|
||||
m_header_checkbox->show();
|
||||
}
|
||||
54
src/qt_gui/log_presets_dialog.h
Normal file
54
src/qt_gui/log_presets_dialog.h
Normal file
@@ -0,0 +1,54 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QPointer>
|
||||
class QTableWidget;
|
||||
class QPushButton;
|
||||
class QTableWidgetItem;
|
||||
class QCheckBox;
|
||||
|
||||
#include "gui_settings.h"
|
||||
|
||||
class LogPresetsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogPresetsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
QWidget* parent = nullptr);
|
||||
~LogPresetsDialog() override = default;
|
||||
|
||||
signals:
|
||||
void PresetChosen(const QString& filter);
|
||||
|
||||
protected:
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
|
||||
private:
|
||||
void LoadFromSettings();
|
||||
void SaveToSettings();
|
||||
void AddAfterSelection();
|
||||
void RemoveSelected();
|
||||
void LoadSelected();
|
||||
void UpdateHeaderCheckState();
|
||||
void SetAllCheckStates(Qt::CheckState state);
|
||||
QList<int> GetCheckedRows() const;
|
||||
void UpdateLoadButtonEnabled();
|
||||
void PositionHeaderCheckbox();
|
||||
|
||||
QList<QString> SerializeTable() const;
|
||||
void PopulateFromList(const QList<QString>& list);
|
||||
|
||||
private:
|
||||
std::shared_ptr<gui_settings> m_gui_settings;
|
||||
QTableWidget* m_table = nullptr;
|
||||
QCheckBox* m_header_checkbox = nullptr;
|
||||
QPushButton* m_add_btn = nullptr;
|
||||
QPushButton* m_remove_btn = nullptr;
|
||||
QPushButton* m_load_btn = nullptr;
|
||||
QPushButton* m_close_btn = nullptr;
|
||||
bool m_updating_checks = false;
|
||||
};
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "background_music_player.h"
|
||||
#include "common/logging/backend.h"
|
||||
#include "common/logging/filter.h"
|
||||
#include "log_presets_dialog.h"
|
||||
#include "settings_dialog.h"
|
||||
#include "ui_settings_dialog.h"
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
@@ -386,6 +387,14 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
Common::FS::GetUserPath(Common::FS::PathType::LogDir));
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(userPath));
|
||||
});
|
||||
|
||||
// Log presets popup button
|
||||
connect(ui->logPresetsButton, &QPushButton::clicked, this, [this]() {
|
||||
auto dlg = new LogPresetsDialog(m_gui_settings, this);
|
||||
connect(dlg, &LogPresetsDialog::PresetChosen, this,
|
||||
[this](const QString& filter) { ui->logFilterLineEdit->setText(filter); });
|
||||
dlg->exec();
|
||||
});
|
||||
}
|
||||
|
||||
// GRAPHICS TAB
|
||||
|
||||
@@ -2217,6 +2217,13 @@
|
||||
<item>
|
||||
<widget class="QLineEdit" name="logFilterLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="logPresetsButton">
|
||||
<property name="text">
|
||||
<string>Load Presets...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user