From 9ca02d7f1cff7bf8fbde5c5ce090d07e649a9257 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 30 Jan 2024 13:04:38 +0100 Subject: [PATCH] moving away from std::unordered_map towards QHash. For transitions between color schemes we need to copy out hash tables, what is way much easier with the COW concept of the Qt containers. Also: according to https://tessil.github.io/2016/08/29/benchmark-hopscotch-map.html QHash seems to be faster in the most relevant category "Random full reads: execution time (integers)" --- examples/mycontrols/main.cpp | 20 ++-- src/controls/QskSkin.cpp | 51 +++++---- src/controls/QskSkin.h | 6 +- src/controls/QskSkinHintTable.cpp | 61 ++++++++--- src/controls/QskSkinHintTable.h | 22 ++-- src/controls/QskSkinTransition.cpp | 161 +++++++++++++---------------- src/controls/QskSkinTransition.h | 19 ++-- support/SkinnyNamespace.cpp | 26 ++--- 8 files changed, 178 insertions(+), 188 deletions(-) diff --git a/examples/mycontrols/main.cpp b/examples/mycontrols/main.cpp index 5c7dfab9..216ce3be 100644 --- a/examples/mycontrols/main.cpp +++ b/examples/mycontrols/main.cpp @@ -102,22 +102,14 @@ class Window : public QskWindow private: void setAlternativeSkin( bool on ) { - auto oldSkin = qskSkinManager->skin(); - if ( oldSkin->parent() == qskSkinManager ) - oldSkin->setParent( nullptr ); // otherwise setSkin deletes it - - auto newSkin = qskSkinManager->setSkin( alternativeSkin( on ) ); - QskSkinTransition transition; + transition.setSourceSkin( qskSkinManager->skin() ); - transition.setSourceSkin( oldSkin ); - transition.setTargetSkin( newSkin ); - transition.setAnimation( QskAnimationHint( 600, QEasingCurve::Linear ) ); - - transition.process(); - - if ( oldSkin->parent() == nullptr ) - delete oldSkin; + if ( auto skin = qskSkinManager->setSkin( alternativeSkin( on ) ) ) + { + transition.setTargetSkin( skin ); + transition.run( 600 ); + } } QString alternativeSkin( bool on ) const diff --git a/src/controls/QskSkin.cpp b/src/controls/QskSkin.cpp index 465253ab..0d42201d 100644 --- a/src/controls/QskSkin.cpp +++ b/src/controls/QskSkin.cpp @@ -21,7 +21,6 @@ #include #include -#include #include "QskBox.h" #include "QskBoxSkinlet.h" @@ -104,6 +103,8 @@ #include "QskStatusIndicator.h" #include "QskStatusIndicatorSkinlet.h" +#include + static inline QskSkinlet* qskNewSkinlet( const QMetaObject* metaObject, QskSkin* skin ) { const QByteArray signature = metaObject->className() + QByteArrayLiteral( "(QskSkin*)" ); @@ -137,19 +138,19 @@ namespace } const QMetaObject* metaObject; - QskSkinlet* skinlet; + QskSkinlet* skinlet; // mutable ??? }; } class QskSkin::PrivateData { public: - std::unordered_map< const QMetaObject*, SkinletData > skinletMap; + QHash< const QMetaObject*, SkinletData > skinletMap; QskSkinHintTable hintTable; - std::unordered_map< int, QFont > fonts; - std::unordered_map< int, QskColorFilter > graphicFilters; + QHash< int, QFont > fonts; + QHash< int, QskColorFilter > graphicFilters; QskGraphicProviderMap graphicProviders; }; @@ -229,9 +230,9 @@ void QskSkin::declareSkinlet( const QMetaObject* metaObject, const auto it = m_data->skinletMap.find( metaObject ); - if ( it != m_data->skinletMap.cend() ) + if ( it != m_data->skinletMap.end() ) { - auto& entry = it->second; + auto& entry = it.value(); if ( entry.metaObject != skinletMetaObject ) { entry.metaObject = skinletMetaObject; @@ -276,18 +277,18 @@ void QskSkin::setFont( int fontRole, const QFont& font ) void QskSkin::resetFont( int fontRole ) { - m_data->fonts.erase( fontRole ); + m_data->fonts.remove( fontRole ); } QFont QskSkin::font( int fontRole ) const { - auto it = m_data->fonts.find( fontRole ); - if ( it != m_data->fonts.cend() ) - return it->second; + auto it = m_data->fonts.constFind( fontRole ); + if ( it != m_data->fonts.constEnd() ) + return it.value(); - it = m_data->fonts.find( QskSkin::DefaultFont ); - if ( it != m_data->fonts.cend() ) - return it->second; + it = m_data->fonts.constFind( QskSkin::DefaultFont ); + if ( it != m_data->fonts.constEnd() ) + return it.value(); return QGuiApplication::font(); } @@ -299,16 +300,12 @@ void QskSkin::setGraphicFilter( int graphicRole, const QskColorFilter& colorFilt void QskSkin::resetGraphicFilter( int graphicRole ) { - m_data->graphicFilters.erase( graphicRole ); + m_data->graphicFilters.remove( graphicRole ); } QskColorFilter QskSkin::graphicFilter( int graphicRole ) const { - auto it = m_data->graphicFilters.find( graphicRole ); - if ( it != m_data->graphicFilters.cend() ) - return it->second; - - return QskColorFilter(); + return m_data->graphicFilters.value( graphicRole ); } const QskSkinHintTable& QskSkin::hintTable() const @@ -321,12 +318,12 @@ QskSkinHintTable& QskSkin::hintTable() return m_data->hintTable; } -const std::unordered_map< int, QFont >& QskSkin::fonts() const +const QHash< int, QFont >& QskSkin::fonts() const { return m_data->fonts; } -const std::unordered_map< int, QskColorFilter >& QskSkin::graphicFilters() const +const QHash< int, QskColorFilter >& QskSkin::graphicFilters() const { return m_data->graphicFilters; } @@ -375,9 +372,9 @@ const QMetaObject* QskSkin::skinletMetaObject( const QMetaObject* metaObject ) c { while ( metaObject ) { - auto it = m_data->skinletMap.find( metaObject ); - if ( it != m_data->skinletMap.cend() ) - return it->second.metaObject; + auto it = m_data->skinletMap.constFind( metaObject ); + if ( it != m_data->skinletMap.constEnd() ) + return it.value().metaObject; metaObject = metaObject->superClass(); } @@ -390,9 +387,9 @@ QskSkinlet* QskSkin::skinlet( const QMetaObject* metaObject ) while ( metaObject ) { auto it = m_data->skinletMap.find( metaObject ); - if ( it != m_data->skinletMap.cend() ) + if ( it != m_data->skinletMap.end() ) { - auto& entry = it->second; + auto& entry = it.value(); if ( entry.skinlet == nullptr ) entry.skinlet = qskNewSkinlet( entry.metaObject, this ); diff --git a/src/controls/QskSkin.h b/src/controls/QskSkin.h index cf347448..95b1cbfe 100644 --- a/src/controls/QskSkin.h +++ b/src/controls/QskSkin.h @@ -13,7 +13,6 @@ #include #include -#include class QskSkinnable; class QskSkinlet; @@ -25,6 +24,7 @@ class QskGraphicProvider; class QskSkinHintTable; class QVariant; +template< typename Key, typename T > class QHash; class QSK_EXPORT QskSkin : public QObject { @@ -91,8 +91,8 @@ class QSK_EXPORT QskSkin : public QObject const QskSkinHintTable& hintTable() const; QskSkinHintTable& hintTable(); - const std::unordered_map< int, QFont >& fonts() const; - const std::unordered_map< int, QskColorFilter >& graphicFilters() const; + const QHash< int, QFont >& fonts() const; + const QHash< int, QskColorFilter >& graphicFilters() const; private: void declareSkinlet( const QMetaObject* metaObject, diff --git a/src/controls/QskSkinHintTable.cpp b/src/controls/QskSkinHintTable.cpp index cd0d1482..145e6989 100644 --- a/src/controls/QskSkinHintTable.cpp +++ b/src/controls/QskSkinHintTable.cpp @@ -11,20 +11,19 @@ const QVariant QskSkinHintTable::invalidHint; inline const QVariant* qskResolvedHint( QskAspect aspect, - const std::unordered_map< QskAspect, QVariant >& hints, - QskAspect* resolvedAspect ) + const QHash< QskAspect, QVariant >& hints, QskAspect* resolvedAspect ) { auto a = aspect; Q_FOREVER { - auto it = hints.find( aspect ); - if ( it != hints.cend() ) + auto it = hints.constFind( aspect ); + if ( it != hints.constEnd() ) { if ( resolvedAspect ) *resolvedAspect = aspect; - return &it->second; + return &it.value(); } #if 1 @@ -74,17 +73,53 @@ QskSkinHintTable::QskSkinHintTable() { } +QskSkinHintTable::QskSkinHintTable( const QskSkinHintTable& other ) + : m_animatorCount( other.m_animatorCount ) + , m_states( other.m_states ) +{ + if ( other.m_hints ) + { + /* + A previous implementation was using STL containers - however: + + according to https://tessil.github.io/2016/08/29/benchmark-hopscotch-map.html + QHash does slightly faster lookups than std::unordered_map in the category + "Random full reads: execution time (integers)", that is the most relevant one + in our use case. + + Considering, that the "copy on write" strategy of QHash makes the implementation + of copy/assignment operators much easier ( needed in QskSkinTransition ) we prefer + using the Qt container over the STL counterparts. + */ + m_hints = new QHash< QskAspect, QVariant >( *other.m_hints ); + } +} + QskSkinHintTable::~QskSkinHintTable() { delete m_hints; } -const std::unordered_map< QskAspect, QVariant >& QskSkinHintTable::hints() const +QskSkinHintTable& QskSkinHintTable::operator=( const QskSkinHintTable& other ) +{ + m_animatorCount = ( other.m_animatorCount ); + m_states = other.m_states; + + delete m_hints; + m_hints = nullptr; + + if ( other.m_hints ) + m_hints = new QHash< QskAspect, QVariant >( *other.m_hints ); + + return *this; +} + +const QHash< QskAspect, QVariant >& QskSkinHintTable::hints() const { if ( m_hints ) return *m_hints; - static std::unordered_map< QskAspect, QVariant > dummyHints; + static QHash< QskAspect, QVariant > dummyHints; return dummyHints; } @@ -93,7 +128,7 @@ const std::unordered_map< QskAspect, QVariant >& QskSkinHintTable::hints() const bool QskSkinHintTable::setHint( QskAspect aspect, const QVariant& skinHint ) { if ( m_hints == nullptr ) - m_hints = new HintMap(); + m_hints = new QHash< QskAspect, QVariant >(); auto it = m_hints->find( aspect ); if ( it == m_hints->end() ) @@ -111,9 +146,9 @@ bool QskSkinHintTable::setHint( QskAspect aspect, const QVariant& skinHint ) return true; } - if ( it->second != skinHint ) + if ( it.value() != skinHint ) { - it->second = skinHint; + it.value() = skinHint; return true; } @@ -127,7 +162,7 @@ bool QskSkinHintTable::removeHint( QskAspect aspect ) if ( m_hints == nullptr ) return false; - const bool erased = m_hints->erase( aspect ); + const bool erased = m_hints->remove( aspect ); if ( erased ) { @@ -153,7 +188,7 @@ QVariant QskSkinHintTable::takeHint( QskAspect aspect ) auto it = m_hints->find( aspect ); if ( it != m_hints->end() ) { - const auto value = it->second; + const auto value = it.value(); m_hints->erase( it ); if ( aspect.isAnimator() ) @@ -214,7 +249,7 @@ QskAspect QskSkinHintTable::resolvedAnimator( auto it = m_hints->find( aspect ); if ( it != m_hints->cend() ) { - hint = it->second.value< QskAnimationHint >(); + hint = it.value().value< QskAnimationHint >(); return aspect; } diff --git a/src/controls/QskSkinHintTable.h b/src/controls/QskSkinHintTable.h index 006ec57f..1602f760 100644 --- a/src/controls/QskSkinHintTable.h +++ b/src/controls/QskSkinHintTable.h @@ -9,7 +9,7 @@ #include "QskAspect.h" #include -#include +#include class QskAnimationHint; @@ -17,8 +17,11 @@ class QSK_EXPORT QskSkinHintTable { public: QskSkinHintTable(); + QskSkinHintTable( const QskSkinHintTable& ); ~QskSkinHintTable(); + QskSkinHintTable& operator=( const QskSkinHintTable& ); + bool setAnimation( QskAspect, QskAnimationHint ); QskAnimationHint animation( QskAspect ) const; @@ -33,7 +36,7 @@ class QSK_EXPORT QskSkinHintTable bool hasHint( QskAspect ) const; - const std::unordered_map< QskAspect, QVariant >& hints() const; + const QHash< QskAspect, QVariant >& hints() const; bool hasAnimators() const; bool hasHints() const; @@ -53,12 +56,10 @@ class QSK_EXPORT QskSkinHintTable bool isResolutionMatching( QskAspect, QskAspect ) const; private: - Q_DISABLE_COPY( QskSkinHintTable ) static const QVariant invalidHint; - typedef std::unordered_map< QskAspect, QVariant > HintMap; - HintMap* m_hints = nullptr; + QHash< QskAspect, QVariant >* m_hints = nullptr; unsigned short m_animatorCount = 0; QskAspect::States m_states; @@ -81,19 +82,16 @@ inline bool QskSkinHintTable::hasAnimators() const inline bool QskSkinHintTable::hasHint( QskAspect aspect ) const { - if ( m_hints != nullptr ) - return m_hints->find( aspect ) != m_hints->cend(); - - return false; + return m_hints && m_hints->contains( aspect ); } inline const QVariant& QskSkinHintTable::hint( QskAspect aspect ) const { if ( m_hints != nullptr ) { - auto it = m_hints->find( aspect ); - if ( it != m_hints->cend() ) - return it->second; + auto it = m_hints->constFind( aspect ); + if ( it != m_hints->constEnd() ) + return it.value(); } return invalidHint; diff --git a/src/controls/QskSkinTransition.cpp b/src/controls/QskSkinTransition.cpp index 8b6776a0..f2c35565 100644 --- a/src/controls/QskSkinTransition.cpp +++ b/src/controls/QskSkinTransition.cpp @@ -16,10 +16,15 @@ #include #include #include +#include -#include #include +static bool qskHasHintTable( const QskSkin* skin, const QskSkinHintTable& hintTable ) +{ + return skin->hintTable().hints().isSharedWith( hintTable.hints() ); +} + static void qskSendStyleEventRecursive( QQuickItem* item ) { QEvent event( QEvent::StyleChange ); @@ -31,11 +36,11 @@ static void qskSendStyleEventRecursive( QQuickItem* item ) } static void qskAddCandidates( const QskSkinTransition::Type mask, - const QskSkin* skin, QSet< QskAspect >& candidates ) + const QHash< QskAspect, QVariant >& hints, QSet< QskAspect >& candidates ) { - for ( const auto& entry : skin->hintTable().hints() ) + for ( auto it = hints.constBegin(); it != hints.constEnd(); ++it ) { - const auto aspect = entry.first.trunk(); + const auto aspect = it.key().trunk(); if ( aspect.isAnimator() ) continue; @@ -127,11 +132,11 @@ namespace QVariant animatedGraphicFilter( int graphicRole ) const; void addGraphicFilterAnimators( const QskAnimationHint&, - const QskSkin*, const QskSkin* ); + const QHash< int, QskColorFilter >&, const QHash< int, QskColorFilter >& ); void addItemAspects( QQuickItem*, const QskAnimationHint&, const QSet< QskAspect >&, - const QskSkin*, const QskSkin* ); + const QskSkinHintTable&, const QskSkinHintTable& ); void update(); @@ -142,7 +147,7 @@ namespace void addHints( const QskControl*, const QskAnimationHint&, const QSet< QskAspect >& candidates, - const QskSkin* skin1, const QskSkin* skin2 ); + const QskSkinHintTable&, const QskSkinHintTable& ); void storeAnimator( const QskControl*, const QskAspect, const QVariant&, const QVariant&, QskAnimationHint ); @@ -150,8 +155,8 @@ namespace void storeUpdateInfo( const QskControl*, QskAspect ); QQuickWindow* m_window; - std::unordered_map< QskAspect, HintAnimator > m_animatorMap; - std::unordered_map< int, QskVariantAnimator > m_graphicFilterAnimatorMap; + QHash< QskAspect, HintAnimator > m_animatorMap; + QHash< int, QskVariantAnimator > m_graphicFilterAnimatorMap; std::vector< UpdateInfo > m_updateInfos; // vector: for fast iteration }; @@ -203,24 +208,24 @@ inline const QQuickWindow* WindowAnimator::window() const void WindowAnimator::start() { for ( auto& it : m_animatorMap ) - it.second.start(); + it.start(); for ( auto& it : m_graphicFilterAnimatorMap ) - it.second.start(); + it.start(); } bool WindowAnimator::isRunning() const { if ( !m_animatorMap.empty() ) { - const auto& animator = m_animatorMap.begin()->second; + const auto& animator = m_animatorMap.constBegin().value(); if ( animator.isRunning() ) return true; } if ( !m_graphicFilterAnimatorMap.empty() ) { - const auto& animator = m_graphicFilterAnimatorMap.begin()->second; + const auto& animator = m_graphicFilterAnimatorMap.constBegin().value(); if ( animator.isRunning() ) return true; } @@ -230,10 +235,10 @@ bool WindowAnimator::isRunning() const inline QVariant WindowAnimator::animatedHint( QskAspect aspect ) const { - auto it = m_animatorMap.find( aspect ); - if ( it != m_animatorMap.cend() ) + auto it = m_animatorMap.constFind( aspect ); + if ( it != m_animatorMap.constEnd() ) { - const auto& animator = it->second; + const auto& animator = it.value(); if ( animator.isRunning() ) return animator.currentValue(); } @@ -243,10 +248,10 @@ inline QVariant WindowAnimator::animatedHint( QskAspect aspect ) const inline QVariant WindowAnimator::animatedGraphicFilter( int graphicRole ) const { - auto it = m_graphicFilterAnimatorMap.find( graphicRole ); - if ( it != m_graphicFilterAnimatorMap.cend() ) + auto it = m_graphicFilterAnimatorMap.constFind( graphicRole ); + if ( it != m_graphicFilterAnimatorMap.constEnd() ) { - const auto& animator = it->second; + const auto& animator = it.value(); if ( animator.isRunning() ) return animator.currentValue(); } @@ -254,22 +259,21 @@ inline QVariant WindowAnimator::animatedGraphicFilter( int graphicRole ) const return QVariant(); } -void WindowAnimator::addGraphicFilterAnimators( const QskAnimationHint& animatorHint, - const QskSkin* skin1, const QskSkin* skin2 ) +void WindowAnimator::addGraphicFilterAnimators( + const QskAnimationHint& animatorHint, + const QHash< int, QskColorFilter >& filters1, + const QHash< int, QskColorFilter >& filters2 ) { const QskColorFilter noFilter; - const auto& filter1 = skin1->graphicFilters(); - const auto& filter2 = skin2->graphicFilters(); - - for ( auto it2 = filter2.begin(); it2 != filter2.end(); ++it2 ) + for ( auto it2 = filters2.constBegin(); it2 != filters2.constEnd(); ++it2 ) { - auto it1 = filter1.find( it2->first ); - if ( it1 == filter1.cend() ) - it1 = filter1.find( 0 ); + auto it1 = filters1.constFind( it2.key() ); + if ( it1 == filters1.constEnd() ) + it1 = filters1.constFind( 0 ); - const auto& f1 = ( it1 != filter1.cend() ) ? it1->second : noFilter; - const auto& f2 = it2->second; + const auto& f1 = ( it1 != filters1.constEnd() ) ? it1.value() : noFilter; + const auto& f2 = it2.value(); if ( f1 != f2 ) { @@ -280,23 +284,24 @@ void WindowAnimator::addGraphicFilterAnimators( const QskAnimationHint& animator animator.setStartValue( QVariant::fromValue( f1 ) ); animator.setEndValue( QVariant::fromValue( f2 ) ); - m_graphicFilterAnimatorMap.emplace( it2->first, animator ); + m_graphicFilterAnimatorMap.emplace( it2.key(), animator ); } } } void WindowAnimator::addItemAspects( QQuickItem* item, const QskAnimationHint& animatorHint, const QSet< QskAspect >& candidates, - const QskSkin* skin1, const QskSkin* skin2 ) + const QskSkinHintTable& table1, const QskSkinHintTable& table2 ) { if ( !item->isVisible() ) return; if ( auto control = qskControlCast( item ) ) { - if ( control->isInitiallyPainted() && ( control->effectiveSkin() == skin2 ) ) + if ( control->isInitiallyPainted() && + qskHasHintTable( control->effectiveSkin(), table2 ) ) { - addHints( control, animatorHint, candidates, skin1, skin2 ); + addHints( control, animatorHint, candidates, table1, table2 ); #if 1 /* As it is hard to identify which controls depend on the animated @@ -310,7 +315,7 @@ void WindowAnimator::addItemAspects( QQuickItem* item, const auto children = item->childItems(); for ( auto child : children ) - addItemAspects( child, animatorHint, candidates, skin1, skin2 ); + addItemAspects( child, animatorHint, candidates, table1, table2 ); } void WindowAnimator::update() @@ -333,15 +338,12 @@ void WindowAnimator::update() void WindowAnimator::addHints( const QskControl* control, const QskAnimationHint& animatorHint, const QSet< QskAspect >& candidates, - const QskSkin* skin1, const QskSkin* skin2 ) + const QskSkinHintTable& table1, const QskSkinHintTable& table2 ) { const auto subControls = control->subControls(); const auto& localTable = control->hintTable(); - const auto& table1 = skin1->hintTable(); - const auto& table2 = skin2->hintTable(); - for ( auto aspect : candidates ) { if ( !isControlAffected( control, subControls, aspect ) ) @@ -548,8 +550,12 @@ void ApplicationAnimator::cleanup( QQuickWindow* window ) class QskSkinTransition::PrivateData { public: - QskSkin* skins[ 2 ] = {}; - QskAnimationHint animationHint; + struct + { + QskSkinHintTable hintTable; + QHash< int, QskColorFilter > graphicFilters; + } tables[ 2 ]; + Type mask = QskSkinTransition::AllTypes; }; @@ -572,57 +578,38 @@ QskSkinTransition::Type QskSkinTransition::mask() const return m_data->mask; } -void QskSkinTransition::setSourceSkin( QskSkin* skin ) +void QskSkinTransition::setSourceSkin( const QskSkin* skin ) { - m_data->skins[ 0 ] = skin; + auto& tables = m_data->tables[ 0 ]; + + tables.hintTable = skin->hintTable(); + tables.graphicFilters = skin->graphicFilters(); } -QskSkin* QskSkinTransition::sourceSkin() const +void QskSkinTransition::setTargetSkin( const QskSkin* skin ) { - return m_data->skins[ 0 ]; + auto& tables = m_data->tables[ 1 ]; + + tables.hintTable = skin->hintTable(); + tables.graphicFilters = skin->graphicFilters(); } -void QskSkinTransition::setTargetSkin( QskSkin* skin ) -{ - m_data->skins[ 1 ] = skin; -} - -QskSkin* QskSkinTransition::targetSkin() const -{ - return m_data->skins[ 1 ]; -} - -void QskSkinTransition::setAnimation( QskAnimationHint animationHint ) -{ - m_data->animationHint = animationHint; -} - -QskAnimationHint QskSkinTransition::animation() const -{ - return m_data->animationHint; -} - -void QskSkinTransition::updateSkin( QskSkin*, QskSkin* ) -{ - // nop -} - -void QskSkinTransition::process() +void QskSkinTransition::run( const QskAnimationHint& animationHint ) { qskApplicationAnimator->reset(); - auto skin1 = m_data->skins[ 0 ]; - auto skin2 = m_data->skins[ 1 ]; + const auto& table1 = m_data->tables[ 0 ].hintTable; + const auto& table2 = m_data->tables[ 1 ].hintTable; + + const auto& graphicFilters1 = m_data->tables[ 0 ].graphicFilters; + const auto& graphicFilters2 = m_data->tables[ 1 ].graphicFilters; QSet< QskAspect > candidates; - if ( skin1 && skin2 ) + if ( ( animationHint.duration > 0 ) && ( m_data->mask != 0 ) ) { - if ( ( m_data->animationHint.duration > 0 ) && ( m_data->mask != 0 ) ) - { - qskAddCandidates( m_data->mask, skin1, candidates ); - qskAddCandidates( m_data->mask, skin2, candidates ); - } + qskAddCandidates( m_data->mask, table1.hints(), candidates ); + qskAddCandidates( m_data->mask, table2.hints(), candidates ); } if ( !candidates.isEmpty() ) @@ -635,17 +622,18 @@ void QskSkinTransition::process() { if ( auto w = qobject_cast< QQuickWindow* >( window ) ) { - if ( !w->isVisible() || ( qskEffectiveSkin( w ) != skin2 ) ) - { + if ( !w->isVisible() ) + continue; + + if ( !qskHasHintTable( qskEffectiveSkin( w ), table2 ) ) continue; - } auto animator = new WindowAnimator( w ); if ( doGraphicFilter ) { - animator->addGraphicFilterAnimators( - m_data->animationHint, skin1, skin2 ); + animator->addGraphicFilterAnimators( animationHint, + graphicFilters1, graphicFilters2 ); doGraphicFilter = false; } @@ -656,7 +644,7 @@ void QskSkinTransition::process() */ animator->addItemAspects( w->contentItem(), - m_data->animationHint, candidates, skin1, skin2 ); + animationHint, candidates, table1, table2 ); qskApplicationAnimator->add( animator ); } @@ -664,9 +652,6 @@ void QskSkinTransition::process() qskApplicationAnimator->start(); } - - // apply the changes - updateSkin( skin1, skin2 ); } bool QskSkinTransition::isRunning() diff --git a/src/controls/QskSkinTransition.h b/src/controls/QskSkinTransition.h index 79598897..58d5da6f 100644 --- a/src/controls/QskSkinTransition.h +++ b/src/controls/QskSkinTransition.h @@ -9,10 +9,12 @@ #include "QskAspect.h" #include -class QskSkin; class QskAnimationHint; +class QskSkin; + class QQuickWindow; class QVariant; +template< typename Key, typename T > class QHash; class QSK_EXPORT QskSkinTransition { @@ -28,27 +30,18 @@ class QSK_EXPORT QskSkinTransition QskSkinTransition(); virtual ~QskSkinTransition(); - void setSourceSkin( QskSkin* ); - QskSkin* sourceSkin() const; - - void setTargetSkin( QskSkin* ); - QskSkin* targetSkin() const; - - void setAnimation( QskAnimationHint ); - QskAnimationHint animation() const; + void setSourceSkin( const QskSkin* ); + void setTargetSkin( const QskSkin* ); void setMask( Type ); Type mask() const; - void process(); + void run( const QskAnimationHint& ); static bool isRunning(); static QVariant animatedHint( const QQuickWindow*, QskAspect ); static QVariant animatedGraphicFilter( const QQuickWindow*, int graphicRole ); - protected: - virtual void updateSkin( QskSkin*, QskSkin* ); - private: Q_DISABLE_COPY( QskSkinTransition ) diff --git a/support/SkinnyNamespace.cpp b/support/SkinnyNamespace.cpp index 7a447f79..1fd93d00 100644 --- a/support/SkinnyNamespace.cpp +++ b/support/SkinnyNamespace.cpp @@ -152,23 +152,13 @@ void Skinny::setSkin( int index, QskAnimationHint hint ) if ( index == names.indexOf( qskSkinManager->skinName() ) ) return; - auto oldSkin = qskSkinManager->skin(); - if ( oldSkin->parent() == qskSkinManager ) - oldSkin->setParent( nullptr ); // otherwise setSkin deletes it + QskSkinTransition transition; + transition.setSourceSkin( qskSkinManager->skin() ); - if ( auto newSkin = qskSkinManager->setSkin( names[ index ] ) ) + if ( auto skin = qskSkinManager->setSkin( names[ index ] ) ) { - QskSkinTransition transition; - - //transition.setMask( QskAspect::Color ); // Metrics are flickering -> TODO - transition.setSourceSkin( oldSkin ); - transition.setTargetSkin( newSkin ); - transition.setAnimation( hint ); - - transition.process(); - - if ( oldSkin->parent() == nullptr ) - delete oldSkin; + transition.setTargetSkin( skin ); + transition.run( hint ); } } @@ -178,10 +168,10 @@ void Skinny::changeFonts( int increment ) const auto fonts = skin->fonts(); - for ( auto it = fonts.begin(); it != fonts.end(); ++it ) + for ( auto it = fonts.constBegin(); it != fonts.constEnd(); ++it ) { - auto role = it->first; - auto font = it->second; + auto role = it.key(); + auto font = it.value(); if ( font.pixelSize() > 0 ) {