From 59c2e8ca33e45475889b700a841059b4786cecc9 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 30 Jan 2024 16:46:01 +0100 Subject: [PATCH] handling QStyleHints::colorSchemeChanged --- examples/gallery/main.cpp | 2 +- src/controls/QskQuickItem.cpp | 3 + src/controls/QskSkin.cpp | 21 ++++++- src/controls/QskSkinManager.cpp | 99 ++++++++++++++++++++++----------- src/controls/QskSkinManager.h | 5 ++ support/SkinnyNamespace.cpp | 43 +++----------- support/SkinnyNamespace.h | 5 +- 7 files changed, 105 insertions(+), 73 deletions(-) diff --git a/examples/gallery/main.cpp b/examples/gallery/main.cpp index 7ca7e09d..26878e3c 100644 --- a/examples/gallery/main.cpp +++ b/examples/gallery/main.cpp @@ -171,7 +171,7 @@ namespace if ( ( index >= 0 ) && ( index < names.size() ) && ( index != names.indexOf( qskSkinManager->skinName() ) ) ) { - Skinny::setSkin( index, 500 ); + qskSkinManager->setSkin( names[index] ); } } }; diff --git a/src/controls/QskQuickItem.cpp b/src/controls/QskQuickItem.cpp index 204a2334..75e7b8ae 100644 --- a/src/controls/QskQuickItem.cpp +++ b/src/controls/QskQuickItem.cpp @@ -79,6 +79,9 @@ namespace */ QObject::connect( qskSkinManager, &QskSkinManager::skinChanged, qskSkinManager, [ this ] { updateSkin(); } ); + + QObject::connect( qskSkinManager, &QskSkinManager::colorSchemeChanged, + qskSkinManager, [ this ] { updateSkin(); } ); } inline void insert( QskQuickItem* item ) diff --git a/src/controls/QskSkin.cpp b/src/controls/QskSkin.cpp index 7961d541..e2fb11db 100644 --- a/src/controls/QskSkin.cpp +++ b/src/controls/QskSkin.cpp @@ -13,6 +13,8 @@ #include "QskSkinHintTable.h" #include "QskStandardSymbol.h" #include "QskPlatform.h" +#include "QskSkinManager.h" +#include "QskSkinTransition.h" #include "QskMargins.h" @@ -230,8 +232,23 @@ void QskSkin::setColorScheme( ColorScheme colorScheme ) m_data->colorScheme = colorScheme; - clearHints(); - initHints(); + const auto transitionHint = qskSkinManager->transitionHint(); + if ( transitionHint.isValid() ) + { + QskSkinTransition transition; + transition.setSourceSkin( this ); + + clearHints(); + initHints(); + + transition.setTargetSkin( this ); + transition.run( transitionHint ); + } + else + { + clearHints(); + initHints(); + } Q_EMIT colorSchemeChanged( colorScheme ); } diff --git a/src/controls/QskSkinManager.cpp b/src/controls/QskSkinManager.cpp index 24f3d003..f1b9f8f7 100644 --- a/src/controls/QskSkinManager.cpp +++ b/src/controls/QskSkinManager.cpp @@ -6,6 +6,8 @@ #include "QskSkinManager.h" #include "QskSkinFactory.h" #include "QskSkin.h" +#include "QskSkinTransition.h" +#include "QskAnimationHint.h" #include #include @@ -21,16 +23,31 @@ #include #endif -/* - We could use QFactoryLoader, but as it is again a "private" class - and does a couple of hardcoded things we don't need ( like always resolving - from the application library path ) we prefer having our own code. - */ namespace { class SkinManager final : public QskSkinManager { + public: + SkinManager() + { +#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 ) + connect( QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, + this, &SkinManager::updateColorScheme ); +#endif + } + + private: +#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 ) + void updateColorScheme( Qt::ColorScheme scheme ) + { + if ( QGuiApplication::desktopSettingsAware() ) + { + skin()->setColorScheme( + static_cast< QskSkin::ColorScheme >( scheme ) ); + } + } +#endif }; } @@ -53,6 +70,11 @@ static inline QString qskResolvedPath( const QString& path ) namespace { + /* + We could use QFactoryLoader, but as it is again a "private" class + and does a couple of hardcoded things we don't need ( like always resolving + from the application library path ) we prefer having our own code. + */ class FactoryLoader final : public QPluginLoader { public: @@ -365,6 +387,7 @@ class QskSkinManager::PrivateData FactoryMap factoryMap; QPointer< QskSkin > skin; + QskAnimationHint transitionHint = 500; bool pluginsRegistered : 1; }; @@ -532,47 +555,49 @@ void QskSkinManager::setSkin( QskSkin* skin ) if ( m_data->skin == skin ) return; - if ( skin && skin->parent() == nullptr ) - skin->setParent( this ); - const auto oldSkin = m_data->skin; m_data->skin = skin; + if ( skin ) + { + if ( skin->parent() == nullptr ) + skin->setParent( this ); + + connect( skin, &QskSkin::colorSchemeChanged, + this, &QskSkinManager::colorSchemeChanged ); + } + if ( oldSkin ) { - if ( oldSkin->parent() == this ) - delete oldSkin; + disconnect( oldSkin, &QskSkin::colorSchemeChanged, + this, &QskSkinManager::colorSchemeChanged ); } Q_EMIT skinChanged( skin ); + + if ( skin && oldSkin && m_data->transitionHint.isValid() ) + { + QskSkinTransition transition; + transition.setSourceSkin( oldSkin ); + transition.setTargetSkin( skin ); + transition.run( m_data->transitionHint ); + } + + if ( oldSkin && oldSkin->parent() == this ) + delete oldSkin; } QskSkin* QskSkinManager::setSkin( const QString& name ) { - if ( m_data->skin && ( m_data->skin->objectName() == name ) ) - return m_data->skin; - - auto colorScheme = QskSkin::UnknownScheme; - if ( m_data->skin ) - colorScheme = m_data->skin->colorScheme(); - - auto skin = createSkin( name, colorScheme ); - if ( skin == nullptr ) - return nullptr; - - if ( skin->parent() == nullptr ) - skin->setParent( this ); - - const auto oldSkin = m_data->skin; - - m_data->skin = skin; - - if ( oldSkin ) + if ( !( m_data->skin && ( m_data->skin->objectName() == name ) ) ) { - Q_EMIT skinChanged( skin ); + auto colorScheme = QskSkin::UnknownScheme; + if ( m_data->skin ) + colorScheme = m_data->skin->colorScheme(); - if ( oldSkin->parent() == this ) - delete oldSkin; + auto skin = createSkin( name, colorScheme ); + if ( skin ) + setSkin( skin ); } return m_data->skin; @@ -599,4 +624,14 @@ QskSkin* QskSkinManager::skin() return m_data->skin; } +void QskSkinManager::setTransitionHint( const QskAnimationHint& hint ) +{ + m_data->transitionHint = hint; +} + +QskAnimationHint QskSkinManager::transitionHint() const +{ + return m_data->transitionHint; +} + #include "moc_QskSkinManager.cpp" diff --git a/src/controls/QskSkinManager.h b/src/controls/QskSkinManager.h index d3992293..188951cc 100644 --- a/src/controls/QskSkinManager.h +++ b/src/controls/QskSkinManager.h @@ -13,6 +13,7 @@ #include class QskSkinFactory; +class QskAnimationHint; #if defined( qskSkinManager ) #undef qskSkinManager @@ -48,8 +49,12 @@ class QSK_EXPORT QskSkinManager : public QObject QskSkin* setSkin( const QString& ); QString skinName() const; + void setTransitionHint( const QskAnimationHint& ); + QskAnimationHint transitionHint() const; + Q_SIGNALS: void skinChanged( QskSkin* ); + void colorSchemeChanged( QskSkin::ColorScheme ); protected: QskSkinManager(); diff --git a/support/SkinnyNamespace.cpp b/support/SkinnyNamespace.cpp index ae84756c..498d4c3d 100644 --- a/support/SkinnyNamespace.cpp +++ b/support/SkinnyNamespace.cpp @@ -7,8 +7,6 @@ #include #include -#include -#include #include #include @@ -131,7 +129,7 @@ static bool pluginPath = initPluginPath(); Q_COREAPP_STARTUP_FUNCTION( initFonts ) -void Skinny::changeSkin( QskAnimationHint hint ) +void Skinny::changeSkin() { const auto names = qskSkinManager->skinNames(); if ( names.size() > 1 ) @@ -139,46 +137,21 @@ void Skinny::changeSkin( QskAnimationHint hint ) auto index = names.indexOf( qskSkinManager->skinName() ); index = ( index + 1 ) % names.size(); - setSkin( index, hint ); + qskSkinManager->setSkin( names[ index ] ); } } -void Skinny::setSkin( int index, QskAnimationHint hint ) +void Skinny::changeColorScheme() { - const auto names = qskSkinManager->skinNames(); - if ( names.size() <= 1 ) - return; - - if ( index == names.indexOf( qskSkinManager->skinName() ) ) - return; - - QskSkinTransition transition; - transition.setSourceSkin( qskSkinManager->skin() ); - - if ( auto skin = qskSkinManager->setSkin( names[ index ] ) ) + if ( auto skin = qskSkinManager->skin() ) { - transition.setTargetSkin( skin ); - transition.run( hint ); + const auto colorScheme = ( skin->colorScheme() == QskSkin::LightScheme ) + ? QskSkin::DarkScheme : QskSkin::LightScheme; + + skin->setColorScheme( colorScheme ); } } -void Skinny::changeColorScheme( QskAnimationHint hint ) -{ - auto skin = qskSkinManager->skin(); - - QskSkinTransition transition; - transition.setMask( QskSkinTransition::Color ); - transition.setSourceSkin( skin ); - - const auto colorScheme = ( skin->colorScheme() == QskSkin::LightScheme ) - ? QskSkin::DarkScheme : QskSkin::LightScheme; - - skin->setColorScheme( colorScheme ); - - transition.setTargetSkin( skin ); - transition.run( hint ); -} - void Skinny::changeFonts( int increment ) { auto skin = qskSkinManager->skin(); diff --git a/support/SkinnyNamespace.h b/support/SkinnyNamespace.h index 1ee27fc6..1bbafc27 100644 --- a/support/SkinnyNamespace.h +++ b/support/SkinnyNamespace.h @@ -10,9 +10,8 @@ namespace Skinny { - SKINNY_EXPORT void changeSkin( QskAnimationHint hint = 500 ); - SKINNY_EXPORT void changeColorScheme( QskAnimationHint hint = 500 ); - SKINNY_EXPORT void setSkin( int index, QskAnimationHint hint = 500 ); + SKINNY_EXPORT void changeSkin(); + SKINNY_EXPORT void changeColorScheme(); SKINNY_EXPORT void changeFonts( int increment ); SKINNY_EXPORT void init(); }