From 208865ba8d15e1216f053f06945c19ea37295eb4 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 11 Oct 2023 09:18:09 +0200 Subject: [PATCH 1/7] QskGestureRecognizer improvements --- examples/gallery/main.cpp | 12 ++++++++---- src/controls/QskGestureRecognizer.cpp | 9 +++------ src/controls/QskGestureRecognizer.h | 3 ++- src/controls/QskScrollBox.cpp | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/examples/gallery/main.cpp b/examples/gallery/main.cpp index b074c299..f0916df0 100644 --- a/examples/gallery/main.cpp +++ b/examples/gallery/main.cpp @@ -229,19 +229,17 @@ namespace } { - auto drawer = new Drawer( parentItem() ); - drawer->setEdge( Qt::RightEdge ); - auto burger = new QskPushButton( "≡", this ); burger->setEmphasis( QskPushButton::LowEmphasis ); connect( burger, &QskPushButton::clicked, - drawer, &QskPopup::open ); + this, &Header::drawerRequested ); } } Q_SIGNALS: void enabledToggled( bool ); + void drawerRequested(); }; class MainView : public QskMainView @@ -264,6 +262,12 @@ namespace connect( header, &Header::enabledToggled, tabView, &TabView::setPagesEnabled ); + auto drawer = new Drawer( this ); + drawer->setEdge( Qt::RightEdge ); + + connect( header, &Header::drawerRequested, + drawer, &QskPopup::open ); + setHeader( header ); setBody( tabView ); } diff --git a/src/controls/QskGestureRecognizer.cpp b/src/controls/QskGestureRecognizer.cpp index b383730c..099307ab 100644 --- a/src/controls/QskGestureRecognizer.cpp +++ b/src/controls/QskGestureRecognizer.cpp @@ -142,12 +142,9 @@ Qt::MouseButtons QskGestureRecognizer::acceptedMouseButtons() const return m_data->buttons; } -QRectF QskGestureRecognizer::gestureRect() const +bool QskGestureRecognizer::isAcceptedPos( const QPointF& pos ) const { - if ( m_data->watchedItem ) - return qskItemRect( m_data->watchedItem ); - - return QRectF( 0.0, 0.0, -1.0, -1.0 ); + return m_data->watchedItem && m_data->watchedItem->contains( pos ); } void QskGestureRecognizer::setRejectOnTimeout( bool on ) @@ -313,7 +310,7 @@ bool QskGestureRecognizer::processMouseEvent( if ( event->type() == QEvent::MouseButtonPress ) { - if ( !gestureRect().contains( pos ) ) + if ( !isAcceptedPos( pos ) ) return false; if ( m_data->state != Idle ) diff --git a/src/controls/QskGestureRecognizer.h b/src/controls/QskGestureRecognizer.h index b34cd012..c4ac00dc 100644 --- a/src/controls/QskGestureRecognizer.h +++ b/src/controls/QskGestureRecognizer.h @@ -22,6 +22,7 @@ class QSK_EXPORT QskGestureRecognizer : public QObject Q_PROPERTY( State state READ state NOTIFY stateChanged ) Q_PROPERTY( QQuickItem* watchedItem READ watchedItem WRITE setWatchedItem ) + Q_PROPERTY( QQuickItem* targetItem READ targetItem WRITE setTargetItem ) Q_PROPERTY( Qt::MouseButtons acceptedMouseButtons READ acceptedMouseButtons WRITE setAcceptedMouseButtons ) @@ -72,7 +73,7 @@ class QSK_EXPORT QskGestureRecognizer : public QObject State state() const; - virtual QRectF gestureRect() const; + virtual bool isAcceptedPos( const QPointF& ) const; Q_SIGNALS: void stateChanged( State from, State to ); diff --git a/src/controls/QskScrollBox.cpp b/src/controls/QskScrollBox.cpp index a2304842..a975baed 100644 --- a/src/controls/QskScrollBox.cpp +++ b/src/controls/QskScrollBox.cpp @@ -136,15 +136,15 @@ namespace setOrientations( Qt::Horizontal | Qt::Vertical ); } - QRectF gestureRect() const override + bool isAcceptedPos( const QPointF& pos ) const override { if ( auto scrollBox = qobject_cast< const QskScrollBox* >( watchedItem() ) ) { if ( qskIsScrollable( scrollBox, orientations() ) ) - return scrollBox->viewContentsRect(); + return scrollBox->viewContentsRect().contains( pos ); } - return QRectF( 0.0, 0.0, -1.0, -1.0 ); // empty + return false; } }; } From 65dea17cfde5d81abf3618b7b56aac604fc5c4d0 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 15 Oct 2023 15:31:51 +0200 Subject: [PATCH 2/7] smooth sliding of menus --- skins/fluent2/QskFluent2Skin.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 1b90f732..7b56147c 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -735,6 +735,7 @@ void Editor::setupListViewColors( void Editor::setupMenuMetrics() { using Q = QskMenu; + using A = QskAspect; setPadding( Q::Panel, { 4, 6, 4, 6 } ); setBoxBorderMetrics( Q::Panel, 1 ); @@ -748,6 +749,14 @@ void Editor::setupMenuMetrics() setStrutSize( Q::Icon, 12, 12 ); setPadding( Q::Icon, { 8, 8, 0, 8 } ); + +#if 1 + setPosition( Q::Panel, 0 ); + setPosition( Q::Panel | QskPopup::Closed, 1 ); + + // copied from Mat3 - what are the correct values for Fluent2 ??? + setAnimation( Q::Panel | A::Metric, 150 ); +#endif } void Editor::setupMenuColors( From 9069c8e39084764096bd8e9d41b7ceb158bf43a1 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 15 Oct 2023 15:33:32 +0200 Subject: [PATCH 3/7] position is a progress value [0-1] - nothing in dp --- skins/material3/QskMaterial3Skin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 957c1ba2..6653e202 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -379,7 +379,7 @@ void Editor::setupMenu() setFontRole( Q::Text, QskMaterial3Skin::M3BodyMedium ); setPosition( Q::Panel, 0 ); - setPosition( Q::Panel | QskPopup::Closed, 1_dp ); + setPosition( Q::Panel | QskPopup::Closed, 1 ); setAnimation( Q::Panel | A::Metric, 150 ); setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic ); From 56446c26db87c27fc03b2ea9bb64fed41c2fb958 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 15 Oct 2023 15:43:29 +0200 Subject: [PATCH 4/7] missing enum initialization fixed --- src/controls/QskListViewSkinlet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controls/QskListViewSkinlet.h b/src/controls/QskListViewSkinlet.h index e26f4cb1..c16cc637 100644 --- a/src/controls/QskListViewSkinlet.h +++ b/src/controls/QskListViewSkinlet.h @@ -24,7 +24,7 @@ class QSK_EXPORT QskListViewSkinlet : public QskScrollViewSkinlet public: enum NodeRole { - TextRole, + TextRole = Inherited::RoleCount, GraphicRole, RoleCount From 3ecd8f337ee89bac5b18e726befbf81215fd45b5 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 15 Oct 2023 15:44:09 +0200 Subject: [PATCH 5/7] code moved from QskPopupSkinlet to QskSlideInNode --- src/CMakeLists.txt | 2 + src/controls/QskMenuSkinlet.cpp | 42 ++++++++- src/controls/QskMenuSkinlet.h | 9 +- src/controls/QskPopupSkinlet.cpp | 138 +---------------------------- src/controls/QskPopupSkinlet.h | 5 -- src/nodes/QskSlideInNode.cpp | 146 +++++++++++++++++++++++++++++++ src/nodes/QskSlideInNode.h | 33 +++++++ 7 files changed, 228 insertions(+), 147 deletions(-) create mode 100644 src/nodes/QskSlideInNode.cpp create mode 100644 src/nodes/QskSlideInNode.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 237d1577..7ce13c74 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -115,6 +115,7 @@ list(APPEND HEADERS nodes/QskRichTextRenderer.h nodes/QskScaleRenderer.h nodes/QskSGNode.h + nodes/QskSlideInNode.h nodes/QskStrokeNode.h nodes/QskStippledLineRenderer.h nodes/QskShapeNode.h @@ -146,6 +147,7 @@ list(APPEND SOURCES nodes/QskRichTextRenderer.cpp nodes/QskScaleRenderer.cpp nodes/QskSGNode.cpp + nodes/QskSlideInNode.cpp nodes/QskStrokeNode.cpp nodes/QskStippledLineRenderer.cpp nodes/QskShapeNode.cpp diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index 0629b137..d75323a9 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -9,12 +9,14 @@ #include "QskGraphic.h" #include "QskColorFilter.h" #include "QskTextOptions.h" -#include "QskSGNode.h" #include "QskFunctions.h" #include "QskMargins.h" #include "QskFunctions.h" #include "QskLabelData.h" +#include "QskSGNode.h" +#include "QskSlideInNode.h" + #include #include @@ -209,11 +211,44 @@ QskMenuSkinlet::QskMenuSkinlet( QskSkin* skin ) : Inherited( skin ) , m_data( new PrivateData() ) { - appendNodeRoles( { PanelRole } ); + appendNodeRoles( { ContentsRole, PanelRole } ); } QskMenuSkinlet::~QskMenuSkinlet() = default; +QSGNode* QskMenuSkinlet::updateSubNode( + const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const +{ + switch ( nodeRole ) + { + case ContentsRole: + { + /* + QskSlideInNode works for controls made of nodes - not for + containers of other quick items. TODO ... + */ + + const auto popup = static_cast< const QskPopup* >( skinnable ); + + auto rect = popup->contentsRect(); + if ( rect.isEmpty() ) + return nullptr; + + auto slideInNode = QskSGNode::ensureNode< QskSlideInNode >( node ); + + const auto progress = popup->metric( popup->faderAspect() ); + slideInNode->updateTranslation( rect, Qt::TopEdge, progress ); + + auto contentsNode = updateContentsNode( popup, slideInNode->contentsNode() ); + slideInNode->setContentsNode( contentsNode ); + + return slideInNode; + } + } + + return Inherited::updateSubNode( skinnable, nodeRole, node ); +} + QRectF QskMenuSkinlet::cursorRect( const QskSkinnable* skinnable, const QRectF& contentsRect, int index ) const { @@ -407,7 +442,8 @@ QskAspect::States QskMenuSkinlet::sampleStates( } } - const auto cursorPos = menu->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); + const auto cursorPos = menu->effectiveSkinHint( + Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index ) { diff --git a/src/controls/QskMenuSkinlet.h b/src/controls/QskMenuSkinlet.h index 4ebe5284..34a3c0b5 100644 --- a/src/controls/QskMenuSkinlet.h +++ b/src/controls/QskMenuSkinlet.h @@ -20,7 +20,9 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet public: enum NodeRole { - PanelRole = QskPopupSkinlet::RoleCount, + ContentsRole = Inherited::RoleCount, + PanelRole, + RoleCount }; @@ -48,7 +50,10 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet Qt::SizeHint, const QSizeF& ) const override; protected: - QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const override; + QSGNode* updateSubNode( const QskSkinnable*, + quint8 nodeRole, QSGNode* ) const override; + + QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const; QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const; QSGNode* updateSampleNode( const QskSkinnable*, diff --git a/src/controls/QskPopupSkinlet.cpp b/src/controls/QskPopupSkinlet.cpp index 70cf300e..07dbb53c 100644 --- a/src/controls/QskPopupSkinlet.cpp +++ b/src/controls/QskPopupSkinlet.cpp @@ -5,108 +5,11 @@ #include "QskPopupSkinlet.h" #include "QskPopup.h" -#include "QskSGNode.h" - -#include -#include -#include - -namespace -{ - class RootNode : public QSGNode - { - public: - ~RootNode() override - { - delete m_clipNode; - delete m_transformNode; - delete m_contentsNode; - } - - void setClipRect( const QRectF& rect ) - { - if ( m_clipNode == nullptr ) - { - m_clipNode = new QSGClipNode(); - m_clipNode->setFlag( QSGNode::OwnedByParent, false ); - m_clipNode->setIsRectangular( true ); - } - - m_clipNode->setClipRect( rect ); - } - - void resetClip() - { - delete m_clipNode; - m_clipNode = nullptr; - } - - void setTranslation( qreal dx, qreal dy ) - { - if ( dx != 0.0 || dy != 0.0 ) - { - if ( m_transformNode == nullptr ) - { - m_transformNode = new QSGTransformNode(); - m_transformNode->setFlag( QSGNode::OwnedByParent, false ); - } - - QTransform transform; - transform.translate( dx, dy ); - - m_transformNode->setMatrix( transform ); - } - else - { - delete m_transformNode; - m_transformNode = nullptr; - } - } - - void setContentsNode( QSGNode* contentsNode ) - { - if ( m_contentsNode != contentsNode ) - { - if ( contentsNode ) - contentsNode->setFlag( QSGNode::OwnedByParent, false ); - - delete m_contentsNode; - m_contentsNode = contentsNode; - } - } - - void rearrangeNodes() - { - const std::initializer_list< QSGNode* > nodes = - { m_clipNode, m_transformNode, m_contentsNode }; - - QSGNode* parentNode = this; - for ( auto node : nodes ) - { - if ( node ) - { - QskSGNode::setParentNode( node, parentNode ); - parentNode = node; - } - } - } - - inline QSGNode* contentsNode() - { - return m_contentsNode; - } - - private: - QSGClipNode* m_clipNode = nullptr; - QSGTransformNode* m_transformNode = nullptr; - QSGNode* m_contentsNode = nullptr; - }; -} QskPopupSkinlet::QskPopupSkinlet( QskSkin* skin ) : Inherited( skin ) { - appendNodeRoles( { OverlayRole, ContentsRole } ); + appendNodeRoles( { OverlayRole } ); } QskPopupSkinlet::~QskPopupSkinlet() = default; @@ -131,48 +34,9 @@ QSGNode* QskPopupSkinlet::updateSubNode( { case OverlayRole: return updateBoxNode( skinnable, node, QskPopup::Overlay ); - - case ContentsRole: - return updateExtraNode( popup, node ); } return Inherited::updateSubNode( skinnable, nodeRole, node ); } -QSGNode* QskPopupSkinlet::updateExtraNode( const QskPopup* popup, QSGNode* node ) const -{ - auto cr = popup->contentsRect(); - if ( cr.isEmpty() ) - return nullptr; - - auto rootNode = QskSGNode::ensureNode< RootNode >( node ); - - const auto faderProgress = popup->metric( popup->faderAspect() ); - if ( faderProgress > 0.0 && faderProgress <= 1.0 ) - { - auto clipRect = QRectF( popup->mapFromScene( QPointF() ), popup->window()->size() ); - clipRect.setTop( cr.top() ); - - rootNode->setClipRect( clipRect ); - } - else - { - rootNode->resetClip(); - } - - rootNode->setTranslation( 0.0, -faderProgress * cr.height() ); - - auto contentsNode = updateContentsNode( popup, rootNode->contentsNode() ); - rootNode->setContentsNode( contentsNode ); - - rootNode->rearrangeNodes(); - - return rootNode; -} - -QSGNode* QskPopupSkinlet::updateContentsNode( const QskPopup*, QSGNode* ) const -{ - return nullptr; -} - #include "moc_QskPopupSkinlet.cpp" diff --git a/src/controls/QskPopupSkinlet.h b/src/controls/QskPopupSkinlet.h index 076f86f9..ecd3a758 100644 --- a/src/controls/QskPopupSkinlet.h +++ b/src/controls/QskPopupSkinlet.h @@ -20,8 +20,6 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet enum NodeRole { OverlayRole, - ContentsRole, - RoleCount }; @@ -35,10 +33,7 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override; - virtual QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const; - private: - QSGNode* updateExtraNode( const QskPopup*, QSGNode* ) const; QSGNode* updateOverlayNode( const QskPopup*, QSGNode* ) const; }; diff --git a/src/nodes/QskSlideInNode.cpp b/src/nodes/QskSlideInNode.cpp new file mode 100644 index 00000000..6c77b366 --- /dev/null +++ b/src/nodes/QskSlideInNode.cpp @@ -0,0 +1,146 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskSlideInNode.h" +#include "QskSGNode.h" +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END + +class QskSlideInNodePrivate final : public QSGNodePrivate +{ + public: + ~QskSlideInNodePrivate() + { + delete clipNode; + delete transformNode; + delete contentsNode; + } + + void reparentContentNode( QskSlideInNode* node ) + { + if ( contentsNode ) + { + QSGNode* parentNode = transformNode; + + if ( parentNode == nullptr ) + parentNode = clipNode; + + if ( parentNode == nullptr ) + parentNode = node; + + QskSGNode::setParentNode( contentsNode, parentNode ); + } + } + + QSGClipNode* clipNode = nullptr; + QSGTransformNode* transformNode = nullptr; + QSGNode* contentsNode = nullptr; +}; + +QskSlideInNode::QskSlideInNode() + : QSGNode( *new QskSlideInNodePrivate, QSGNode::BasicNodeType ) +{ +} + +QskSlideInNode::~QskSlideInNode() = default; + +void QskSlideInNode::updateTranslation( const QRectF& rect, + Qt::Edge edge, qreal progress ) +{ + Q_UNUSED( edge ); // TODO ... + + Q_D( QskSlideInNode ); + + { + // clipping + + if ( progress > 0.0 && progress <= 1.0 ) + { + if ( d->clipNode == nullptr ) + { + d->clipNode = new QSGClipNode(); + d->clipNode->setFlag( QSGNode::OwnedByParent, false ); + d->clipNode->setIsRectangular( true ); + } + + d->clipNode->setClipRect( rect ); + + } + else + { + delete d->clipNode; + d->clipNode = nullptr; + } + + if ( d->clipNode ) + QskSGNode::setParentNode( d->clipNode, this ); + } + + { + // translation + + qreal dx = 0.0; + qreal dy = -progress* rect.height(); + + if ( dx != 0.0 || dy != 0.0 ) + { + if ( d->transformNode == nullptr ) + { + d->transformNode = new QSGTransformNode(); + d->transformNode->setFlag( QSGNode::OwnedByParent, false ); + } + + QTransform transform; + transform.translate( dx, dy ); + + d->transformNode->setMatrix( transform ); + } + else + { + delete d->transformNode; + d->transformNode = nullptr; + } + + if ( d->transformNode ) + { + QSGNode* parentNode = d->clipNode; + if ( parentNode == nullptr ) + parentNode = this; + + QskSGNode::setParentNode( d->transformNode, parentNode ); + } + } + + d->reparentContentNode( this ); +} + +void QskSlideInNode::setContentsNode( QSGNode* node ) +{ + Q_D( QskSlideInNode ); + + if ( d->contentsNode == node ) + return; + + if ( node ) + node->setFlag( QSGNode::OwnedByParent, false ); + + delete d->contentsNode; + d->contentsNode = node; + + d->reparentContentNode( this ); +} + +QSGNode* QskSlideInNode::contentsNode() +{ + return d_func()->contentsNode; +} + +const QSGNode* QskSlideInNode::contentsNode() const +{ + return d_func()->contentsNode; +} diff --git a/src/nodes/QskSlideInNode.h b/src/nodes/QskSlideInNode.h new file mode 100644 index 00000000..532663f2 --- /dev/null +++ b/src/nodes/QskSlideInNode.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_SLIDE_IN_NODE_H +#define QSK_SLIDE_IN_NODE_H + +#include "QskGlobal.h" + +#include +#include + +class QskSlideInNodePrivate; + +class QSK_EXPORT QskSlideInNode : public QSGNode +{ + public: + QskSlideInNode(); + ~QskSlideInNode() override; + + void updateTranslation( const QRectF&, Qt::Edge, qreal progress ); + + void setContentsNode( QSGNode* ); + + QSGNode* contentsNode(); + const QSGNode* contentsNode() const; + + private: + Q_DECLARE_PRIVATE( QskSlideInNode ) +}; + +#endif From 7cf88e7b4515908e0cf601f4ae6314f7725a59ab Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 15 Oct 2023 15:53:27 +0200 Subject: [PATCH 6/7] compiler warning fixed --- src/controls/QskPopupSkinlet.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/controls/QskPopupSkinlet.cpp b/src/controls/QskPopupSkinlet.cpp index 07dbb53c..d3777785 100644 --- a/src/controls/QskPopupSkinlet.cpp +++ b/src/controls/QskPopupSkinlet.cpp @@ -28,8 +28,6 @@ QRectF QskPopupSkinlet::subControlRect( const QskSkinnable* skinnable, QSGNode* QskPopupSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { - const auto popup = static_cast< const QskPopup* >( skinnable ); - switch ( nodeRole ) { case OverlayRole: From 3b5e6aa0fd9c7390863aa0041de2c0cd96988716 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 16 Oct 2023 19:19:38 +0200 Subject: [PATCH 7/7] always accept transitions for items without QQuickItem::ItemHasContents --- src/controls/QskSkinnable.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/controls/QskSkinnable.cpp b/src/controls/QskSkinnable.cpp index fa97a45f..03b9139c 100644 --- a/src/controls/QskSkinnable.cpp +++ b/src/controls/QskSkinnable.cpp @@ -1259,13 +1259,19 @@ bool QskSkinnable::isTransitionAccepted( QskAspect aspect ) const { Q_UNUSED( aspect ) - /* - Usually we only need smooth transitions, when state changes - happen while the skinnable is visible. There are few exceptions - like QskPopup::Closed, that is used to slide/fade in. - */ if ( auto control = qskControlCast( owningItem() ) ) - return control->isInitiallyPainted(); + { + /* + Usually we only need smooth transitions, when state changes + happen while the skinnable is visible. There are few exceptions + like QskPopup::Closed, that is used to slide/fade in. + */ + + if ( control->flags() & QQuickItem::ItemHasContents ) + return control->isInitiallyPainted(); + + return true; + } return false; }