Lazy initialize macro segment widgets

This should make it less time consuming to accidentally switch between
macros with a large amount of macro segments
This commit is contained in:
WarmUpTill 2025-05-02 22:52:17 +02:00 committed by WarmUpTill
parent f59478fac7
commit 230863adda
9 changed files with 140 additions and 28 deletions

View File

@ -61,12 +61,40 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
setLayout(mainLayout);
_entryData = entryData;
UpdateEntryData(id);
SetupWidgets(true);
_actionStateTimer.start(300);
_loading = false;
}
void MacroActionEdit::SetupWidgets(bool basicSetup)
{
if (_allWidgetsAreSetup) {
return;
}
const auto id = (*_entryData)->GetId();
_actionSelection->setCurrentText(
obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
const bool enabled = (*_entryData)->Enabled();
_enable->setChecked(enabled);
SetDisableEffect(!enabled);
HeaderInfoChanged(
QString::fromStdString((*_entryData)->GetShortDesc()));
if (basicSetup) {
return;
}
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
_section->SetContent(widget, (*_entryData)->GetCollapsed());
SetFocusPolicyOfWidgets();
_allWidgetsAreSetup = true;
}
void MacroActionEdit::ActionSelectionChanged(const QString &text)
{
if (_loading || !_entryData) {
@ -96,22 +124,6 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
SetFocusPolicyOfWidgets();
}
void MacroActionEdit::UpdateEntryData(const std::string &id)
{
_actionSelection->setCurrentText(
obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
const bool enabled = (*_entryData)->Enabled();
_enable->setChecked(enabled);
SetDisableEffect(!enabled);
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
HeaderInfoChanged(
QString::fromStdString((*_entryData)->GetShortDesc()));
_section->SetContent(widget, (*_entryData)->GetCollapsed());
SetFocusPolicyOfWidgets();
}
void MacroActionEdit::SetEntryData(std::shared_ptr<MacroAction> *data)
{
_entryData = data;

View File

@ -17,7 +17,7 @@ public:
QWidget *parent = nullptr,
std::shared_ptr<MacroAction> * = nullptr,
const std::string &id = MacroAction::GetDefaultID().data());
void UpdateEntryData(const std::string &id);
void SetupWidgets(bool basicSetup = false);
void SetEntryData(std::shared_ptr<MacroAction> *);
private slots:

View File

@ -138,7 +138,7 @@ MacroConditionEdit::MacroConditionEdit(
mainLayout->addWidget(_frame);
setLayout(mainLayout);
UpdateEntryData(id);
SetupWidgets(true);
_loading = false;
}
@ -178,23 +178,36 @@ void MacroConditionEdit::SetRootNode(bool root)
SetLogicSelection();
}
void MacroConditionEdit::UpdateEntryData(const std::string &id)
void MacroConditionEdit::SetupWidgets(bool basicSetup)
{
if (_allWidgetsAreSetup) {
return;
}
const auto id = (*_entryData)->GetId();
_conditionSelection->setCurrentText(obs_module_text(
MacroConditionFactory::GetConditionName(id).c_str()));
auto widget =
MacroConditionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
HeaderInfoChanged(
QString::fromStdString((*_entryData)->GetShortDesc()));
SetLogicSelection();
_section->SetContent(widget, (*_entryData)->GetCollapsed());
_dur->setVisible(MacroConditionFactory::UsesDurationModifier(id));
auto modifier = (*_entryData)->GetDurationModifier();
_dur->SetValue(modifier);
if (basicSetup) {
return;
}
auto widget =
MacroConditionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
_section->SetContent(widget, (*_entryData)->GetCollapsed());
SetFocusPolicyOfWidgets();
_allWidgetsAreSetup = true;
}
void MacroConditionEdit::SetEntryData(std::shared_ptr<MacroCondition> *data)

View File

@ -41,7 +41,7 @@ public:
bool root = true);
bool IsRootNode() const;
void SetRootNode(bool);
void UpdateEntryData(const std::string &id);
void SetupWidgets(bool basicSetup = false);
void SetEntryData(std::shared_ptr<MacroCondition> *);
private slots:

View File

@ -35,6 +35,9 @@ MacroSegmentList::MacroSegmentList(QWidget *parent)
setWidget(wrapper);
setWidgetResizable(true);
setAcceptDrops(true);
connect(verticalScrollBar(), &QScrollBar::valueChanged, this,
[this]() { SetupVisibleMacroSegmentWidgets(); });
}
MacroSegmentList::~MacroSegmentList()
@ -98,16 +101,18 @@ void MacroSegmentList::SetHelpMsgVisible(bool visible) const
_helpMsg->setVisible(visible);
}
void MacroSegmentList::Insert(int idx, MacroSegmentEdit *widget)
void MacroSegmentList::Insert(int idx, QWidget *widget)
{
widget->installEventFilter(this);
_contentLayout->insertWidget(idx, widget);
SetupVisibleMacroSegmentWidgets();
}
void MacroSegmentList::Add(QWidget *widget)
{
widget->installEventFilter(this);
_contentLayout->addWidget(widget);
SetupVisibleMacroSegmentWidgets();
}
void MacroSegmentList::Remove(int idx) const
@ -322,6 +327,36 @@ QRect MacroSegmentList::GetContentItemRectWithPadding(int idx) const
return rect;
}
void MacroSegmentList::SetVisibilityCheckEnable(bool enable)
{
_checkVisibility = enable;
if (_checkVisibility) {
QTimer::singleShot(0, this, [this]() {
SetupVisibleMacroSegmentWidgets();
});
}
}
void MacroSegmentList::SetupVisibleMacroSegmentWidgets()
{
if (!_checkVisibility) {
return;
}
const auto viewportRect = viewport()->rect();
for (auto segment : widget()->findChildren<MacroSegmentEdit *>()) {
const auto pos = segment->mapTo(viewport(), QPoint(0, 0));
const QRect rect(pos, segment->size());
if (!viewportRect.intersects(rect)) {
continue;
}
segment->SetupWidgets();
}
}
int MacroSegmentList::GetSegmentIndexFromPos(const QPoint &pos) const
{
int idx = -1;
@ -455,4 +490,10 @@ void MacroSegmentList::dropEvent(QDropEvent *event)
_dragPosition = -1;
}
void MacroSegmentList::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
SetupVisibleMacroSegmentWidgets();
}
} // namespace advss

