From 530fbdd2821a18dd6ca69d98fdfdcc1ce9b47b0d Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 26 Apr 2024 21:48:51 +0200 Subject: [PATCH] Add ResourceTable class Base class to be used to display items in a table --- CMakeLists.txt | 4 + lib/utils/resource-table-hotkey-handler.cpp | 70 +++++++++ lib/utils/resource-table-hotkey-handler.hpp | 37 +++++ lib/utils/resource-table.cpp | 157 ++++++++++++++++++++ lib/utils/resource-table.hpp | 50 +++++++ 5 files changed, 318 insertions(+) create mode 100644 lib/utils/resource-table-hotkey-handler.cpp create mode 100644 lib/utils/resource-table-hotkey-handler.hpp create mode 100644 lib/utils/resource-table.cpp create mode 100644 lib/utils/resource-table.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a71c2052..130492ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,10 @@ target_sources( lib/utils/regex-config.hpp lib/utils/resizing-text-edit.cpp lib/utils/resizing-text-edit.hpp + lib/utils/resource-table.cpp + lib/utils/resource-table.hpp + lib/utils/resource-table-hotkey-handler.cpp + lib/utils/resource-table-hotkey-handler.hpp lib/utils/scene-selection.cpp lib/utils/scene-selection.hpp lib/utils/scene-switch-helpers.cpp diff --git a/lib/utils/resource-table-hotkey-handler.cpp b/lib/utils/resource-table-hotkey-handler.cpp new file mode 100644 index 00000000..edfd2e32 --- /dev/null +++ b/lib/utils/resource-table-hotkey-handler.cpp @@ -0,0 +1,70 @@ +#include "resource-table-hotkey-handler.hpp" + +#include +#include +#include + +namespace advss { + +void RegisterHotkeyFunction(QWidget *widget, Qt::Key key, + std::function func) +{ + ResourceTabHotkeyHandler::Instance()->RegisterHandler(widget, key, + func); +} + +void DeregisterHotkeyFunctions(QWidget *widget) +{ + ResourceTabHotkeyHandler::Instance()->Deregister(widget); +} + +ResourceTabHotkeyHandler *ResourceTabHotkeyHandler::Instance() +{ + static ResourceTabHotkeyHandler handler; + return &handler; +} + +void ResourceTabHotkeyHandler::RegisterHandler(QWidget *widget, Qt::Key key, + std::function func) +{ + std::lock_guard lock(_mutex); + _callbacks.emplace(widget, CallbackData{key, func}); + widget->installEventFilter(this); +} + +void ResourceTabHotkeyHandler::Deregister(QWidget *widget) +{ + std::lock_guard lock(_mutex); + _callbacks.erase(widget); +} + +bool ResourceTabHotkeyHandler::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() != QEvent::KeyPress) { + return QObject::eventFilter(obj, event); + } + QKeyEvent *keyEvent = static_cast(event); + auto pressedKey = keyEvent->key(); + + std::lock_guard lock(_mutex); + auto it = _callbacks.find(obj); + if (it == _callbacks.end()) { + return QObject::eventFilter(obj, event); + } + + auto current = it; + while (current != _callbacks.end() && current->first == it->first) { + auto &[_, cbData] = *current; + if (pressedKey != cbData.key) { + ++current; + continue; + } + cbData.func(); + ++current; + continue; + } + + return QObject::eventFilter(obj, event); +} + +} // namespace advss diff --git a/lib/utils/resource-table-hotkey-handler.hpp b/lib/utils/resource-table-hotkey-handler.hpp new file mode 100644 index 00000000..7aa2b18e --- /dev/null +++ b/lib/utils/resource-table-hotkey-handler.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "export-symbol-helper.hpp" + +#include +#include +#include +#include + +namespace advss { + +EXPORT void RegisterHotkeyFunction(QWidget *, Qt::Key, + std::function func); +EXPORT void DeregisterHotkeyFunctions(QWidget *); + +class ResourceTabHotkeyHandler : public QObject { + Q_OBJECT +public: + static ResourceTabHotkeyHandler *Instance(); + void RegisterHandler(QWidget *, Qt::Key, std::function func); + void Deregister(QWidget *); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +private: + struct CallbackData { + Qt::Key key; + std::function func; + }; + + ResourceTabHotkeyHandler() : QObject(){}; + + std::multimap _callbacks; + std::mutex _mutex; +}; + +} // namespace advss diff --git a/lib/utils/resource-table.cpp b/lib/utils/resource-table.cpp new file mode 100644 index 00000000..e531c877 --- /dev/null +++ b/lib/utils/resource-table.cpp @@ -0,0 +1,157 @@ +#include "resource-table.hpp" +#include "plugin-state-helpers.hpp" +#include "resource-table-hotkey-handler.hpp" +#include "ui-helpers.hpp" + +#include +#include + +namespace advss { + +ResourceTable::ResourceTable(QTabWidget *parent, const QString &help, + const QString &addToolTip, + const QString &removeToolTip, + const QStringList &headers, + const std::function &openSettings) + : QWidget(parent), + _table(new QTableWidget()), + _add(new QPushButton()), + _remove(new QPushButton()), + _help(new QLabel(help)) +{ + _add->setMaximumWidth(22); + _add->setProperty("themeID", + QVariant(QString::fromUtf8("addIconSmall"))); + _add->setFlat(true); + _add->setToolTip(addToolTip); + + _remove->setMaximumWidth(22); + _remove->setProperty("themeID", + QVariant(QString::fromUtf8("removeIconSmall"))); + _remove->setFlat(true); + _remove->setToolTip(removeToolTip); + + _help->setWordWrap(true); + _help->setAlignment(Qt::AlignCenter); + + _table->setColumnCount(headers.size()); + _table->horizontalHeader()->setSectionResizeMode( + QHeaderView::ResizeMode::Interactive); + _table->setHorizontalHeaderLabels(headers); + _table->verticalHeader()->hide(); + _table->setCornerButtonEnabled(false); + _table->setShowGrid(false); + _table->setEditTriggers(QAbstractItemView::NoEditTriggers); + _table->setSelectionBehavior(QAbstractItemView::SelectRows); + + auto helpAndTableLayout = new QGridLayout(); + helpAndTableLayout->setContentsMargins(0, 0, 0, 0); + helpAndTableLayout->addWidget(_table, 0, 0); + helpAndTableLayout->addWidget(_help, 0, 0, Qt::AlignCenter); + + auto controlLayout = new QHBoxLayout; + controlLayout->setContentsMargins(0, 0, 0, 0); + controlLayout->addWidget(_add); + controlLayout->addWidget(_remove); + controlLayout->addStretch(); + + auto layout = new QVBoxLayout(); + layout->addLayout(helpAndTableLayout); + layout->addLayout(controlLayout); + setLayout(layout); + + QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add())); + QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove())); + QWidget::connect(_table, &QTableWidget::cellDoubleClicked, + [openSettings]() { openSettings(); }); + + RegisterHotkeyFunction(this, Qt::Key_F2, openSettings); + RegisterHotkeyFunction(this, Qt::Key_Delete, [this]() { Remove(); }); +} + +ResourceTable::~ResourceTable() +{ + DeregisterHotkeyFunctions(this); +} + +void ResourceTable::SetHelpVisible(bool visible) const +{ + _help->setVisible(visible); +} + +void ResourceTable::HighlightAddButton(bool enable) +{ + _add->disconnect(_highlightConnection); + if (enable && HighlightUIElementsEnabled()) { + _highlightConnection = PulseWidget(_add, QColor(Qt::green)); + } +} + +void ResourceTable::resizeEvent(QResizeEvent *) +{ + const auto columnCount = _table->columnCount(); + const auto columnSize = (_table->width() - 1) / columnCount; + for (int i = 0; i < columnCount; ++i) { + _table->horizontalHeader()->resizeSection(i, columnSize); + } +} + +void AddItemTableRow(QTableWidget *table, const QStringList &cellLabels) +{ + int row = table->rowCount(); + table->setRowCount(row + 1); + + int col = 0; + for (const auto &cellLabel : cellLabels) { + auto *item = new QTableWidgetItem(cellLabel); + item->setToolTip(cellLabel); + table->setItem(row, col, item); + col++; + } + + table->sortByColumn(0, Qt::AscendingOrder); +} + +void UpdateItemTableRow(QTableWidget *table, int row, + const QStringList &cellLabels) +{ + int col = 1; // Skip the name cell + for (const auto &cellLabel : cellLabels) { + auto item = table->item(row, col); + item->setText(cellLabel); + item->setToolTip(cellLabel); + col++; + } +} + +void RenameItemTableRow(QTableWidget *table, const QString &oldName, + const QString &newName) +{ + for (int row = 0; row < table->rowCount(); row++) { + auto item = table->item(row, 0); + if (!item) { + continue; + } + + if (item->text() == oldName) { + item->setText(newName); + table->sortByColumn(0, Qt::AscendingOrder); + return; + } + } + assert(false); +} + +void RemoveItemTableRow(QTableWidget *table, const QString &name) +{ + for (int row = 0; row < table->rowCount(); ++row) { + auto item = table->item(row, 0); + if (item && item->text() == name) { + table->removeRow(row); + return; + } + } + table->sortByColumn(0, Qt::AscendingOrder); +} + +} // namespace advss diff --git a/lib/utils/resource-table.hpp b/lib/utils/resource-table.hpp new file mode 100644 index 00000000..c081a7a2 --- /dev/null +++ b/lib/utils/resource-table.hpp @@ -0,0 +1,50 @@ +#pragma once +#include "export-symbol-helper.hpp" + +#include +#include +#include +#include + +class QResizeEvent; + +namespace advss { + +class ADVSS_EXPORT ResourceTable : public QWidget { + Q_OBJECT + +public: + ResourceTable(QTabWidget *parent, const QString &help, + const QString &addToolTip, const QString &removeToolTip, + const QStringList &headers, + const std::function &openSettings); + virtual ~ResourceTable(); + + QTableWidget *Table() const { return _table; } + void SetHelpVisible(bool) const; + void HighlightAddButton(bool); + +protected slots: + virtual void Add() {} + virtual void Remove() {} + +protected: + void resizeEvent(QResizeEvent *event); + +private: + QTableWidget *_table; + QPushButton *_add; + QPushButton *_remove; + QLabel *_help; + + QMetaObject::Connection _highlightConnection; +}; + +EXPORT void AddItemTableRow(QTableWidget *table, const QStringList &cells); +EXPORT void UpdateItemTableRow(QTableWidget *table, int row, + const QStringList &cells); +EXPORT void RenameItemTableRow(QTableWidget *table, const QString &oldName, + const QString &newName); +EXPORT void RemoveItemTableRow(QTableWidget *table, const QString &name); + +} // namespace advss