diff --git a/CMakeLists.txt b/CMakeLists.txt index c5bc4be..e09dc0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000 -DUSE_WIDGETS) find_package(Qt6 REQUIRED COMPONENTS BuildInternals Core Widgets OPTIONAL_COMPONENTS QuickControls2 LinguistTools) find_package(KF6Config) +find_package(KF6ColorScheme) get_target_property(QT_QTPATHS_EXECUTABLE Qt6::qtpaths IMPORTED_LOCATION) diff --git a/src/qt6ct-common/CMakeLists.txt b/src/qt6ct-common/CMakeLists.txt index f748167..422dd3d 100644 --- a/src/qt6ct-common/CMakeLists.txt +++ b/src/qt6ct-common/CMakeLists.txt @@ -26,5 +26,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../) add_library(qt6ct-common SHARED ${app_SRCS}) set_target_properties(qt6ct-common PROPERTIES VERSION ${QT6CT_VERSION}) -target_link_libraries(qt6ct-common PRIVATE Qt6::Gui) +target_link_libraries(qt6ct-common PRIVATE Qt6::Gui $ $) +target_compile_definitions(qt6ct-common PRIVATE $<$:KF_CONFIGCORE_LIB> $<$:KF_COLORSCHEME_LIB>) install(TARGETS qt6ct-common DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/qt6ct-common/qt6ct.cpp b/src/qt6ct-common/qt6ct.cpp index 6cd5b2c..d1e9140 100644 --- a/src/qt6ct-common/qt6ct.cpp +++ b/src/qt6ct-common/qt6ct.cpp @@ -34,6 +34,10 @@ #include #include #include +#if defined KF_CONFIGCORE_LIB && defined KF_COLORSCHEME_LIB +#include +#include +#endif #include "qt6ct.h" #ifndef QT6CT_DATADIR @@ -116,6 +120,9 @@ QStringList Qt6CT::sharedColorSchemePaths() for(const QString &p : QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) { paths << (p + QLatin1String("/qt6ct/colors")); +#if defined KF_CONFIGCORE_LIB && defined KF_COLORSCHEME_LIB + paths << (p + QLatin1String("/color-schemes")); +#endif } paths << QLatin1String(QT6CT_DATADIR"/qt6ct/colors"); paths.removeDuplicates(); @@ -143,8 +150,18 @@ QString Qt6CT::resolvePath(const QString &path) return tmp; } +bool Qt6CT::isKColorScheme(const QString &filePath) +{ + return filePath.toLower().endsWith(".colors"); +} + QPalette Qt6CT::loadColorScheme(const QString &filePath, const QPalette &fallback) { +#if defined KF_CONFIGCORE_LIB && defined KF_COLORSCHEME_LIB + if(isKColorScheme(filePath)) + return KColorScheme::createApplicationPalette(KSharedConfig::openConfig(filePath)); +#endif + QPalette customPalette; QSettings settings(filePath, QSettings::IniFormat); settings.beginGroup("ColorScheme"); diff --git a/src/qt6ct-common/qt6ct.h b/src/qt6ct-common/qt6ct.h index 78effab..a868e5e 100644 --- a/src/qt6ct-common/qt6ct.h +++ b/src/qt6ct-common/qt6ct.h @@ -67,6 +67,7 @@ class QT6CT_EXPORT Qt6CT static QString userColorSchemePath(); static QStringList sharedColorSchemePaths(); static QString resolvePath(const QString &path); + static bool isKColorScheme(const QString &filePath); static QPalette loadColorScheme(const QString &filePath, const QPalette &fallback); static void registerStyleInstance(StyleInstance *instance); diff --git a/src/qt6ct-qtplugin/qt6ctplatformtheme.cpp b/src/qt6ct-qtplugin/qt6ctplatformtheme.cpp index 9eb7d4c..c5fd8a9 100644 --- a/src/qt6ct-qtplugin/qt6ctplatformtheme.cpp +++ b/src/qt6ct-qtplugin/qt6ctplatformtheme.cpp @@ -70,6 +70,9 @@ Qt6CTPlatformTheme::Qt6CTPlatformTheme() QMetaObject::invokeMethod(this, "createFSWatcher", Qt::QueuedConnection); #endif QGuiApplication::setFont(m_generalFont); + //must be applied before Q_COREAPP_STARTUP_FUNCTION execution + if(Qt6CT::isKColorScheme(m_schemePath)) + qApp->setProperty("KDE_COLOR_SCHEME_PATH", m_schemePath); #ifdef QT_QUICKCONTROLS2_LIB //don't override the value explicitly set by the user if(QQuickStyle::name().isEmpty() || QQuickStyle::name() == QLatin1String("Fusion")) @@ -81,6 +84,7 @@ Qt6CTPlatformTheme::Qt6CTPlatformTheme() if(!QStyleFactory::keys().contains("qt6ct-style")) qCCritical(lqt6ct) << "unable to find qt6ct proxy style"; #endif + QCoreApplication::instance()->installEventFilter(this); } Qt6CTPlatformTheme::~Qt6CTPlatformTheme() @@ -177,6 +181,9 @@ void Qt6CTPlatformTheme::applySettings() QGuiApplication::setFont(m_generalFont); //apply font + if(Qt6CT::isKColorScheme(m_schemePath)) + qApp->setProperty("KDE_COLOR_SCHEME_PATH", m_schemePath); + #ifdef QT_WIDGETS_LIB if(hasWidgets()) { @@ -258,6 +265,7 @@ void Qt6CTPlatformTheme::updateSettings() void Qt6CTPlatformTheme::readSettings() { + m_schemePath.clear(); m_palette.reset(); QSettings settings(Qt6CT::configFile(), QSettings::IniFormat); @@ -268,6 +276,7 @@ void Qt6CTPlatformTheme::readSettings() if(!schemePath.isEmpty() && settings.value("custom_palette", false).toBool()) { schemePath = Qt6CT::resolvePath(schemePath); //replace environment variables + m_schemePath = schemePath; m_palette = std::make_unique(Qt6CT::loadColorScheme(schemePath, *QPlatformTheme::palette(SystemPalette))); } m_iconTheme = settings.value("icon_theme").toString(); @@ -377,3 +386,17 @@ QString Qt6CTPlatformTheme::loadStyleSheets(const QStringList &paths) content.replace(regExp, "\n"); return content; } + +//There's such a thing as KColorSchemeManager that lets the user to change the color scheme +//application-wide and we should re-apply the color scheme if KCSM resets it to the default +//which leads KColorScheme to get the color scheme from kdeglobals which won't help us. +bool Qt6CTPlatformTheme::eventFilter(QObject *obj, QEvent *e) +{ + if(obj == qApp && + e->type() == QEvent::DynamicPropertyChange && + static_cast(e)->propertyName() == "KDE_COLOR_SCHEME_PATH" && + qApp->property("KDE_COLOR_SCHEME_PATH").toString().isEmpty() && + Qt6CT::isKColorScheme(m_schemePath)) + applySettings(); + return QObject::eventFilter(obj, e); +} diff --git a/src/qt6ct-qtplugin/qt6ctplatformtheme.h b/src/qt6ct-qtplugin/qt6ctplatformtheme.h index fd348d0..358166d 100644 --- a/src/qt6ct-qtplugin/qt6ctplatformtheme.h +++ b/src/qt6ct-qtplugin/qt6ctplatformtheme.h @@ -66,6 +66,9 @@ class Qt6CTPlatformTheme : public QObject, public QGenericUnixTheme //virtual QList keyBindings(QKeySequence::StandardKey key) const; //virtual QString standardButtonText(int button) const; +protected: + bool eventFilter(QObject *obj, QEvent *e) override; + private slots: void applySettings(); #ifdef QT_WIDGETS_LIB @@ -79,7 +82,7 @@ private slots: bool hasWidgets(); #endif QString loadStyleSheets(const QStringList &paths); - QString m_style, m_iconTheme, m_userStyleSheet, m_prevStyleSheet; + QString m_style, m_schemePath, m_iconTheme, m_userStyleSheet, m_prevStyleSheet; std::unique_ptr m_palette; QFont m_generalFont, m_fixedFont; int m_doubleClickInterval; diff --git a/src/qt6ct/CMakeLists.txt b/src/qt6ct/CMakeLists.txt index 7efe4eb..578f3b0 100644 --- a/src/qt6ct/CMakeLists.txt +++ b/src/qt6ct/CMakeLists.txt @@ -32,6 +32,6 @@ endif() add_executable(qt6ct ${app_SRCS}) target_link_libraries(qt6ct PRIVATE Qt6::Widgets Qt6::WidgetsPrivate $ qt6ct-common) -target_compile_definitions(qt6ct PRIVATE $<$:KF_CONFIGCORE_LIB>) +target_compile_definitions(qt6ct PRIVATE $<$:KF_CONFIGCORE_LIB> $<$:KF_COLORSCHEME_LIB>) install(TARGETS qt6ct DESTINATION ${CMAKE_INSTALL_BINDIR}) install(FILES qt6ct.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) diff --git a/src/qt6ct/appearancepage.cpp b/src/qt6ct/appearancepage.cpp index 9732947..f5a64ae 100644 --- a/src/qt6ct/appearancepage.cpp +++ b/src/qt6ct/appearancepage.cpp @@ -75,7 +75,7 @@ AppearancePage::AppearancePage(QWidget *parent) : QMenu *menu = new QMenu(this); menu->addAction(QIcon::fromTheme("document-new"), tr("Create"), this, SLOT(createColorScheme())); m_changeColorSchemeAction = menu->addAction(QIcon::fromTheme("accessories-text-editor"), tr("Edit"), this, SLOT(changeColorScheme())); - menu->addAction(QIcon::fromTheme("edit-copy"), tr("Create a Copy"), this, SLOT(copyColorScheme())); + m_copyColorSchemeAction = menu->addAction(QIcon::fromTheme("edit-copy"), tr("Create a Copy"), this, SLOT(copyColorScheme())); m_renameColorSchemeAction = menu->addAction(tr("Rename"), this, SLOT(renameColorScheme())); menu->addSeparator(); m_removeColorSchemeAction = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Remove"), this, SLOT(removeColorScheme())); @@ -314,6 +314,7 @@ void AppearancePage::setPreviewPalette(const QPalette &p) void AppearancePage::updateActions() { + m_copyColorSchemeAction->setVisible(!Qt6CT::isKColorScheme(m_ui->colorSchemeComboBox->currentData().toString())); if(m_ui->colorSchemeComboBox->count() == 0 || !QFileInfo(m_ui->colorSchemeComboBox->currentData().toString()).isWritable()) { @@ -392,11 +393,26 @@ void AppearancePage::findColorSchemes(const QString &path) { QDir dir(path); dir.setFilter(QDir::Files); - dir.setNameFilters(QStringList() << "*.conf"); + QStringList nameFilters; + nameFilters << "*.conf"; +#if defined KF_CONFIGCORE_LIB && defined KF_COLORSCHEME_LIB + nameFilters << "*.colors"; +#endif + dir.setNameFilters(nameFilters); for(const QFileInfo &info : dir.entryInfoList()) { - m_ui->colorSchemeComboBox->addItem(info.baseName(), info.filePath()); + QString name = info.baseName(); + QString path = info.filePath(); +#if defined KF_CONFIGCORE_LIB && defined KF_COLORSCHEME_LIB + if(Qt6CT::isKColorScheme(path)) + { + KSharedConfigPtr config = KSharedConfig::openConfig(path, KConfig::SimpleConfig); + KConfigGroup group(config, "General"); + name = group.readEntry("Name", name) + " (KColorScheme)"; + } +#endif + m_ui->colorSchemeComboBox->addItem(name, path); } } diff --git a/src/qt6ct/appearancepage.h b/src/qt6ct/appearancepage.h index 73aefb3..52a2ac0 100644 --- a/src/qt6ct/appearancepage.h +++ b/src/qt6ct/appearancepage.h @@ -72,7 +72,7 @@ private slots: QStyle *m_selectedStyle = nullptr; QPalette m_customPalette; QWidget *m_previewWidget; - QAction *m_changeColorSchemeAction, *m_renameColorSchemeAction, *m_removeColorSchemeAction; + QAction *m_changeColorSchemeAction, *m_copyColorSchemeAction, *m_renameColorSchemeAction, *m_removeColorSchemeAction; Ui::PreviewForm *m_previewUi; };