SceneSwitcher/lib/macro/macro-segment.hpp
WarmUpTill ba38b8bf27
Some checks failed
debian-build / build (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
Don't block UI while executing long runnig actions
The previous approach had the problem of losing any action internal
state changes in the created copy.

Revert "Fix temp var values of actions not being accessible"
This reverts commit df42538319.
Revert "Don't block UI while running actions"
This reverts commit a01d26e25d.
2026-04-04 21:14:05 +02:00

168 lines
4.6 KiB
C++

#pragma once
// The following helpers are used by all macro segments,
// so it makes sense to include them here:
#include "log-helper.hpp"
#include "obs-module-helper.hpp"
#include "sync-helpers.hpp"
#include "temp-variable.hpp"
#include <QWidget>
#include <QFrame>
#include <QVBoxLayout>
#include <QTimer>
#include <obs-data.h>
class QLabel;
namespace advss {
class Macro;
class EXPORT MacroSegment : public Lockable {
public:
MacroSegment(Macro *m, bool supportsVariableValue);
virtual ~MacroSegment() = default;
Macro *GetMacro() const { return _macro; }
void SetIndex(int idx) { _idx = idx; }
int GetIndex() const { return _idx; }
void SetCollapsed(bool collapsed) { _collapsed = collapsed; }
bool GetCollapsed() const { return _collapsed; }
void SetUseCustomLabel(bool enable) { _useCustomLabel = enable; }
bool GetUseCustomLabel() const { return _useCustomLabel; }
void SetCustomLabel(const std::string &label) { _customLabel = label; }
std::string GetCustomLabel() const { return _customLabel; }
virtual bool Save(obs_data_t *obj) const = 0;
virtual bool Load(obs_data_t *obj) = 0;
virtual std::vector<TempVariableRef> GetTempVarRefs() const;
virtual bool PostLoad();
virtual std::string GetShortDesc() const;
virtual std::string GetId() const = 0;
void EnableHighlight();
bool GetHighlightAndReset();
void SetEnabled(bool);
bool Enabled() const;
virtual std::string GetVariableValue() const;
protected:
friend bool SupportsVariableValue(MacroSegment *);
friend void IncrementVariableRef(MacroSegment *);
friend void DecrementVariableRef(MacroSegment *);
void SetVariableValue(const std::string &value);
bool IsReferencedInVars() const { return _variableRefs != 0; }
virtual void SetupTempVars();
void AddTempvar(const std::string &id, const std::string &name,
const std::string &description = "");
bool IsTempVarInUse(const std::string &id) const;
void SetTempVarValue(const std::string &id, const std::string &value);
template<typename T, typename = std::enable_if_t<
std::is_same<std::decay_t<T>, bool>::value>>
void SetTempVarValue(const std::string &id, T value)
{
SetTempVarValue(id, value ? std::string("true")
: std::string("false"));
}
template<typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
void SetTempVarValue(const std::string &id, F &&valueProvider)
{
if (IsTempVarInUse(id)) {
SetTempVarValue(id, valueProvider());
}
}
private:
void ClearAvailableTempvars();
std::optional<const TempVariable>
GetTempVar(const std::string &id) const;
void InvalidateTempVarValues();
// Macro helpers
Macro *_macro = nullptr;
int _idx = 0;
// UI helper
bool _highlight = false;
bool _collapsed = false;
bool _enabled = true;
// Custom header labels
bool _useCustomLabel = false;
std::string _customLabel = obs_module_text(
"AdvSceneSwitcher.macroTab.segment.defaultCustomLabel");
// Variable helpers
const bool _supportsVariableValue = false;
int _variableRefs = 0;
std::string _variableValue;
std::vector<TempVariable> _tempVariables;
friend class Macro;
};
class Section;
class MacroSegmentEdit : public QWidget {
Q_OBJECT
public:
MacroSegmentEdit(QWidget *parent = nullptr);
// Use this function to avoid accidental edits when scrolling through
// list of actions and conditions
void SetFocusPolicyOfWidgets();
void SetCollapsed(bool collapsed);
void SetSelected(bool);
virtual std::shared_ptr<MacroSegment> Data() const = 0;
virtual void SetupWidgets(bool basicSetup = false) = 0;
public slots:
void HeaderInfoChanged(const QString &);
protected slots:
void Collapsed(bool) const;
protected:
void SetDisableEffect(bool);
void SetEnableAppearance(bool);
bool eventFilter(QObject *obj, QEvent *ev) override;
Section *_section;
QLabel *_headerInfo;
QWidget *_frame;
QVBoxLayout *_contentLayout;
bool _allWidgetsAreSetup = false;
private:
enum class DropLineState {
NONE,
ABOVE,
BELOW,
};
void ShowDropLine(DropLineState);
// The reason for using two separate frame widgets, each with their own
// stylesheet, and changing their visibility vs. using a single frame
// and changing the stylesheet at runtime is that the operation of
// adjusting the stylesheet is very expensive and can take multiple
// hundred milliseconds per widget.
// This performance impact would hurt in areas like drag and drop or
// emitting the "SelectionChanged" signal.
QFrame *_noBorderframe;
QFrame *_borderFrame;
// In most cases the line above the widget will be used.
// The lower one will only be used if the segment is the last one in
// the list.
QFrame *_dropLineAbove;
QFrame *_dropLineBelow;
friend class MacroSegmentList;
};
} // namespace advss