diff --git a/frontend/components/VolumeControl.cpp b/frontend/components/VolumeControl.cpp index 9579676b9..3b5349024 100644 --- a/frontend/components/VolumeControl.cpp +++ b/frontend/components/VolumeControl.cpp @@ -51,8 +51,6 @@ VolumeControl::VolumeControl(obs_source_t *source, QWidget *parent, bool vertica contextMenu(nullptr), QFrame(parent) { - utils = std::make_unique(this); - uuid = obs_source_get_uuid(source); mainLayout = new QBoxLayout(QBoxLayout::LeftToRight, this); @@ -62,21 +60,21 @@ VolumeControl::VolumeControl(obs_source_t *source, QWidget *parent, bool vertica categoryLabel = new QLabel("Active"); categoryLabel->setAlignment(Qt::AlignCenter); - utils->addClass(categoryLabel, "mixer-category"); - utils->addClass(categoryLabel, "text-tiny"); + idian::Utils::addClass(categoryLabel, "mixer-category"); + idian::Utils::addClass(categoryLabel, "text-tiny"); nameButton = new VolumeName(source, this); nameButton->setMaximumWidth(280); - utils->addClass(nameButton, "text-small"); - utils->addClass(nameButton, "mixer-name"); + idian::Utils::addClass(nameButton, "text-small"); + idian::Utils::addClass(nameButton, "mixer-name"); muteButton = new QPushButton(this); muteButton->setCheckable(true); - utils->addClass(muteButton, "btn-mute"); + idian::Utils::addClass(muteButton, "btn-mute"); monitorButton = new QPushButton(this); monitorButton->setCheckable(true); - utils->addClass(monitorButton, "btn-monitor"); + idian::Utils::addClass(monitorButton, "btn-monitor"); volumeLabel = new QLabel(this); volumeLabel->setIndent(0); @@ -89,8 +87,8 @@ VolumeControl::VolumeControl(obs_source_t *source, QWidget *parent, bool vertica sourceName = obs_source_get_name(source); setObjectName(sourceName); - utils->applyStateStylingEventFilter(muteButton); - utils->applyStateStylingEventFilter(monitorButton); + idian::Utils::applyStateStylingEventFilter(muteButton); + idian::Utils::applyStateStylingEventFilter(monitorButton); volumeMeter = new VolumeMeter(this, source); @@ -641,11 +639,11 @@ void VolumeControl::updateCategoryLabel() bool styleUnassigned = mixerStatus().has(VolumeControl::MixerStatus::Unassigned); bool stylePreviewed = mixerStatus().has(VolumeControl::MixerStatus::Preview); - utils->toggleClass("volume-pinned", stylePinned); - utils->toggleClass("volume-inactive", styleInactive); - utils->toggleClass("volume-preview", styleInactive && stylePreviewed); - utils->toggleClass("volume-hidden", styleHidden && !stylePinned); - utils->toggleClass("volume-unassigned", styleUnassigned); + idian::Utils::toggleClass(this, "volume-pinned", stylePinned); + idian::Utils::toggleClass(this, "volume-inactive", styleInactive); + idian::Utils::toggleClass(this, "volume-preview", styleInactive && stylePreviewed); + idian::Utils::toggleClass(this, "volume-hidden", styleHidden && !stylePinned); + idian::Utils::toggleClass(this, "volume-unassigned", styleUnassigned); categoryLabel->setText(labelText); categoryLabel->setAlignment(Qt::AlignCenter); @@ -803,10 +801,10 @@ void VolumeControl::processMixerState() // Qt doesn't support overriding the QPushButton icon using pseudo state selectors like :checked // in QSS so we set a checked class selector on the button to be used instead. - utils->toggleClass(muteButton, "checked", showAsMuted); - utils->toggleClass(monitorButton, "checked", showAsMonitored); + idian::Utils::toggleClass(muteButton, "checked", showAsMuted); + idian::Utils::toggleClass(monitorButton, "checked", showAsMonitored); - utils->toggleClass(muteButton, "mute-warning", showWarningIcon); + idian::Utils::toggleClass(muteButton, "mute-warning", showWarningIcon); style()->polish(muteButton); style()->polish(monitorButton); diff --git a/frontend/components/VolumeControl.hpp b/frontend/components/VolumeControl.hpp index d1cf8dfbe..a4c60faa2 100644 --- a/frontend/components/VolumeControl.hpp +++ b/frontend/components/VolumeControl.hpp @@ -66,8 +66,6 @@ public: }; private: - std::unique_ptr utils; - OBSWeakSource weakSource_; const char *uuid; std::vector obsSignals; diff --git a/shared/qt/idian/components/CheckBox.cpp b/shared/qt/idian/components/CheckBox.cpp index 89484539a..9cb8e70b9 100644 --- a/shared/qt/idian/components/CheckBox.cpp +++ b/shared/qt/idian/components/CheckBox.cpp @@ -21,7 +21,7 @@ using idian::CheckBox; -CheckBox::CheckBox(QWidget *parent) : QCheckBox(parent), Utils(this) +CheckBox::CheckBox(QWidget *parent) : QCheckBox(parent) { Utils::applyStateStylingEventFilter(this); } diff --git a/shared/qt/idian/components/ComboBox.cpp b/shared/qt/idian/components/ComboBox.cpp index d8117f311..126311d24 100644 --- a/shared/qt/idian/components/ComboBox.cpp +++ b/shared/qt/idian/components/ComboBox.cpp @@ -25,7 +25,7 @@ using idian::ComboBox; -ComboBox::ComboBox(QWidget *parent) : QComboBox(parent), Utils(this) +ComboBox::ComboBox(QWidget *parent) : QComboBox(parent) { Utils::applyStateStylingEventFilter(this); } diff --git a/shared/qt/idian/components/InlineButton.cpp b/shared/qt/idian/components/InlineButton.cpp index 733732f5f..900f18521 100644 --- a/shared/qt/idian/components/InlineButton.cpp +++ b/shared/qt/idian/components/InlineButton.cpp @@ -18,7 +18,7 @@ #include namespace idian { -InlineButton::InlineButton(QWidget *parent) : QPushButton(parent), Utils(this) +InlineButton::InlineButton(QWidget *parent) : QPushButton(parent) { Utils::applyStateStylingEventFilter(this); } diff --git a/shared/qt/idian/components/ToggleSwitch.cpp b/shared/qt/idian/components/ToggleSwitch.cpp index 042ad1921..773928051 100644 --- a/shared/qt/idian/components/ToggleSwitch.cpp +++ b/shared/qt/idian/components/ToggleSwitch.cpp @@ -35,8 +35,7 @@ QColor blendColors(const QColor &color1, const QColor &color2, float ratio) ToggleSwitch::ToggleSwitch(QWidget *parent) : QAbstractButton(parent), animHandle(new QPropertyAnimation(this, "xpos", this)), - animBgColor(new QPropertyAnimation(this, "blend", this)), - Utils(this) + animBgColor(new QPropertyAnimation(this, "blend", this)) { Utils::applyStateStylingEventFilter(this); @@ -104,7 +103,7 @@ void ToggleSwitch::updateBackgroundColor() void ToggleSwitch::changeEvent(QEvent *event) { if (event->type() == QEvent::EnabledChange) { - Utils::toggleClass("disabled", !isEnabled()); + Utils::toggleClass(this, "disabled", !isEnabled()); updateBackgroundColor(); } } diff --git a/shared/qt/idian/include/Idian/CheckBox.hpp b/shared/qt/idian/include/Idian/CheckBox.hpp index ac3f6f0fe..d37bb8381 100644 --- a/shared/qt/idian/include/Idian/CheckBox.hpp +++ b/shared/qt/idian/include/Idian/CheckBox.hpp @@ -23,7 +23,7 @@ namespace idian { -class CheckBox : public QCheckBox, public Utils { +class CheckBox : public QCheckBox { Q_OBJECT; public: diff --git a/shared/qt/idian/include/Idian/ComboBox.hpp b/shared/qt/idian/include/Idian/ComboBox.hpp index 74b20068e..d8ae0f2f2 100644 --- a/shared/qt/idian/include/Idian/ComboBox.hpp +++ b/shared/qt/idian/include/Idian/ComboBox.hpp @@ -24,7 +24,7 @@ namespace idian { -class ComboBox : public QComboBox, public Utils { +class ComboBox : public QComboBox { Q_OBJECT public: diff --git a/shared/qt/idian/include/Idian/InlineButton.hpp b/shared/qt/idian/include/Idian/InlineButton.hpp index 034cc3c48..13287d102 100644 --- a/shared/qt/idian/include/Idian/InlineButton.hpp +++ b/shared/qt/idian/include/Idian/InlineButton.hpp @@ -26,7 +26,7 @@ class QPixmap; namespace idian { class Utils; -class InlineButton : public QPushButton, public Utils { +class InlineButton : public QPushButton { Q_OBJECT public: diff --git a/shared/qt/idian/include/Idian/Row.hpp b/shared/qt/idian/include/Idian/Row.hpp index 845b736d4..16b2b406e 100644 --- a/shared/qt/idian/include/Idian/Row.hpp +++ b/shared/qt/idian/include/Idian/Row.hpp @@ -35,7 +35,7 @@ class RowList; class RowInfo; // Row widget containing one or more controls -class Row : public QFrame, public Utils { +class Row : public QFrame { Q_OBJECT public: diff --git a/shared/qt/idian/include/Idian/StateEventFilter.cpp b/shared/qt/idian/include/Idian/StateEventFilter.cpp index be7820a29..4ac41214f 100644 --- a/shared/qt/idian/include/Idian/StateEventFilter.cpp +++ b/shared/qt/idian/include/Idian/StateEventFilter.cpp @@ -23,7 +23,7 @@ #include namespace idian { -StateEventFilter::StateEventFilter(idian::Utils *utils, QWidget *target) : QObject(target), target(target), utils(utils) +StateEventFilter::StateEventFilter(QWidget *target) : QObject(target), target(target) { QAbstractButton *button = qobject_cast(target); if (button) { @@ -45,54 +45,54 @@ bool StateEventFilter::eventFilter(QObject *obj, QEvent *event) switch (event->type()) { case QEvent::StyleChange: case QEvent::ThemeChange: - utils->repolish(widget); + Utils::repolish(widget); - utils->polishChildren(widget); + Utils::polishChildren(widget); break; case QEvent::FocusIn: - utils->toggleClass(widget, "focus", true); + Utils::toggleClass(widget, "focus", true); focusEvent = static_cast(event); if (focusEvent->reason() != Qt::MouseFocusReason && focusEvent->reason() != Qt::PopupFocusReason) { - utils->toggleClass(widget, "keyFocus", true); + Utils::toggleClass(widget, "keyFocus", true); } else { - utils->toggleClass(widget, "keyFocus", false); + Utils::toggleClass(widget, "keyFocus", false); } - utils->polishChildren(widget); + Utils::polishChildren(widget); break; case QEvent::FocusOut: - utils->toggleClass(widget, "focus", false); + Utils::toggleClass(widget, "focus", false); focusEvent = static_cast(event); if (focusEvent->reason() != Qt::PopupFocusReason) { - utils->toggleClass(widget, "keyFocus", false); - utils->polishChildren(widget); + Utils::toggleClass(widget, "keyFocus", false); + Utils::polishChildren(widget); } - utils->polishChildren(widget); + Utils::polishChildren(widget); break; case QEvent::HoverEnter: if (widget->isEnabled()) { - utils->toggleClass(widget, "hover", true); + Utils::toggleClass(widget, "hover", true); } - utils->polishChildren(widget); + Utils::polishChildren(widget); break; case QEvent::HoverLeave: - utils->toggleClass(widget, "hover", false); + Utils::toggleClass(widget, "hover", false); - utils->polishChildren(widget); + Utils::polishChildren(widget); break; case QEvent::EnabledChange: - utils->toggleClass(widget, "disabled", !widget->isEnabled()); + Utils::toggleClass(widget, "disabled", !widget->isEnabled()); - utils->polishChildren(widget); + Utils::polishChildren(widget); break; default: @@ -104,10 +104,10 @@ bool StateEventFilter::eventFilter(QObject *obj, QEvent *event) // Delay icon update if (QLabel *label = qobject_cast(widget)) { QMetaObject::invokeMethod( - this, [this, label]() { utils->applyColorToIcon(label); }, Qt::QueuedConnection); + this, [this, label]() { Utils::applyColorToIcon(label); }, Qt::QueuedConnection); } else if (QAbstractButton *button = qobject_cast(widget)) { QMetaObject::invokeMethod( - this, [this, button]() { utils->applyColorToIcon(button); }, Qt::QueuedConnection); + this, [this, button]() { Utils::applyColorToIcon(button); }, Qt::QueuedConnection); } } @@ -116,7 +116,7 @@ bool StateEventFilter::eventFilter(QObject *obj, QEvent *event) void StateEventFilter::updateCheckedState(bool checked) { - utils->toggleClass(target, "checked", checked); + Utils::toggleClass(target, "checked", checked); } } // namespace idian diff --git a/shared/qt/idian/include/Idian/StateEventFilter.hpp b/shared/qt/idian/include/Idian/StateEventFilter.hpp index 9d62c168a..1c5d2854f 100644 --- a/shared/qt/idian/include/Idian/StateEventFilter.hpp +++ b/shared/qt/idian/include/Idian/StateEventFilter.hpp @@ -27,7 +27,7 @@ class StateEventFilter : public QObject { Q_OBJECT public: - explicit StateEventFilter(idian::Utils *utils, QWidget *parent); + explicit StateEventFilter(QWidget *parent); bool eventFilter(QObject *obj, QEvent *event); @@ -35,7 +35,6 @@ public slots: void updateCheckedState(bool checked); private: - Utils *utils; QWidget *target; }; } // namespace idian diff --git a/shared/qt/idian/include/Idian/ToggleSwitch.hpp b/shared/qt/idian/include/Idian/ToggleSwitch.hpp index 150204ed9..c7b604584 100644 --- a/shared/qt/idian/include/Idian/ToggleSwitch.hpp +++ b/shared/qt/idian/include/Idian/ToggleSwitch.hpp @@ -31,7 +31,7 @@ namespace idian { -class ToggleSwitch : public QAbstractButton, public Utils { +class ToggleSwitch : public QAbstractButton { Q_OBJECT Q_PROPERTY(int xpos MEMBER xPos WRITE setPos) Q_PROPERTY(QColor background MEMBER backgroundInactive DESIGNABLE true) diff --git a/shared/qt/idian/include/Idian/Utils.cpp b/shared/qt/idian/include/Idian/Utils.cpp index b2cd3eb8a..c4fc12559 100644 --- a/shared/qt/idian/include/Idian/Utils.cpp +++ b/shared/qt/idian/include/Idian/Utils.cpp @@ -26,6 +26,76 @@ #include namespace idian { +void Utils::polishChildren(QWidget *widget) +{ + for (QWidget *child : widget->findChildren()) { + repolish(child); + } +} + +void Utils::repolish(QWidget *widget) +{ + widget->style()->polish(widget); +} + +void Utils::addClass(QWidget *widget, const QString &classname) +{ + if (!classNameIsValid(classname)) { + return; + } + + QVariant current = widget->property("class"); + + QStringList classList = current.toString().split(" "); + if (classList.contains(classname)) { + return; + } + + classList.removeDuplicates(); + classList.removeAll(""); + classList.append(classname); + + QString newClasses = classList.isEmpty() ? "" : classList.join(" "); + widget->setProperty("class", newClasses); + + repolish(widget); +} + +void Utils::removeClass(QWidget *widget, const QString &classname) +{ + if (!classNameIsValid(classname)) { + return; + } + + QVariant current = widget->property("class"); + if (current.isNull()) { + return; + } + + QStringList classList = current.toString().split(" "); + if (!classList.contains(classname, Qt::CaseSensitive)) { + return; + } + + classList.removeDuplicates(); + classList.removeAll(""); + classList.removeAll(classname); + + QString newClasses = classList.isEmpty() ? "" : classList.join(" "); + widget->setProperty("class", newClasses); + + repolish(widget); +} + +void Utils::toggleClass(QWidget *widget, const QString &classname, bool toggle) +{ + if (toggle) { + addClass(widget, classname); + } else { + removeClass(widget, classname); + } +} + void Utils::applyColorToIcon(QAbstractButton *button) { if (button && !button->icon().isNull()) { @@ -71,6 +141,6 @@ QPixmap Utils::recolorPixmap(const QPixmap &src, const QColor &color) // Widgets can then be styled via CSS class-style rules like .hover. void Utils::applyStateStylingEventFilter(QWidget *widget) { - widget->installEventFilter(new StateEventFilter(this, widget)); + widget->installEventFilter(new StateEventFilter(widget)); } } // namespace idian diff --git a/shared/qt/idian/include/Idian/Utils.hpp b/shared/qt/idian/include/Idian/Utils.hpp index 9ada1f5f0..6c468cccd 100644 --- a/shared/qt/idian/include/Idian/Utils.hpp +++ b/shared/qt/idian/include/Idian/Utils.hpp @@ -27,7 +27,8 @@ class QLabel; namespace idian { // Helpers for OBS Idian widgets -class Utils { +class Utils : public QObject { + Q_OBJECT static bool classNameIsValid(const QString &name) { @@ -37,92 +38,28 @@ class Utils { } public: - QWidget *parent = nullptr; - - Utils(QWidget *w) { parent = w; } + Utils(QObject *parent = nullptr) {}; // Force all children widgets to repaint - void polishChildren() { polishChildren(parent); } - static void polishChildren(QWidget *widget) - { - for (QWidget *child : widget->findChildren()) { - repolish(child); - } - } + static void polishChildren(QWidget *widget); - void repolish() { repolish(parent); } - static void repolish(QWidget *widget) { widget->style()->polish(widget); } + static void repolish(QWidget *widget); // Adds a style class to the widget - void addClass(const QString &classname) { addClass(parent, classname); } - static void addClass(QWidget *widget, const QString &classname) - { - if (!classNameIsValid(classname)) { - return; - } - - QVariant current = widget->property("class"); - - QStringList classList = current.toString().split(" "); - if (classList.contains(classname)) { - return; - } - - classList.removeDuplicates(); - classList.removeAll(""); - classList.append(classname); - - QString newClasses = classList.isEmpty() ? "" : classList.join(" "); - widget->setProperty("class", newClasses); - - repolish(widget); - } + static void addClass(QWidget *widget, const QString &classname); // Removes a style class from a widget - void removeClass(const QString &classname) { removeClass(parent, classname); } - static void removeClass(QWidget *widget, const QString &classname) - { - if (!classNameIsValid(classname)) { - return; - } - - QVariant current = widget->property("class"); - if (current.isNull()) { - return; - } - - QStringList classList = current.toString().split(" "); - if (!classList.contains(classname, Qt::CaseSensitive)) { - return; - } - - classList.removeDuplicates(); - classList.removeAll(""); - classList.removeAll(classname); - - QString newClasses = classList.isEmpty() ? "" : classList.join(" "); - widget->setProperty("class", newClasses); - - repolish(widget); - } + static void removeClass(QWidget *widget, const QString &classname); // Forces the addition or removal of a style class from a widget - void toggleClass(const QString &classname, bool toggle) { toggleClass(parent, classname, toggle); } - static void toggleClass(QWidget *widget, const QString &classname, bool toggle) - { - if (toggle) { - addClass(widget, classname); - } else { - removeClass(widget, classname); - } - } + static void toggleClass(QWidget *widget, const QString &classname, bool toggle); static void applyColorToIcon(QAbstractButton *button); static void applyColorToIcon(QLabel *label); static QPixmap recolorPixmap(const QPixmap &src, const QColor &color); - void applyStateStylingEventFilter(QWidget *widget); + static void applyStateStylingEventFilter(QWidget *widget); }; } // namespace idian diff --git a/shared/qt/idian/widgets/Row.cpp b/shared/qt/idian/widgets/Row.cpp index 0488b95bf..019885d1b 100644 --- a/shared/qt/idian/widgets/Row.cpp +++ b/shared/qt/idian/widgets/Row.cpp @@ -27,7 +27,7 @@ #include namespace idian { -Row::Row(QWidget *parent) : QFrame(parent), Utils(this) +Row::Row(QWidget *parent) : QFrame(parent) { rowLayout = new QHBoxLayout(this); rowLayout->setContentsMargins(0, 0, 0, 0); @@ -49,7 +49,7 @@ void Row::setBuddy(QWidget *widget) void Row::setChangeCursor(bool change) { changeCursor = change; - Utils::toggleClass("cursor-pointer", change); + Utils::toggleClass(this, "cursor-pointer", change); } void Row::enterEvent(QEnterEvent *event) @@ -98,7 +98,7 @@ void Row::connectBuddyWidget(QWidget *widget) { setAttribute(Qt::WA_Hover, true); setFocusPolicy(Qt::StrongFocus); - applyStateStylingEventFilter(this); + Utils::applyStateStylingEventFilter(this); // If element is a ToggleSwitch and checkable, forward clicks to the widget ToggleSwitch *obsToggle = qobject_cast(widget);