handling QStyleHints::colorSchemeChanged

This commit is contained in:
Uwe Rathmann 2024-01-30 16:46:01 +01:00
parent 5aa46b3ccc
commit 59c2e8ca33
7 changed files with 105 additions and 73 deletions

View File

@ -171,7 +171,7 @@ namespace
if ( ( index >= 0 ) && ( index < names.size() ) if ( ( index >= 0 ) && ( index < names.size() )
&& ( index != names.indexOf( qskSkinManager->skinName() ) ) ) && ( index != names.indexOf( qskSkinManager->skinName() ) ) )
{ {
Skinny::setSkin( index, 500 ); qskSkinManager->setSkin( names[index] );
} }
} }
}; };

View File

@ -79,6 +79,9 @@ namespace
*/ */
QObject::connect( qskSkinManager, &QskSkinManager::skinChanged, QObject::connect( qskSkinManager, &QskSkinManager::skinChanged,
qskSkinManager, [ this ] { updateSkin(); } ); qskSkinManager, [ this ] { updateSkin(); } );
QObject::connect( qskSkinManager, &QskSkinManager::colorSchemeChanged,
qskSkinManager, [ this ] { updateSkin(); } );
} }
inline void insert( QskQuickItem* item ) inline void insert( QskQuickItem* item )

View File

@ -13,6 +13,8 @@
#include "QskSkinHintTable.h" #include "QskSkinHintTable.h"
#include "QskStandardSymbol.h" #include "QskStandardSymbol.h"
#include "QskPlatform.h" #include "QskPlatform.h"
#include "QskSkinManager.h"
#include "QskSkinTransition.h"
#include "QskMargins.h" #include "QskMargins.h"
@ -230,8 +232,23 @@ void QskSkin::setColorScheme( ColorScheme colorScheme )
m_data->colorScheme = colorScheme; m_data->colorScheme = colorScheme;
clearHints(); const auto transitionHint = qskSkinManager->transitionHint();
initHints(); if ( transitionHint.isValid() )
{
QskSkinTransition transition;
transition.setSourceSkin( this );
clearHints();
initHints();
transition.setTargetSkin( this );
transition.run( transitionHint );
}
else
{
clearHints();
initHints();
}
Q_EMIT colorSchemeChanged( colorScheme ); Q_EMIT colorSchemeChanged( colorScheme );
} }

View File

@ -6,6 +6,8 @@
#include "QskSkinManager.h" #include "QskSkinManager.h"
#include "QskSkinFactory.h" #include "QskSkinFactory.h"
#include "QskSkin.h" #include "QskSkin.h"
#include "QskSkinTransition.h"
#include "QskAnimationHint.h"
#include <qdir.h> #include <qdir.h>
#include <qglobalstatic.h> #include <qglobalstatic.h>
@ -21,16 +23,31 @@
#include <qstylehints.h> #include <qstylehints.h>
#endif #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 namespace
{ {
class SkinManager final : public QskSkinManager 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 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 class FactoryLoader final : public QPluginLoader
{ {
public: public:
@ -365,6 +387,7 @@ class QskSkinManager::PrivateData
FactoryMap factoryMap; FactoryMap factoryMap;
QPointer< QskSkin > skin; QPointer< QskSkin > skin;
QskAnimationHint transitionHint = 500;
bool pluginsRegistered : 1; bool pluginsRegistered : 1;
}; };
@ -532,47 +555,49 @@ void QskSkinManager::setSkin( QskSkin* skin )
if ( m_data->skin == skin ) if ( m_data->skin == skin )
return; return;
if ( skin && skin->parent() == nullptr )
skin->setParent( this );
const auto oldSkin = m_data->skin; const auto oldSkin = m_data->skin;
m_data->skin = 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 )
{ {
if ( oldSkin->parent() == this ) disconnect( oldSkin, &QskSkin::colorSchemeChanged,
delete oldSkin; this, &QskSkinManager::colorSchemeChanged );
} }
Q_EMIT skinChanged( skin ); 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 ) QskSkin* QskSkinManager::setSkin( const QString& name )
{ {
if ( m_data->skin && ( m_data->skin->objectName() == 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 )
{ {
Q_EMIT skinChanged( skin ); auto colorScheme = QskSkin::UnknownScheme;
if ( m_data->skin )
colorScheme = m_data->skin->colorScheme();
if ( oldSkin->parent() == this ) auto skin = createSkin( name, colorScheme );
delete oldSkin; if ( skin )
setSkin( skin );
} }
return m_data->skin; return m_data->skin;
@ -599,4 +624,14 @@ QskSkin* QskSkinManager::skin()
return m_data->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" #include "moc_QskSkinManager.cpp"

View File

@ -13,6 +13,7 @@
#include <memory> #include <memory>
class QskSkinFactory; class QskSkinFactory;
class QskAnimationHint;
#if defined( qskSkinManager ) #if defined( qskSkinManager )
#undef qskSkinManager #undef qskSkinManager
@ -48,8 +49,12 @@ class QSK_EXPORT QskSkinManager : public QObject
QskSkin* setSkin( const QString& ); QskSkin* setSkin( const QString& );
QString skinName() const; QString skinName() const;
void setTransitionHint( const QskAnimationHint& );
QskAnimationHint transitionHint() const;
Q_SIGNALS: Q_SIGNALS:
void skinChanged( QskSkin* ); void skinChanged( QskSkin* );
void colorSchemeChanged( QskSkin::ColorScheme );
protected: protected:
QskSkinManager(); QskSkinManager();

View File

@ -7,8 +7,6 @@
#include <QskSkinManager.h> #include <QskSkinManager.h>
#include <QskSkin.h> #include <QskSkin.h>
#include <QskSkinTransition.h>
#include <QskAnimationHint.h>
#include <QGuiApplication> #include <QGuiApplication>
#include <QByteArray> #include <QByteArray>
@ -131,7 +129,7 @@ static bool pluginPath = initPluginPath();
Q_COREAPP_STARTUP_FUNCTION( initFonts ) Q_COREAPP_STARTUP_FUNCTION( initFonts )
void Skinny::changeSkin( QskAnimationHint hint ) void Skinny::changeSkin()
{ {
const auto names = qskSkinManager->skinNames(); const auto names = qskSkinManager->skinNames();
if ( names.size() > 1 ) if ( names.size() > 1 )
@ -139,46 +137,21 @@ void Skinny::changeSkin( QskAnimationHint hint )
auto index = names.indexOf( qskSkinManager->skinName() ); auto index = names.indexOf( qskSkinManager->skinName() );
index = ( index + 1 ) % names.size(); 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 ( auto skin = qskSkinManager->skin() )
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 ] ) )
{ {
transition.setTargetSkin( skin ); const auto colorScheme = ( skin->colorScheme() == QskSkin::LightScheme )
transition.run( hint ); ? 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 ) void Skinny::changeFonts( int increment )
{ {
auto skin = qskSkinManager->skin(); auto skin = qskSkinManager->skin();

View File

@ -10,9 +10,8 @@
namespace Skinny namespace Skinny
{ {
SKINNY_EXPORT void changeSkin( QskAnimationHint hint = 500 ); SKINNY_EXPORT void changeSkin();
SKINNY_EXPORT void changeColorScheme( QskAnimationHint hint = 500 ); SKINNY_EXPORT void changeColorScheme();
SKINNY_EXPORT void setSkin( int index, QskAnimationHint hint = 500 );
SKINNY_EXPORT void changeFonts( int increment ); SKINNY_EXPORT void changeFonts( int increment );
SKINNY_EXPORT void init(); SKINNY_EXPORT void init();
} }