Index: src/kmessagewidget.cpp =================================================================== --- src/kmessagewidget.cpp +++ src/kmessagewidget.cpp @@ -32,6 +32,115 @@ #include #include +#include +#include +#include + +//--------------------------------------------------------------------- +// KGlobalSettings +// A basic interface to read the global KDE settings store (kdeglobals) +//--------------------------------------------------------------------- +class KGlobalSettings +{ +public: + KGlobalSettings(const QString &initialGroup = QString()) + { + const QString kdeGlobals = QStandardPaths::locate(QStandardPaths::ConfigLocation, QStringLiteral("kdeglobals")); + if (!kdeGlobals.isEmpty()) { + m_settings = new QSettings(kdeGlobals, QSettings::IniFormat); + } + if (m_settings && !initialGroup.isEmpty()){ + if (m_settings->childGroups().contains(initialGroup)) { + m_settings->beginGroup(initialGroup); + } else { + delete m_settings; + m_settings = nullptr; + } + } + } + + virtual ~KGlobalSettings() + { + delete m_settings; + } + + QColor readRGBRaw(const QString &key, QColor value = QColor()) + { + if (m_settings && m_settings->contains(key)) { + QStringList rgb = m_settings->value(key).toStringList(); + if (rgb.size() >= 3) { + QColor newValue(rgb.at(0).toInt(), rgb.at(1).toInt(), rgb.at(2).toInt()); + if (newValue.isValid()) { + value = newValue; + } + } + } + return value; + } + + QColor readRGB(const QString &key, QColor value = QColor()) + { + // + if (qEnvironmentVariableIsSet("KMESSAGEWIDGET_BACKGROUND_BRIGHTNESS_MATCHED")) { + return readRGBMatched(key, value); + } else { + return readRGBRaw(key, value); + } + } + + // read an RGB triplet from in the currently active group, or return + // the default if the key doesn't exist. The returned RGB value is + // corrected so that its brightness is as close as possible to the brightness + // of the default colour. + QColor readRGBMatched(const QString &key, QColor value = QColor()) + { + qreal defaultBrightness = value.isValid() ? psychoMetricBrightness(value) : -1; + qWarning() << "Default intensity for key" << key << ":" << defaultBrightness; + if (m_settings && m_settings->contains(key)) { + QStringList rgb = m_settings->value(key).toStringList(); + if (rgb.size() >= 3) { + QColor newValue(rgb.at(0).toInt(), rgb.at(1).toInt(), rgb.at(2).toInt()); + if (newValue.isValid()) { + qreal newBrightness = psychoMetricBrightness(newValue); + if (defaultBrightness >= 0 && newBrightness > 0) { + // determine the largest factor by which we can scale the RGB + // triplet to approach the reference brightness as much as possible. + qreal brightnessScaleFactor = defaultBrightness / newBrightness; + qreal maxRGB = newValue.redF(); + if (newValue.greenF() > maxRGB) { + maxRGB = newValue.greenF(); + } + if (newValue.blueF() > maxRGB) { + maxRGB = newValue.blueF(); + } + if (maxRGB * brightnessScaleFactor > 1) { + brightnessScaleFactor = 1 / maxRGB; + } + qWarning() << "brightness scaling:" << newBrightness << ":" + << brightnessScaleFactor << "*" << newValue.redF() << newValue.greenF() << newValue.blueF(); + value.setRgbF(newValue.redF() * brightnessScaleFactor + , newValue.greenF() * brightnessScaleFactor + , newValue.blueF() * brightnessScaleFactor); + } else { + value = newValue; + } + qWarning() << "New intensity:" << psychoMetricBrightness(value); + } + } + } + return value; + } + +private: + // calculate the perceived (psycho-metric) brightness for an RGB triplet + qreal psychoMetricBrightness(QColor rgb) + { + return 0.299 * rgb.redF() + 0.586 * rgb.greenF() + 0.115 * rgb.blueF(); + } + + QSettings *m_settings = nullptr; +}; + //--------------------------------------------------------------------- // KMessageWidgetPrivate //--------------------------------------------------------------------- @@ -258,30 +367,34 @@ { d->messageType = type; QColor bgBaseColor; + const QPalette palette = QGuiApplication::palette(); - // We have to hardcode colors here because KWidgetsAddons is a tier 1 framework - // and therefore can't depend on any other KDE Frameworks - // The following RGB color values come from the "default" scheme in kcolorscheme.cpp + // We cannot use KColorScheme here because KWidgetsAddons is a tier 1 framework + // and therefore can't depend on any other KDE Frameworks. We thus try to get + // the colours that interest us directly from the global settings store using QSettings. + // It that fails we use hardcoded colours, or the highlight colour (for Information). + // The hardcoded RGB color bgBaseColors come from the "default" scheme in kcolorscheme.cpp + KGlobalSettings settings(QStringLiteral("Colors:Window")); switch (type) { case Positive: - bgBaseColor.setRgb(39, 174, 96); // Window: ForegroundPositive + bgBaseColor = settings.readRGB(QStringLiteral("ForegroundPositive"), QColor(39, 174, 96)); break; case Information: - bgBaseColor.setRgb(61, 174, 233); // Window: ForegroundActive + bgBaseColor = settings.readRGB(QStringLiteral("ForegroundActive"), palette.highlight().color()); break; case Warning: - bgBaseColor.setRgb(246, 116, 0); // Window: ForegroundNeutral + bgBaseColor = settings.readRGB(QStringLiteral("ForegroundNeutral"), QColor(246, 116, 0)); break; case Error: - bgBaseColor.setRgb(218, 68, 83); // Window: ForegroundNegative + bgBaseColor = settings.readRGB(QStringLiteral("ForegroundNegative"), QColor(218, 68, 83)); break; } const qreal bgBaseColorAlpha = 0.2; bgBaseColor.setAlphaF(bgBaseColorAlpha); - const QPalette palette = QGuiApplication::palette(); const QColor windowColor = palette.window().color(); - const QColor textColor = palette.text().color(); + // prefer the theme's normal foreground colour for text for more reliable readability with dark themes + const QColor textColor = settings.readRGBRaw(QStringLiteral("ForegroundNormal"), palette.text().color()); const QColor border = bgBaseColor; // Generate a final background color from overlaying bgBaseColor over windowColor