From e0763a49572b39370b35bc13ba8f104a6411ef2f Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 20 Mar 2022 19:51:05 +0100 Subject: [PATCH] Improve performance for drag and drop - Changing the style sheets for the selection frame dynamically considerably slowed down the handling of the mouse events. Instead two separate widgets with fixed style sheets are now used. - Recreating the macro segments after dropping a widget took too much time leading to unresponsive drop operations --- src/headers/advanced-scene-switcher.hpp | 2 - src/headers/macro-segment.hpp | 6 +- src/macro-action-edit.cpp | 17 +++--- src/macro-condition-edit.cpp | 17 +++--- src/macro-segment-list.cpp | 10 ++-- src/macro-segment.cpp | 79 ++++++++++++++++--------- src/macro-tab.cpp | 5 -- 7 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index b76dbe0a..2fdcd9ab 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -298,8 +298,6 @@ public slots: void on_close_clicked(); private: - void SetSelection(MacroSegmentList *, int); - MacroSegmentList *conditionsList = nullptr; MacroSegmentList *actionsList = nullptr; diff --git a/src/headers/macro-segment.hpp b/src/headers/macro-segment.hpp index 95c04336..92f56280 100644 --- a/src/headers/macro-segment.hpp +++ b/src/headers/macro-segment.hpp @@ -62,8 +62,10 @@ signals: protected: Section *_section; QLabel *_headerInfo; - QFrame *_frame; - QVBoxLayout *_selectionFrameLayout; + QWidget *_frame; + QFrame *_noBorderframe; + QFrame *_borderFrame; + QVBoxLayout *_contentLayout; private: virtual MacroSegment *Data() = 0; diff --git a/src/macro-action-edit.cpp b/src/macro-action-edit.cpp index c679be63..1590dc80 100644 --- a/src/macro-action-edit.cpp +++ b/src/macro-action-edit.cpp @@ -80,14 +80,14 @@ MacroActionEdit::MacroActionEdit(QWidget *parent, _section->AddHeaderWidget(_headerInfo); QVBoxLayout *actionLayout = new QVBoxLayout; - actionLayout->setContentsMargins(0, 0, 0, 0); - actionLayout->setSpacing(0); - actionLayout->addWidget(_frame); - _selectionFrameLayout->addWidget(_section); + actionLayout->setContentsMargins({7, 7, 7, 7}); + actionLayout->addWidget(_section); + _contentLayout->addLayout(actionLayout); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addLayout(actionLayout); + mainLayout->setSpacing(0); + mainLayout->addWidget(_frame); setLayout(mainLayout); _entryData = entryData; @@ -316,8 +316,8 @@ void AdvSceneSwitcher::MacroActionSelectionChanged(int idx) return; } - SetSelection(actionsList, idx); - SetSelection(conditionsList, -1); + actionsList->SetSelection(idx); + conditionsList->SetSelection(-1); if (idx < 0 || (unsigned)idx >= macro->Actions().size()) { currentActionIdx = -1; @@ -346,10 +346,7 @@ void AdvSceneSwitcher::MacroActionReorder(int to, int from) macro->Actions().insert(macro->Actions().begin() + to, action); } - int idx = to > from ? from : to; macro->UpdateActionIndices(); - actionsList->Clear(idx); - PopulateMacroActions(*macro, idx); HighlightAction(to); SetActionData(*macro); } diff --git a/src/macro-condition-edit.cpp b/src/macro-condition-edit.cpp index 69630246..83953550 100644 --- a/src/macro-condition-edit.cpp +++ b/src/macro-condition-edit.cpp @@ -125,14 +125,14 @@ MacroConditionEdit::MacroConditionEdit( _section->AddHeaderWidget(_dur); QVBoxLayout *conditionLayout = new QVBoxLayout; - conditionLayout->setContentsMargins(0, 0, 0, 0); - conditionLayout->setSpacing(0); - conditionLayout->addWidget(_frame); - _selectionFrameLayout->addWidget(_section); + conditionLayout->setContentsMargins({7, 7, 7, 7}); + conditionLayout->addWidget(_section); + _contentLayout->addLayout(conditionLayout); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addLayout(conditionLayout); + mainLayout->setSpacing(0); + mainLayout->addWidget(_frame); setLayout(mainLayout); UpdateEntryData(id); @@ -460,8 +460,8 @@ void AdvSceneSwitcher::MacroConditionSelectionChanged(int idx) return; } - SetSelection(conditionsList, idx); - SetSelection(actionsList, -1); + conditionsList->SetSelection(idx); + actionsList->SetSelection(-1); if (idx < 0 || (unsigned)idx >= macro->Conditions().size()) { currentConditionIdx = -1; @@ -500,10 +500,7 @@ void AdvSceneSwitcher::MacroConditionReorder(int to, int from) condition); } - int idx = to > from ? from : to; macro->UpdateConditionIndices(); - conditionsList->Clear(idx); - PopulateMacroConditions(*macro, idx); HighlightCondition(to); SetConditionData(*macro); } diff --git a/src/macro-segment-list.cpp b/src/macro-segment-list.cpp index ff2af215..7688a94c 100644 --- a/src/macro-segment-list.cpp +++ b/src/macro-segment-list.cpp @@ -157,11 +157,11 @@ void MacroSegmentList::mousePressEvent(QMouseEvent *event) void MacroSegmentList::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton && _dragPosition != -1) { - QWidget *widget = nullptr; - if (_contentLayout->itemAt(_dragPosition)) { - widget = - _contentLayout->itemAt(_dragPosition)->widget(); + auto item = _contentLayout->itemAt(_dragPosition); + if (!item) { + return; } + auto widget = item->widget(); if (!widget) { return; } @@ -256,6 +256,8 @@ void MacroSegmentList::dropEvent(QDropEvent *event) if (dropPosition == -1) { return; } + _contentLayout->insertItem( + dropPosition, _contentLayout->takeAt(_dragPosition)); emit Reorder(dropPosition, _dragPosition); } _dragPosition = -1; diff --git a/src/macro-segment.cpp b/src/macro-segment.cpp index 127c40c8..dd706475 100644 --- a/src/macro-segment.cpp +++ b/src/macro-segment.cpp @@ -56,17 +56,47 @@ bool MouseWheelWidgetAdjustmentGuard::eventFilter(QObject *o, QEvent *e) } MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent) - : QWidget(parent), _showHighlight(highlight) + : QWidget(parent), + _showHighlight(highlight), + _section(new Section(300)), + _headerInfo(new QLabel()), + _contentLayout(new QVBoxLayout), + _frame(new QWidget), + _borderFrame(new QFrame), + _noBorderframe(new QFrame) { - _section = new Section(300); - _headerInfo = new QLabel(); + // The reason for using two separate frame widget 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. + _borderFrame->setObjectName("border"); + _borderFrame->setStyleSheet("#border {" + "border-color: rgba(0, 0, 0, 255);" + "border-width: 2px;" + "border-style: dashed;" + "border-radius: 4px;" + "background-color: rgba(0,0,0,100);" + "}"); + _noBorderframe->setObjectName("noBorder"); + _noBorderframe->setStyleSheet("#noBorder {" + "border-color: rgba(0, 0, 0, 0);" + "border-width: 2px;" + "border-style: dashed;" + "border-radius: 4px;" + "background-color: rgba(0,0,0,50);" + "}"); + _frame->setObjectName("frameWrapper"); + _frame->setStyleSheet("#frameWrapper {" + "border-width: 2px;" + "border-radius: 4px;" + "background-color: rgba(0,0,0,0);" + "}"); - _frame = new QFrame; - _frame->setObjectName("segmentFrame"); - _selectionFrameLayout = new QVBoxLayout; - SetSelected(false); - _frame->setLayout(_selectionFrameLayout); - // Set background transparent to avoid blocking highlight frame + // Set background of these widget types to be transparent to avoid + // blocking highlight frame background setStyleSheet("QCheckBox { background-color: rgba(0,0,0,0); }" "QLabel { background-color: rgba(0,0,0,0); }" "QSlider { background-color: rgba(0,0,0,0); }"); @@ -75,9 +105,9 @@ MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent) // the edit areas setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + // Signal handling QWidget::connect(_section, &Section::Collapsed, this, &MacroSegmentEdit::Collapsed); - // Macro signals QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this, SIGNAL(MacroAdded(const QString &))); @@ -87,7 +117,6 @@ MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent) SIGNAL(MacroRenamed(const QString &, const QString)), this, SIGNAL(MacroRenamed(const QString &, const QString))); - // Scene group signals QWidget::connect(parent, SIGNAL(SceneGroupAdded(const QString &)), this, SIGNAL(SceneGroupAdded(const QString &))); @@ -98,6 +127,15 @@ MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent) SIGNAL(SceneGroupRenamed(const QString &, const QString)), this, SIGNAL(SceneGroupRenamed(const QString &, const QString))); + // Frame layout + auto layout = new QGridLayout; + layout->setContentsMargins(0, 0, 0, 0); + layout->addLayout(_contentLayout, 0, 0); + layout->addWidget(_noBorderframe, 0, 0); + layout->addWidget(_borderFrame, 0, 0); + _frame->setLayout(layout); + SetSelected(false); + _timer.setInterval(1500); connect(&_timer, SIGNAL(timeout()), this, SLOT(Highlight())); _timer.start(); @@ -153,21 +191,6 @@ void MacroSegmentEdit::SetCollapsed(bool collapsed) void MacroSegmentEdit::SetSelected(bool selected) { - if (selected) { - _frame->setStyleSheet("#segmentFrame {" - "border-color: rgba(0, 0, 0, 255);" - "border-width: 2px;" - "border-style: dashed;" - "border-radius: 4px;" - "background-color: rgba(0,0,0,100);" - "}"); - } else { - _frame->setStyleSheet("#segmentFrame {" - "border-color: rgba(0, 0, 0, 0);" - "border-width: 2px;" - "border-style: dashed;" - "border-radius: 4px;" - "background-color: rgba(0,0,0,50);" - "}"); - } + _borderFrame->setVisible(selected); + _noBorderframe->setVisible(!selected); } diff --git a/src/macro-tab.cpp b/src/macro-tab.cpp index d5d404c9..835bc23e 100644 --- a/src/macro-tab.cpp +++ b/src/macro-tab.cpp @@ -601,11 +601,6 @@ void AdvSceneSwitcher::MinimizeConditions() ui->macroSplitter->setSizes(sizes); } -void AdvSceneSwitcher::SetSelection(MacroSegmentList *list, int idx) -{ - list->SetSelection(idx); -} - void AdvSceneSwitcher::DeleteMacroSegementHotkey() { if (currentActionIdx != -1) {