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() )
&& ( 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,
qskSkinManager, [ this ] { updateSkin(); } );
QObject::connect( qskSkinManager, &QskSkinManager::colorSchemeChanged,
qskSkinManager, [ this ] { updateSkin(); } );
}
inline void insert( QskQuickItem* item )

View File

@ -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 );
}

View File

@ -6,6 +6,8 @@
#include "QskSkinManager.h"
#include "QskSkinFactory.h"
#include "QskSkin.h"
#include "QskSkinTransition.h"
#include "QskAnimationHint.h"
#include <qdir.h>
#include <qglobalstatic.h>
@ -21,16 +23,31 @@
#include <qstylehints.h>
#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"

View File

@ -13,6 +13,7 @@
#include <memory>
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();

View File

@ -7,8 +7,6 @@
#include <QskSkinManager.h>
#include <QskSkin.h>
#include <QskSkinTransition.h>
#include <QskAnimationHint.h>
#include <QGuiApplication>
#include <QByteArray>
@ -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();

View File

@ -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();
}