From d0f483b634b37fad5b4e9b6b40bcb3133b99df92 Mon Sep 17 00:00:00 2001 From: WarmUpTill <19472752+WarmUpTill@users.noreply.github.com> Date: Mon, 19 Oct 2026 18:26:51 +0200 Subject: [PATCH] Show variable usage count on variable tab --- CMakeLists.txt | 2 + data/locale/en-US.ini | 5 ++ lib/variables/variable-tab.cpp | 83 +++++++++++++++++++++++++++++++- lib/variables/variable-tab.hpp | 5 ++ lib/variables/variable-usage.cpp | 35 ++++++++++++++ lib/variables/variable-usage.hpp | 15 ++++++ 6 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 lib/variables/variable-usage.cpp create mode 100644 lib/variables/variable-usage.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 862e2a71..5284252c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,6 +331,8 @@ target_sources( lib/variables/variable-tab.hpp lib/variables/variable-text-edit.cpp lib/variables/variable-text-edit.hpp + lib/variables/variable-usage.cpp + lib/variables/variable-usage.hpp lib/variables/variable.cpp lib/variables/variable.hpp) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 217f5d1c..438abf7a 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -103,6 +103,11 @@ AdvSceneSwitcher.variableTab.lastUsed.text.never="Never" AdvSceneSwitcher.variableTab.lastChanged.header="Last changed" AdvSceneSwitcher.variableTab.lastChanged.text.none="No change since launch" AdvSceneSwitcher.variableTab.lastChanged.tooltip="Times changed: %1\n\nPrevious value: %2" +AdvSceneSwitcher.variableTab.usage.header="Used by" +AdvSceneSwitcher.variableTab.usage.text.none="Not used" +AdvSceneSwitcher.variableTab.usage.text.single="1 macro" +AdvSceneSwitcher.variableTab.usage.text.multiple="%1 macros" +AdvSceneSwitcher.variableTab.usage.tooltip="References: %1\n\nMacros:\n%2" AdvSceneSwitcher.variableTab.search.placeholder="Search ..." AdvSceneSwitcher.variableTab.search.all="All columns" AdvSceneSwitcher.variableTab.search.name="Name column" diff --git a/lib/variables/variable-tab.cpp b/lib/variables/variable-tab.cpp index 1e5face5..29b500dc 100644 --- a/lib/variables/variable-tab.cpp +++ b/lib/variables/variable-tab.cpp @@ -6,6 +6,7 @@ #include "tab-helpers.hpp" #include "time-helpers.hpp" #include "ui-helpers.hpp" +#include "variable-usage.hpp" #include "variable.hpp" #include @@ -218,6 +219,62 @@ static void updateVariableStatus(QTableWidget *table) } } +static constexpr int usageColumn = 5; + +static QString formatUsageText(const VariableUsage &usage) +{ + if (usage.macroNames.size() == 1) { + return obs_module_text( + "AdvSceneSwitcher.variableTab.usage.text.single"); + } + + return QString(obs_module_text( + "AdvSceneSwitcher.variableTab.usage.text.multiple")) + .arg(usage.macroNames.size()); +} + +static QString formatUsageTooltip(const VariableUsage &usage) +{ + QStringList macroNames; + for (const auto &name : usage.macroNames) { + macroNames << QString::fromStdString(name); + } + macroNames.sort(); + + return QString(obs_module_text( + "AdvSceneSwitcher.variableTab.usage.tooltip")) + .arg(usage.referenceCount) + .arg(macroNames.join("\n")); +} + +static void updateVariableUsage(QTableWidget *table) +{ + const auto usage = GetVariableUsage(); + for (int row = 0; row < table->rowCount(); row++) { + auto nameItem = table->item(row, 0); + if (!nameItem) { + continue; + } + + auto item = table->item(row, usageColumn); + if (!item) { + item = new QTableWidgetItem(); + table->setItem(row, usageColumn, item); + } + + const auto it = usage.find(nameItem->text().toStdString()); + if (it == usage.end()) { + item->setText(obs_module_text( + "AdvSceneSwitcher.variableTab.usage.text.none")); + item->setToolTip(""); + continue; + } + + item->setText(formatUsageText(it->second)); + item->setToolTip(formatUsageTooltip(it->second)); + } +} + static void openSettingsDialog(VariableTable *table) { auto selectedRows = table->Table()->selectionModel()->selectedRows(); @@ -350,7 +407,9 @@ VariableTable::VariableTable(Settings &settings, QWidget *parent) << obs_module_text( "AdvSceneSwitcher.variableTab.lastUsed.header") << obs_module_text( - "AdvSceneSwitcher.variableTab.lastChanged.header"), + "AdvSceneSwitcher.variableTab.lastChanged.header") + << obs_module_text( + "AdvSceneSwitcher.variableTab.usage.header"), [this]() { openSettingsDialog(this); }), _searchField(new QLineEdit(this)), _clear(new QPushButton(this)), @@ -424,6 +483,7 @@ VariableTable::VariableTable(Settings &settings, QWidget *parent) [this](const QString &oldName, const QString &newName) { RenameItemTableRow(Table(), oldName, newName); + UpdateUsage(); }); QWidget::connect( VariableSignalManager::Instance(), &VariableSignalManager::Add, @@ -433,6 +493,7 @@ VariableTable::VariableTable(Settings &settings, QWidget *parent) getCellLabels(GetVariableByQString(name))); SetHelpVisible(false); HighlightAddButton(false); + UpdateUsage(); }); QWidget::connect(VariableSignalManager::Instance(), &VariableSignalManager::Remove, this, @@ -450,6 +511,15 @@ VariableTable::VariableTable(Settings &settings, QWidget *parent) [this]() { updateVariableStatus(Table()); }); timer->start(); + auto usageTimer = new QTimer(this); + usageTimer->setInterval(5000); + QWidget::connect(usageTimer, &QTimer::timeout, [this]() { + if (isVisible()) { + UpdateUsage(); + } + }); + usageTimer->start(); + auto searchLayout = new QHBoxLayout(); searchLayout->addWidget(_searchField); searchLayout->addWidget(_clear); @@ -461,6 +531,17 @@ VariableTable::VariableTable(Settings &settings, QWidget *parent) SetHelpVisible(GetVariables().empty()); } +void VariableTable::UpdateUsage() +{ + updateVariableUsage(Table()); +} + +void VariableTable::showEvent(QShowEvent *event) +{ + ResourceTable::showEvent(event); + UpdateUsage(); +} + static void setupTab(QTabWidget *tab) { if (GetVariables().empty()) { diff --git a/lib/variables/variable-tab.hpp b/lib/variables/variable-tab.hpp index 068b8614..01a111f2 100644 --- a/lib/variables/variable-tab.hpp +++ b/lib/variables/variable-tab.hpp @@ -25,12 +25,17 @@ public: static VariableTable *CreateTabTable(); void HideDockOptions() const; +protected: + void showEvent(QShowEvent *event) override; + private slots: void Add(); void Remove(); void Filter(); private: + void UpdateUsage(); + QLineEdit *_searchField; QPushButton *_clear; QComboBox *_searchType; diff --git a/lib/variables/variable-usage.cpp b/lib/variables/variable-usage.cpp new file mode 100644 index 00000000..a353630b --- /dev/null +++ b/lib/variables/variable-usage.cpp @@ -0,0 +1,35 @@ +#include "variable-usage.hpp" +#include "macro-helpers.hpp" +#include "macro.hpp" +#include "sync-helpers.hpp" +#include "variable-ref.hpp" + +#include + +namespace advss { + +static std::unordered_map collectReferences(Macro *macro) +{ + VariableRefCollector collector; + OBSDataAutoRelease data = obs_data_create(); + macro->Save(data); + return collector.Counts(); +} + +std::unordered_map GetVariableUsage() +{ + std::unordered_map result; + auto lock = LockContext(); + // Nested macros are saved as part of their parent macro + for (const auto ¯o : GetTopLevelMacros()) { + for (const auto &[name, count] : + collectReferences(macro.get())) { + auto &usage = result[name]; + usage.referenceCount += count; + usage.macroNames.emplace_back(macro->Name()); + } + } + return result; +} + +} // namespace advss diff --git a/lib/variables/variable-usage.hpp b/lib/variables/variable-usage.hpp new file mode 100644 index 00000000..4847e231 --- /dev/null +++ b/lib/variables/variable-usage.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include +#include + +namespace advss { + +struct VariableUsage { + int referenceCount = 0; + std::vector macroNames; +}; + +std::unordered_map GetVariableUsage(); + +} // namespace advss