From 38567c2f2d2d0f8524e42224dff53a929cbf086a Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Sat, 24 May 2025 09:33:44 +0200 Subject: [PATCH 1/3] kstyle/animations: Use QObject as base type rather than QWidget This prepares for the animation engine being used with Qt Quick Controls. In most cases the type is cast to the relevant widget type for checking anyway, so might as well use the cast object further down but not require a QWidget at the beginning. --- kstyle/animations/breezeanimations.cpp | 48 +++++++++++++------------- kstyle/animations/breezeanimations.h | 4 +-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp index 12e5107c5..ceab53802 100644 --- a/kstyle/animations/breezeanimations.cpp +++ b/kstyle/animations/breezeanimations.cpp @@ -82,7 +82,7 @@ void Animations::setupEngines() } //____________________________________________________________ -void Animations::registerWidget(QWidget *widget) const +void Animations::registerWidget(QObject *widget) const { if (!widget) { return; @@ -101,37 +101,37 @@ void Animations::registerWidget(QWidget *widget) const // for optimization, one should put with most used widgets here first // buttons - if (qobject_cast(widget)) { - _toolButtonEngine->registerWidget(widget, AnimationHover | AnimationFocus); - _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); + if (auto toolButton = qobject_cast(widget)) { + _toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); + _widgetStateEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); } else if (qobject_cast(widget) || qobject_cast(widget)) { _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed); - } else if (qobject_cast(widget)) { + } else if (auto button = qobject_cast(widget)) { // register to toolbox engine if needed - if (qobject_cast(widget->parent())) { - _toolBoxEngine->registerWidget(widget); + if (auto toolBox = qobject_cast(widget->parent())) { + _toolBoxEngine->registerWidget(toolBox); } - _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); + _widgetStateEngine->registerWidget(button, AnimationHover | AnimationFocus); } // groupboxes else if (QGroupBox *groupBox = qobject_cast(widget)) { if (groupBox->isCheckable()) { - _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); + _widgetStateEngine->registerWidget(groupBox, AnimationHover | AnimationFocus); } } // sliders - else if (qobject_cast(widget)) { - _scrollBarEngine->registerWidget(widget, AnimationHover | AnimationFocus); - } else if (qobject_cast(widget)) { - _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); - } else if (qobject_cast(widget)) { - _dialEngine->registerWidget(widget, AnimationHover | AnimationFocus); + else if (auto scrollBar = qobject_cast(widget)) { + _scrollBarEngine->registerWidget(scrollBar, AnimationHover | AnimationFocus); + } else if (auto slider = qobject_cast(widget)) { + _widgetStateEngine->registerWidget(slider, AnimationHover | AnimationFocus); + } else if (auto dial = qobject_cast(widget)) { + _dialEngine->registerWidget(dial, AnimationHover | AnimationFocus); } // progress bar @@ -162,24 +162,24 @@ void Animations::registerWidget(QWidget *widget) const // header views // need to come before abstract item view, otherwise is skipped - else if (qobject_cast(widget)) { - _headerViewEngine->registerWidget(widget); + else if (auto headerView = qobject_cast(widget)) { + _headerViewEngine->registerWidget(headerView); } // lists - else if (qobject_cast(widget)) { - _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus); + else if (auto itemView = qobject_cast(widget)) { + _inputWidgetEngine->registerWidget(itemView, AnimationHover | AnimationFocus); } // tabbar - else if (qobject_cast(widget)) { - _tabBarEngine->registerWidget(widget); + else if (auto tabBar = qobject_cast(widget)) { + _tabBarEngine->registerWidget(tabBar); } // scrollarea else if (QAbstractScrollArea *scrollArea = qobject_cast(widget)) { - if (scrollArea->frameShadow() == QFrame::Sunken && (widget->focusPolicy() & Qt::StrongFocus)) { - _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus); + if (scrollArea->frameShadow() == QFrame::Sunken && (scrollArea->focusPolicy() & Qt::StrongFocus)) { + _inputWidgetEngine->registerWidget(scrollArea, AnimationHover | AnimationFocus); } } @@ -190,7 +190,7 @@ void Animations::registerWidget(QWidget *widget) const } //____________________________________________________________ -void Animations::unregisterWidget(QWidget *widget) const +void Animations::unregisterWidget(QObject *widget) const { if (!widget) { return; diff --git a/kstyle/animations/breezeanimations.h b/kstyle/animations/breezeanimations.h index 6551900a5..3215e8fb9 100644 --- a/kstyle/animations/breezeanimations.h +++ b/kstyle/animations/breezeanimations.h @@ -31,10 +31,10 @@ public: explicit Animations(); //* register animations corresponding to given widget, depending on its type. - void registerWidget(QWidget *widget) const; + void registerWidget(QObject *widget) const; /** unregister all animations associated to a widget */ - void unregisterWidget(QWidget *widget) const; + void unregisterWidget(QObject *widget) const; //* enability engine [[nodiscard]] WidgetStateEngine &widgetEnabilityEngine() const -- GitLab From 75201d1e63d82f7282c8bedcc7cc3d2417b1e123 Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Sat, 24 May 2025 09:40:01 +0200 Subject: [PATCH 2/3] kstyle: Use styleObject for widgetStateEngine in CheckBox/RadioButton Prepares it for doing the animation also with Qt Quick Controls without an actual QWidget. --- kstyle/breezestyle.cpp | 44 ++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp index 09cee6003..19149c382 100644 --- a/kstyle/breezestyle.cpp +++ b/kstyle/breezestyle.cpp @@ -4738,6 +4738,8 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter //___________________________________________________________________________________ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { + const QObject *styleObject = widget ? widget : option->styleObject; + // copy rect and palette const auto &rect(option->rect); const auto &palette(option->palette); @@ -4757,15 +4759,15 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter } // animation state - _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver); - _animations->widgetStateEngine().updateState(widget, AnimationPressed, checkBoxState != CheckOff); + _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver); + _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, checkBoxState != CheckOff); auto target = checkBoxState; - if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) { + if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) { checkBoxState = CheckAnimated; } - const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed)); + const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed)); - const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover)); + const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover)); // render _helper->renderCheckBoxBackground(painter, rect, palette, checkBoxState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation); @@ -4777,6 +4779,8 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter //___________________________________________________________________________________ bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { + const QObject *styleObject = widget ? widget : option->styleObject; + // copy rect and palette const auto &rect(option->rect); const auto &palette(option->palette); @@ -4791,19 +4795,27 @@ bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPaint RadioButtonState radioButtonState((state & State_On) ? RadioOn : RadioOff); // animation state - _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver); - _animations->widgetStateEngine().updateState(widget, AnimationPressed, radioButtonState != RadioOff); - if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) { + _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver); + _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, radioButtonState != RadioOff); + if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) { radioButtonState = RadioAnimated; } - const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed)); + const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed)); // colors - const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover)); + const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover)); // render - _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation); - _helper->renderRadioButton(painter, rect, palette, mouseOver, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation, opacity); + _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(styleObject, option, mouseOver), sunken, animation); + _helper->renderRadioButton(painter, + rect, + palette, + mouseOver, + radioButtonState, + hasHighlightNeutral(styleObject, option, mouseOver), + sunken, + animation, + opacity); return true; } @@ -5450,6 +5462,8 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint return true; } + const QObject *styleObject = widget ? widget : option->styleObject; + // copy palette and rect const auto &palette(option->palette); const auto &rect(option->rect); @@ -5501,10 +5515,10 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint const bool hasFocus(enabled && (state & State_HasFocus)); // update animation state - _animations->widgetStateEngine().updateState(widget, AnimationFocus, hasFocus); + _animations->widgetStateEngine().updateState(styleObject, AnimationFocus, hasFocus); - const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(widget, AnimationFocus)); - const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationFocus)); + const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(styleObject, AnimationFocus)); + const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationFocus)); // focus color QColor focusColor; if (isFocusAnimated) { -- GitLab From a572df8f099969919544dbc2478de6aa2082a705 Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Sat, 24 May 2025 09:54:44 +0200 Subject: [PATCH 3/3] kstyle: Register Qt Quick Controls with animations Since it's all software-rendered and indirect, only the CheckBox and RadioButton controls are actually wired up since the rest of the animations is quite subtle. --- kstyle/animations/breezeanimations.cpp | 9 +++++++++ kstyle/breezestyle.cpp | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp index ceab53802..5285f5daf 100644 --- a/kstyle/animations/breezeanimations.cpp +++ b/kstyle/animations/breezeanimations.cpp @@ -100,6 +100,15 @@ void Animations::registerWidget(QObject *widget) const // install animation timers // for optimization, one should put with most used widgets here first + // KQuickStyleItem. + const QString elementType = widget->property("elementType").toString(); + if (!elementType.isEmpty()) { + if (elementType == QLatin1String("checkbox") || elementType == QLatin1String("radiobutton")) { + _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed); + } + return; + } + // buttons if (auto toolButton = qobject_cast(widget)) { _toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp index 19149c382..e549803f1 100644 --- a/kstyle/breezestyle.cpp +++ b/kstyle/breezestyle.cpp @@ -4739,6 +4739,7 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { const QObject *styleObject = widget ? widget : option->styleObject; + isQtQuickControl(option, widget); // registers it with widgetStateEngine. // copy rect and palette const auto &rect(option->rect); @@ -4780,6 +4781,7 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { const QObject *styleObject = widget ? widget : option->styleObject; + isQtQuickControl(option, widget); // registers it with widgetStateEngine. // copy rect and palette const auto &rect(option->rect); @@ -5463,6 +5465,7 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint } const QObject *styleObject = widget ? widget : option->styleObject; + isQtQuickControl(option, widget); // registers it with widgetStateEngine. // copy palette and rect const auto &palette(option->palette); @@ -8460,6 +8463,7 @@ bool Style::isQtQuickControl(const QStyleOption *option, const QWidget *widget) if (!widget && option) { if (const auto item = qobject_cast(option->styleObject)) { _windowManager->registerQuickItem(item); + _animations->registerWidget(item); return true; } } -- GitLab