Add custom application color picker in global settings

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
This commit is contained in:
Kellermorph
2026-09-21 21:54:50 +02:00
parent 61f5e5e502
commit 5d033bf1b2
6 changed files with 148 additions and 11 deletions
+82 -1
View File
@@ -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
+1
View File
@@ -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 &);
+8
View File
@@ -20,7 +20,9 @@
#include <QApplication>
#include <QColor>
#include <QImage>
#include <QMdiArea>
#include <QStyle>
#include <QTabBar>
#include <QWidget>
#include <cmath>
@@ -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<QTabBar *>(widget) || qobject_cast<QMdiArea *>(widget))
widget->update();
}
@@ -23,6 +23,7 @@
#include "../../utils/qetsettings.h"
#include "../../utils/qetutils.h"
#include "../../qetmessagebox.h"
#include "../nokde/kcolorbutton.h"
#include <QFileDialog>
#include <QFontDialog>
#include <QSettings>
@@ -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);
}
@@ -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();
@@ -23,15 +23,26 @@
<attribute name="title">
<string>Apparence</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="m_use_system_color_cb">
<property name="text">
<string>Utiliser les couleurs du système</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="m_system_color_layout">
<item>
<widget class="QCheckBox" name="m_use_system_color_cb">
<property name="text">
<string>Utiliser les couleurs du système</string>
</property>
</widget>
</item>
<item>
<widget class="KColorButton" name="m_custom_app_color_kpb">
<property name="toolTip">
<string>Couleur de l'application</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -1161,4 +1172,11 @@ Vous pouvez spécifier ici la valeur par défaut de ce champ pour les éléments
</tabstops>
<resources/>
<connections/>
<customwidgets>
<customwidget>
<class>KColorButton</class>
<extends>QPushButton</extends>
<header>nokde/kcolorbutton.h</header>
</customwidget>
</customwidgets>
</ui>