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)"
This commit is contained in:
parent
34e8dd9d65
commit
9ca02d7f1c
@ -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
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <qpa/qplatformtheme.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "QskBox.h"
|
||||
#include "QskBoxSkinlet.h"
|
||||
@ -104,6 +103,8 @@
|
||||
#include "QskStatusIndicator.h"
|
||||
#include "QskStatusIndicatorSkinlet.h"
|
||||
|
||||
#include <qhash.h>
|
||||
|
||||
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 );
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "QskAspect.h"
|
||||
|
||||
#include <qvariant.h>
|
||||
#include <unordered_map>
|
||||
#include <qhash.h>
|
||||
|
||||
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;
|
||||
|
@ -16,10 +16,15 @@
|
||||
#include <qguiapplication.h>
|
||||
#include <qobject.h>
|
||||
#include <qvector.h>
|
||||
#include <qhash.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
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()
|
||||
|
@ -9,10 +9,12 @@
|
||||
#include "QskAspect.h"
|
||||
#include <memory>
|
||||
|
||||
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 )
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user