From 5d033bf1b2d1a903244ff520dcfb4bbb2540b782 Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Mon, 21 Sep 2026 21:54:50 +0200 Subject: [PATCH] Add custom application color picker in global settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a KColorButton next to the 'Utiliser les couleurs du système' checkbox in the Apparence settings tab: - When the checkbox is active (default), system colors are used and the color button is disabled - When the checkbox is inactive, the color button becomes active and lets the user pick any color for the entire application - useCustomPalette() builds a full QPalette from the chosen color with proper light/dark text contrast, button shading, and icon theme switching - The chosen color is persisted in QSettings as 'customapplicationcolor' and restored on next startup Files changed: - sources/ui/configpage/generalconfigurationpage.ui: HBoxLayout with checkbox + KColorButton, customwidget declaration - sources/ui/configpage/generalconfigurationpage.h: new slot - sources/ui/configpage/generalconfigurationpage.cpp: load/save custom color, enable/disable logic, toggled slot - sources/qetapp.h: useCustomPalette() declaration - sources/qetapp.cpp: useCustomPalette() implementation, startup restore of custom color --- sources/qetapp.cpp | 83 ++++++++++++++++++- sources/qetapp.h | 1 + sources/qetpalette.cpp | 8 ++ .../configpage/generalconfigurationpage.cpp | 30 ++++++- .../ui/configpage/generalconfigurationpage.h | 1 + .../ui/configpage/generalconfigurationpage.ui | 36 ++++++-- 6 files changed, 148 insertions(+), 11 deletions(-) diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp index f24aade63..ccbcd7eac 100644 --- a/sources/qetapp.cpp +++ b/sources/qetapp.cpp @@ -1816,6 +1816,81 @@ void QETApp::useSystemPalette(bool use) { QET::Palette::refreshStyleSheets(); } +/** + @brief QETApp::useCustomPalette + Apply a user-chosen color as the application-wide palette. + Builds a full QPalette from \a color, keeping the system palette + as a fallback for roles we don't touch. + @param color the user-chosen base color +*/ +void QETApp::useCustomPalette(const QColor &color) { + if (!color.isValid()) + return; + + // Derive readable text colors from the chosen color. + const bool dark = color.lightness() < 128; + const QColor text = dark ? QColor(220, 220, 220) : QColor(30, 30, 30); + const QColor disabled_text = dark ? QColor(175, 175, 175) : QColor(128, 128, 128); + + // Slightly lighter/darker for button and window shading. + QColor button = color; + button = QColor::fromHslF(color.hslHueF(), + color.hslSaturationF(), + dark ? qMin(color.lightnessF() + 0.08, 1.0) + : qMax(color.lightnessF() - 0.08, 0.0)); + QColor light = QColor::fromHslF(color.hslHueF(), + color.hslSaturationF(), + dark ? qMin(color.lightnessF() + 0.15, 1.0) + : qMax(color.lightnessF() - 0.15, 0.0)); + QColor mid = QColor::fromHslF(color.hslHueF(), + color.hslSaturationF(), + dark ? qMin(color.lightnessF() + 0.04, 1.0) + : qMax(color.lightnessF() - 0.04, 0.0)); + QColor dark_c = QColor::fromHslF(color.hslHueF(), + color.hslSaturationF(), + dark ? qMin(color.lightnessF() - 0.04, 1.0) + : qMax(color.lightnessF() - 0.12, 0.0)); + QColor shadow = QColor::fromHslF(color.hslHueF(), + color.hslSaturationF(), + dark ? qMin(color.lightnessF() - 0.10, 1.0) + : qMax(color.lightnessF() - 0.20, 0.0)); + + QPalette p; + // Active and Inactive get the same colors; only Disabled differs. + for (auto group : {QPalette::Active, QPalette::Inactive}) { + p.setColor(group, QPalette::Window, color); + p.setColor(group, QPalette::WindowText, text); + p.setColor(group, QPalette::Base, color); + p.setColor(group, QPalette::AlternateBase, button); + p.setColor(group, QPalette::Text, text); + p.setColor(group, QPalette::Button, button); + p.setColor(group, QPalette::ButtonText, text); + p.setColor(group, QPalette::BrightText, dark ? QColor(255,90,90) : Qt::white); + p.setColor(group, QPalette::Highlight, QColor(30, 96, 176)); + p.setColor(group, QPalette::HighlightedText, Qt::white); + p.setColor(group, QPalette::ToolTipBase, button); + p.setColor(group, QPalette::ToolTipText, text); + p.setColor(group, QPalette::Light, light); + p.setColor(group, QPalette::Midlight, mid); + p.setColor(group, QPalette::Mid, mid); + p.setColor(group, QPalette::Dark, dark_c); + p.setColor(group, QPalette::Shadow, shadow); +#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) + p.setColor(group, QPalette::Accent, QColor(30, 96, 176)); +#endif + } + p.setColor(QPalette::Disabled, QPalette::WindowText, disabled_text); + p.setColor(QPalette::Disabled, QPalette::Text, disabled_text); + p.setColor(QPalette::Disabled, QPalette::ButtonText, disabled_text); + + qApp->setPalette(p); + qApp->setStyleSheet(QString()); + + // Switch icon theme to match light/dark. + applyIconTheme(p); + QET::Palette::refreshStyleSheets(); +} + /** @brief QETApp::quitQET Request the closing of all windows; @@ -2404,7 +2479,13 @@ void QETApp::initStyle() //Apply or not the system style QSettings settings; - useSystemPalette(settings.value("usesystemcolors", true).toBool()); + if (settings.value("usesystemcolors", true).toBool()) { + useSystemPalette(true); + } else if (settings.contains("customapplicationcolor")) { + useCustomPalette(QColor(settings.value("customapplicationcolor").toString())); + } else { + useSystemPalette(false); + } #if defined(Q_OS_MACOS) && QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) // Setting an application palette stops Qt from following the OS diff --git a/sources/qetapp.h b/sources/qetapp.h index ad249fd84..402e504fe 100644 --- a/sources/qetapp.h +++ b/sources/qetapp.h @@ -263,6 +263,7 @@ class QETApp : public QObject void setMainWindowVisible(QMainWindow *, bool); void invertMainWindowVisibility(QWidget *); void useSystemPalette(bool); + void useCustomPalette(const QColor &color); void quitQET(); void checkRemainingWindows(); void openFiles(const QETArguments &); diff --git a/sources/qetpalette.cpp b/sources/qetpalette.cpp index 8b080eeff..e8910a297 100644 --- a/sources/qetpalette.cpp +++ b/sources/qetpalette.cpp @@ -20,7 +20,9 @@ #include #include #include +#include #include +#include #include #include @@ -307,4 +309,10 @@ void QET::Palette::refreshStyleSheets() for (QWidget *widget : widgets) if (!widget->styleSheet().isEmpty()) widget->setStyleSheet(widget->styleSheet()); + + // Force an immediate repaint on tab bars and MDI areas so their text + // updates together with the rest of the UI, not one event loop later. + for (QWidget *widget : widgets) + if (qobject_cast(widget) || qobject_cast(widget)) + widget->update(); } diff --git a/sources/ui/configpage/generalconfigurationpage.cpp b/sources/ui/configpage/generalconfigurationpage.cpp index 70ad81599..685d91a3d 100644 --- a/sources/ui/configpage/generalconfigurationpage.cpp +++ b/sources/ui/configpage/generalconfigurationpage.cpp @@ -23,6 +23,7 @@ #include "../../utils/qetsettings.h" #include "../../utils/qetutils.h" #include "../../qetmessagebox.h" +#include "../nokde/kcolorbutton.h" #include #include #include @@ -74,6 +75,12 @@ GeneralConfigurationPage::GeneralConfigurationPage(QWidget *parent) : ui->DiagramEditor_Grid_PointSize_min_sb->setValue(settings.value("diagrameditor/grid_pointsize_min", 1).toInt()); ui->DiagramEditor_Grid_PointSize_max_sb->setValue(settings.value("diagrameditor/grid_pointsize_max", 1).toInt()); ui->m_use_system_color_cb->setChecked(settings.value("usesystemcolors", "true").toBool()); + bool sysColors = ui->m_use_system_color_cb->isChecked(); + ui->m_custom_app_color_kpb->setEnabled(!sysColors); + if (settings.contains("customapplicationcolor")) + ui->m_custom_app_color_kpb->setColor(QColor(settings.value("customapplicationcolor").toString())); + else + ui->m_custom_app_color_kpb->setColor(QApplication::palette().color(QPalette::Window)); bool tabbed = settings.value("diagrameditor/viewmode", "tabbed") == "tabbed"; if(tabbed) ui->m_use_tab_mode_rb->setChecked(true); @@ -206,7 +213,17 @@ void GeneralConfigurationPage::applyConf() bool must_use_system_colors = ui->m_use_system_color_cb->isChecked(); settings.setValue("usesystemcolors", must_use_system_colors); if (was_using_system_colors != must_use_system_colors) { - QETApp::instance()->useSystemPalette(must_use_system_colors); + if (must_use_system_colors) { + QETApp::instance()->useSystemPalette(true); + } else { + QColor custom_color = ui->m_custom_app_color_kpb->color(); + settings.setValue("customapplicationcolor", custom_color.name()); + QETApp::instance()->useCustomPalette(custom_color); + } + } else if (!must_use_system_colors) { + QColor custom_color = ui->m_custom_app_color_kpb->color(); + settings.setValue("customapplicationcolor", custom_color.name()); + QETApp::instance()->useCustomPalette(custom_color); } settings.setValue("border-columns_0",ui->m_border_0->isChecked()); settings.setValue("lang", ui->m_lang_cb->itemData(ui->m_lang_cb->currentIndex()).toString()); @@ -625,3 +642,14 @@ void GeneralConfigurationPage::on_m_hdpi_round_cb_clicked(bool checked) ui->m_hdpi_round_policy_cb->setEnabled(checked); } +/** + @brief GeneralConfigurationPage::on_m_use_system_color_cb_toggled + Enable/disable the custom color picker when the system color + checkbox is toggled. + @param checked +*/ +void GeneralConfigurationPage::on_m_use_system_color_cb_toggled(bool checked) +{ + ui->m_custom_app_color_kpb->setEnabled(!checked); +} + diff --git a/sources/ui/configpage/generalconfigurationpage.h b/sources/ui/configpage/generalconfigurationpage.h index ab55fdb79..015ec8cc1 100644 --- a/sources/ui/configpage/generalconfigurationpage.h +++ b/sources/ui/configpage/generalconfigurationpage.h @@ -53,6 +53,7 @@ class GeneralConfigurationPage : public ConfigPage void on_ElementEditor_Grid_PointSize_min_sb_valueChanged(int value); void on_m_hdpi_round_cb_clicked(bool checked); + void on_m_use_system_color_cb_toggled(bool checked); private: void fillLang(); diff --git a/sources/ui/configpage/generalconfigurationpage.ui b/sources/ui/configpage/generalconfigurationpage.ui index 0b2083f2d..7813f8a0e 100644 --- a/sources/ui/configpage/generalconfigurationpage.ui +++ b/sources/ui/configpage/generalconfigurationpage.ui @@ -23,15 +23,26 @@ Apparence - - - - - Utiliser les couleurs du système - - - - + + + + + + + Utiliser les couleurs du système + + + + + + + Couleur de l'application + + + + + + Qt::Horizontal @@ -1161,4 +1172,11 @@ Vous pouvez spécifier ici la valeur par défaut de ce champ pour les éléments + + + KColorButton + QPushButton +
nokde/kcolorbutton.h
+
+