View File

@ -20,7 +20,7 @@ public:
MacroSegmentEdit *WidgetAt(int idx) const;
MacroSegmentEdit *WidgetAt(const QPoint &) const;
int IndexAt(const QPoint &) const;
void Insert(int idx, MacroSegmentEdit *widget);
void Insert(int idx, QWidget *widget);
void Add(QWidget *widget);
void Remove(int idx) const;
void Clear(int idx = 0) const; // Clear all elements >= idx
@ -28,6 +28,7 @@ public:
void SetCollapsed(bool) const;
void SetSelection(int idx) const;
QVBoxLayout *ContentLayout() const { return _contentLayout; }
void SetVisibilityCheckEnable(bool enable);
signals:
void SelectionChanged(int idx);
@ -42,8 +43,10 @@ protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
void resizeEvent(QResizeEvent *event);
private:
void SetupVisibleMacroSegmentWidgets();
int GetSegmentIndexFromPos(const QPoint &) const;
int GetDragIndex(const QPoint &) const;
int GetDropIndex(const QPoint &) const;
@ -62,6 +65,8 @@ private:
QVBoxLayout *_layout;
QVBoxLayout *_contentLayout;
QLabel *_helpMsg;
bool _checkVisibility = true;
};
} // namespace advss

View File

@ -106,6 +106,7 @@ public:
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 &);
@ -130,6 +131,7 @@ protected:
QLabel *_headerInfo;
QWidget *_frame;
QVBoxLayout *_contentLayout;
bool _allWidgetsAreSetup = false;
private:
enum class DropLineState {

View File

@ -531,29 +531,56 @@ void AdvSceneSwitcher::on_runMacroOnChange_stateChanged(int value) const
void AdvSceneSwitcher::PopulateMacroActions(Macro &m, uint32_t afterIdx)
{
auto &actions = m.Actions();
// The layout system has not completed geometry propagation yet, so we
// can skip those checks for now
ui->actionsList->SetVisibilityCheckEnable(false);
for (; afterIdx < actions.size(); afterIdx++) {
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
actions[afterIdx]->GetId());
ui->actionsList->Add(newEntry);
}
ui->actionsList->SetHelpMsgVisible(actions.size() == 0);
// Give the layout system time before enabling the visibility checks and
// fully constructing the visible macro segments
QTimer::singleShot(0, this, [this]() {
ui->actionsList->SetVisibilityCheckEnable(true);
});
}
void AdvSceneSwitcher::PopulateMacroElseActions(Macro &m, uint32_t afterIdx)
{
auto &actions = m.ElseActions();
// The layout system has not completed geometry propagation yet, so we
// can skip those checks for now
ui->elseActionsList->SetVisibilityCheckEnable(false);
for (; afterIdx < actions.size(); afterIdx++) {
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
actions[afterIdx]->GetId());
ui->elseActionsList->Add(newEntry);
}
ui->elseActionsList->SetHelpMsgVisible(actions.size() == 0);
// Give the layout system time before enabling the visibility checks and
// fully constructing the visible macro segments
QTimer::singleShot(0, this, [this]() {
ui->elseActionsList->SetVisibilityCheckEnable(true);
});
}
void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx)
{
bool root = afterIdx == 0;
auto &conditions = m.Conditions();
// The layout system has not completed geometry propagation yet, so we
// can skip those checks for now
ui->conditionsList->SetVisibilityCheckEnable(false);
for (; afterIdx < conditions.size(); afterIdx++) {
auto newEntry = new MacroConditionEdit(
this, &conditions[afterIdx],
@ -562,6 +589,12 @@ void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx)
root = false;
}
ui->conditionsList->SetHelpMsgVisible(conditions.size() == 0);
// Give the layout system time before enabling the visibility checks and
// fully constructing the visible macro segments
QTimer::singleShot(0, this, [this]() {
ui->conditionsList->SetVisibilityCheckEnable(true);
});
}
void AdvSceneSwitcher::SetActionData(Macro &m) const

View File

@ -47,6 +47,12 @@ void Section::Collapse(bool collapse)
_toggleButton->setChecked(collapse);
_toggleButton->setArrowType(collapse ? Qt::ArrowType::RightArrow
: Qt::ArrowType::DownArrow);
if (!_toggleAnimation) {
_collapsed = collapse;
emit Collapsed(collapse);
return;
}
_toggleAnimation->setDirection(collapse ? QAbstractAnimation::Backward
: QAbstractAnimation::Forward);
_transitioning = true;