File indexing completed on 2024-03-24 15:25:56

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kcolorscheme.h"
0009 #include "kcolorschemehelpers_p.h"
0010 
0011 #include "kconfigwidgets_debug.h"
0012 
0013 #include <KColorUtils>
0014 #include <KConfig>
0015 #include <KConfigGroup>
0016 
0017 #include <QBrush>
0018 #include <QColor>
0019 
0020 // BEGIN StateEffects
0021 StateEffects::StateEffects(QPalette::ColorGroup state, const KSharedConfigPtr &config)
0022     : _color(0, 0, 0, 0) //, _chain(0) not needed yet
0023 {
0024     QString group;
0025     if (state == QPalette::Disabled) {
0026         group = QStringLiteral("ColorEffects:Disabled");
0027     } else if (state == QPalette::Inactive) {
0028         group = QStringLiteral("ColorEffects:Inactive");
0029     }
0030 
0031     for (auto &effect : _effects) {
0032         effect = 0;
0033     }
0034 
0035     // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
0036     if (!group.isEmpty()) {
0037         KConfigGroup cfg(config, group);
0038         const bool enabledByDefault = (state == QPalette::Disabled);
0039         if (cfg.readEntry("Enable", enabledByDefault)) {
0040             _effects[Intensity] = cfg.readEntry("IntensityEffect", (int)(state == QPalette::Disabled ? IntensityDarken : IntensityNoEffect));
0041             _effects[Color] = cfg.readEntry("ColorEffect", (int)(state == QPalette::Disabled ? ColorNoEffect : ColorDesaturate));
0042             _effects[Contrast] = cfg.readEntry("ContrastEffect", (int)(state == QPalette::Disabled ? ContrastFade : ContrastTint));
0043             _amount[Intensity] = cfg.readEntry("IntensityAmount", state == QPalette::Disabled ? 0.10 : 0.0);
0044             _amount[Color] = cfg.readEntry("ColorAmount", state == QPalette::Disabled ? 0.0 : -0.9);
0045             _amount[Contrast] = cfg.readEntry("ContrastAmount", state == QPalette::Disabled ? 0.65 : 0.25);
0046             if (_effects[Color] > ColorNoEffect) {
0047                 _color = cfg.readEntry("Color", state == QPalette::Disabled ? QColor(56, 56, 56) : QColor(112, 111, 110));
0048             }
0049         }
0050     }
0051 }
0052 
0053 QBrush StateEffects::brush(const QBrush &background) const
0054 {
0055     QColor color = background.color(); // TODO - actually work on brushes
0056     switch (_effects[Intensity]) {
0057     case IntensityShade:
0058         color = KColorUtils::shade(color, _amount[Intensity]);
0059         break;
0060     case IntensityDarken:
0061         color = KColorUtils::darken(color, _amount[Intensity]);
0062         break;
0063     case IntensityLighten:
0064         color = KColorUtils::lighten(color, _amount[Intensity]);
0065         break;
0066     }
0067     switch (_effects[Color]) {
0068     case ColorDesaturate:
0069         color = KColorUtils::darken(color, 0.0, 1.0 - _amount[Color]);
0070         break;
0071     case ColorFade:
0072         color = KColorUtils::mix(color, _color, _amount[Color]);
0073         break;
0074     case ColorTint:
0075         color = KColorUtils::tint(color, _color, _amount[Color]);
0076         break;
0077     }
0078     return QBrush(color);
0079 }
0080 
0081 QBrush StateEffects::brush(const QBrush &foreground, const QBrush &background) const
0082 {
0083     QColor color = foreground.color(); // TODO - actually work on brushes
0084     QColor bg = background.color();
0085     // Apply the foreground effects
0086     switch (_effects[Contrast]) {
0087     case ContrastFade:
0088         color = KColorUtils::mix(color, bg, _amount[Contrast]);
0089         break;
0090     case ContrastTint:
0091         color = KColorUtils::tint(color, bg, _amount[Contrast]);
0092         break;
0093     }
0094     // Now apply global effects
0095     return brush(color);
0096 }
0097 // END StateEffects
0098 
0099 // BEGIN default colors
0100 struct SerializedColors {
0101     QColor NormalBackground;
0102     QColor AlternateBackground;
0103     QColor NormalText;
0104     QColor InactiveText;
0105     QColor ActiveText;
0106     QColor LinkText;
0107     QColor VisitedText;
0108     QColor NegativeText;
0109     QColor NeutralText;
0110     QColor PositiveText;
0111 };
0112 
0113 struct DecorationColors {
0114     QColor Focus;
0115     QColor Hover;
0116 };
0117 
0118 // clang-format off
0119 // These numbers come from the default color scheme which is currently
0120 // Breeze Light ([breeze repo]/colors/BreezeLight.colors)
0121 static const SerializedColors defaultViewColors = {
0122     { 255, 255, 255 }, // Background
0123     { 247, 247, 247 }, // Alternate
0124     {  35,  38, 41  }, // Normal
0125     { 112, 125, 138 }, // Inactive
0126     {  61, 174, 233 }, // Active
0127     {  41, 128, 185 }, // Link
0128     { 155,  89, 182 }, // Visited
0129     { 218,  68,  83 }, // Negative
0130     { 246, 116,   0 }, // Neutral
0131     {  39, 174,  96 }  // Positive
0132 };
0133 
0134 static const SerializedColors defaultWindowColors = {
0135     { 239, 240, 241 }, // Background
0136     { 227, 229, 231 }, // Alternate
0137     {  35,  38, 41  }, // Normal
0138     { 112, 125, 138 }, // Inactive
0139     {  61, 174, 233 }, // Active
0140     {  41, 128, 185 }, // Link
0141     { 155,  89, 182 }, // Visited
0142     { 218,  68,  83 }, // Negative
0143     { 246, 116,   0 }, // Neutral
0144     {  39, 174,  96 }  // Positive
0145 };
0146 
0147 static const SerializedColors defaultButtonColors = {
0148     { 252, 252, 252 }, // Background
0149     { 163, 212, 250 }, // Alternate
0150     {  35,  38, 41  }, // Normal
0151     { 112, 125, 138 }, // Inactive
0152     {  61, 174, 233 }, // Active
0153     {  41, 128, 185 }, // Link
0154     { 155,  89, 182 }, // Visited
0155     { 218,  68,  83 }, // Negative
0156     { 246, 116,   0 }, // Neutral
0157     {  39, 174,  96 }  // Positive
0158 };
0159 
0160 static const SerializedColors defaultSelectionColors = {
0161     {  61, 174, 233 }, // Background
0162     { 163, 212, 250 }, // Alternate
0163     { 255, 255, 255 }, // Normal
0164     { 112, 125, 138 }, // Inactive
0165     { 255, 255, 255 }, // Active
0166     { 253, 188,  75 }, // Link
0167     { 155,  89, 182 }, // Visited
0168     { 176,  55,  69 }, // Negative
0169     { 198,  92,   0 }, // Neutral
0170     {  23, 104,  57 }  // Positive
0171 };
0172 
0173 static const SerializedColors defaultTooltipColors = {
0174     { 247, 247, 247 }, // Background
0175     { 239, 240, 241 }, // Alternate
0176     {  35,  38,  41 }, // Normal
0177     { 112, 125, 138 }, // Inactive
0178     {  61, 174, 233 }, // Active
0179     {  41, 128, 185 }, // Link
0180     { 155,  89, 182 }, // Visited
0181     { 218,  68,  83 }, // Negative
0182     { 246, 116,   0 }, // Neutral
0183     {  39, 174,  96 }  // Positive
0184 };
0185 
0186 static const SerializedColors defaultComplementaryColors = {
0187     {  42,  46,  50 }, // Background
0188     {  27,  30,  32 }, // Alternate
0189     { 252, 252, 252 }, // Normal
0190     { 161, 169, 177 }, // Inactive
0191     {  61, 174, 233 }, // Active
0192     {  29, 153, 243 }, // Link
0193     { 155,  89, 182 }, // Visited
0194     { 218,  68,  83 }, // Negative
0195     { 246, 116,   0 }, // Neutral
0196     {  39, 174,  96 }  // Positive
0197 };
0198 
0199 static const SerializedColors defaultHeaderColors = {
0200     { 222, 224, 226 }, // Background
0201     { 239, 240, 241 }, // Alternate
0202     {  35,  38,  41 }, // Normal
0203     { 112, 125, 138 }, // Inactive
0204     {  61, 174, 233 }, // Active
0205     {  41, 128, 185 }, // Link
0206     { 155,  89, 182 }, // Visited
0207     { 218,  68,  83 }, // Negative
0208     { 246, 116,   0 }, // Neutral
0209     {  39, 174,  96 }  // Positive
0210 };
0211 
0212 static const DecorationColors defaultDecorationColors = {
0213     {  61, 174, 233 }, // Focus
0214     { 147, 206, 233 }, // Hover
0215 };
0216 // END default colors
0217 // clang-format off
0218 
0219 //BEGIN KColorSchemePrivate
0220 class KColorSchemePrivate : public QSharedData
0221 {
0222 public:
0223     explicit KColorSchemePrivate(const KSharedConfigPtr &, QPalette::ColorGroup state, KColorScheme::ColorSet set);
0224     ~KColorSchemePrivate()
0225     {
0226     }
0227 
0228     QBrush background(KColorScheme::BackgroundRole) const;
0229     QBrush foreground(KColorScheme::ForegroundRole) const;
0230     QBrush decoration(KColorScheme::DecorationRole) const;
0231     qreal contrast() const;
0232 
0233     struct Brushes {
0234         std::array<QBrush, KColorScheme::NForegroundRoles> fg;
0235         std::array<QBrush, KColorScheme::NBackgroundRoles> bg;
0236         std::array<QBrush, KColorScheme::NDecorationRoles> deco;
0237 
0238         bool operator==(const Brushes &b) const
0239         {
0240             return this == &b || (fg == b.fg && bg == b.bg && deco == b.deco);
0241         }
0242     } _brushes;
0243 
0244     qreal _contrast;
0245 };
0246 
0247 static SerializedColors loadSerializedColors(const KConfigGroup &group, const SerializedColors &defaults)
0248 {
0249     constexpr std::array configMap = {
0250         std::pair{"ForegroundNormal", &SerializedColors::NormalText},
0251         std::pair{"ForegroundInactive", &SerializedColors::InactiveText},
0252         std::pair{"ForegroundActive", &SerializedColors::ActiveText},
0253         std::pair{"ForegroundLink", &SerializedColors::LinkText},
0254         std::pair{"ForegroundVisited", &SerializedColors::VisitedText},
0255         std::pair{"ForegroundNegative", &SerializedColors::NegativeText},
0256         std::pair{"ForegroundNeutral", &SerializedColors::NeutralText},
0257         std::pair{"ForegroundPositive", &SerializedColors::PositiveText},
0258         std::pair{"BackgroundNormal", &SerializedColors::NormalBackground},
0259         std::pair{"BackgroundAlternate", &SerializedColors::AlternateBackground},
0260     };
0261     SerializedColors loadedColors;
0262     for (const auto &entry : configMap) {
0263       loadedColors.*(entry.second) = group.readEntry(entry.first, defaults.*(entry.second));
0264     }
0265     return loadedColors;
0266 }
0267 
0268 static DecorationColors loadDecorationColors(const KConfigGroup &group, const DecorationColors &defaults)
0269 {
0270     DecorationColors colors;
0271     colors.Focus = group.readEntry("DecorationFocus", defaults.Focus);
0272     colors.Hover = group.readEntry("DecorationHover", defaults.Hover);
0273     return colors;
0274 }
0275 
0276 KColorSchemePrivate::KColorSchemePrivate(const KSharedConfigPtr &config, QPalette::ColorGroup state, KColorScheme::ColorSet set)
0277 {
0278     const char *groupName = nullptr;
0279     SerializedColors defaultColors;
0280     DecorationColors defaultDecoColors = defaultDecorationColors;
0281     QBrush tint;
0282     switch (set) {
0283     case KColorScheme::Window:
0284         groupName = "Colors:Window";
0285         defaultColors = defaultWindowColors;
0286         break;
0287     case KColorScheme::Button:
0288         groupName = "Colors:Button";
0289         defaultColors = defaultButtonColors;
0290         break;
0291     case KColorScheme::Selection: {
0292         const KConfigGroup inactiveEffectGroup(config, "ColorEffects:Inactive");
0293         // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
0294         const bool inactiveSelectionEffect = inactiveEffectGroup.readEntry("ChangeSelectionColor", inactiveEffectGroup.readEntry("Enable", true));
0295         // if enabled, inactive/disabled uses Window colors instead, ala gtk
0296         // ...except tinted with the Selection:NormalBackground color so it looks more like selection
0297         if (state == QPalette::Active || (state == QPalette::Inactive && !inactiveSelectionEffect)) {
0298             groupName = "Colors:Selection";
0299            defaultColors = defaultSelectionColors;
0300         } else if (state == QPalette::Inactive) {
0301             groupName = "Colors:Window";
0302             defaultColors = defaultWindowColors;
0303             tint = KColorSchemePrivate(config, QPalette::Active, KColorScheme::Selection)._brushes.bg[KColorScheme::NormalBackground];
0304         } else { // disabled (...and still want this branch when inactive+disabled exists)
0305             groupName = "Colors:Window";
0306             defaultColors = defaultWindowColors;
0307         }
0308     } break;
0309     case KColorScheme::Tooltip:
0310         groupName = "Colors:Tooltip";
0311         defaultColors = defaultTooltipColors;
0312         break;
0313     case KColorScheme::Complementary:
0314         groupName = "Colors:Complementary";
0315         defaultColors = defaultComplementaryColors;
0316         break;
0317     case KColorScheme::Header:
0318         groupName = "Colors:Header";
0319         defaultColors = loadSerializedColors(config->group("Colors:Window"), defaultHeaderColors);
0320         defaultDecoColors = loadDecorationColors(config->group("Colors:Window"), defaultDecorationColors);
0321         break;
0322     case KColorScheme::NColorSets:
0323         qCWarning(KCONFIG_WIDGETS_LOG) << "ColorSet::NColorSets is not a valid color set value to pass to KColorScheme::KColorScheme";
0324         [[fallthrough]];
0325     case KColorScheme::View:
0326         groupName = "Colors:View";
0327         defaultColors = defaultViewColors;
0328         break;
0329     }
0330 
0331     KConfigGroup cfg(config, groupName);
0332     bool hasInactivePalette = false;
0333     if (state == QPalette::Inactive) {
0334         KConfigGroup inactiveGroup = KConfigGroup(&cfg, "Inactive");
0335         if (inactiveGroup.exists()) {
0336             cfg = inactiveGroup;
0337             hasInactivePalette = true;
0338         }
0339     }
0340 
0341     _contrast = KColorScheme::contrastF(config);
0342 
0343      const SerializedColors loadedColors = loadSerializedColors(cfg, defaultColors);
0344      const DecorationColors loadedDecoColors = loadDecorationColors(cfg, defaultDecoColors);
0345 
0346     _brushes.fg[KColorScheme::NormalText] = loadedColors.NormalText;
0347     _brushes.fg[KColorScheme::InactiveText] = loadedColors.InactiveText;
0348     _brushes.fg[KColorScheme::ActiveText] = loadedColors.ActiveText;
0349     _brushes.fg[KColorScheme::LinkText] = loadedColors.LinkText;
0350     _brushes.fg[KColorScheme::VisitedText] = loadedColors.VisitedText;
0351     _brushes.fg[KColorScheme::NegativeText] = loadedColors.NegativeText;
0352     _brushes.fg[KColorScheme::NeutralText] = loadedColors.NeutralText;
0353     _brushes.fg[KColorScheme::PositiveText] = loadedColors.PositiveText;
0354 
0355     _brushes.bg[KColorScheme::NormalBackground] = loadedColors.NormalBackground;
0356     _brushes.bg[KColorScheme::AlternateBackground] = loadedColors.AlternateBackground;
0357 
0358     _brushes.deco[KColorScheme::FocusColor] = loadedDecoColors.Focus;
0359     _brushes.deco[KColorScheme::HoverColor] = loadedDecoColors.Hover;
0360 
0361     if (tint != Qt::NoBrush) {
0362         // adjustment
0363         _brushes.bg[KColorScheme::NormalBackground] =
0364             KColorUtils::tint(_brushes.bg[KColorScheme::NormalBackground].color(), tint.color(), 0.4);
0365         _brushes.bg[KColorScheme::AlternateBackground] =
0366             KColorUtils::tint(_brushes.bg[KColorScheme::AlternateBackground].color(), tint.color(), 0.4);
0367     }
0368 
0369     // apply state adjustments
0370     if (state != QPalette::Active || (state == QPalette::Inactive && !hasInactivePalette)) {
0371         StateEffects effects(state, config);
0372         for (auto &fg : _brushes.fg) {
0373             fg = effects.brush(fg, _brushes.bg[KColorScheme::NormalBackground]);
0374         }
0375         for (auto &deco : _brushes.deco) {
0376             deco = effects.brush(deco, _brushes.bg[KColorScheme::NormalBackground]);
0377         }
0378         _brushes.bg[KColorScheme::NormalBackground] = effects.brush(_brushes.bg[KColorScheme::NormalBackground]);
0379         _brushes.bg[KColorScheme::AlternateBackground] = effects.brush(_brushes.bg[KColorScheme::AlternateBackground]);
0380     }
0381 
0382     // calculated backgrounds
0383     _brushes.bg[KColorScheme::ActiveBackground] =
0384         KColorUtils::tint(_brushes.bg[KColorScheme::NormalBackground].color(),
0385                           _brushes.fg[KColorScheme::ActiveText].color());
0386     _brushes.bg[KColorScheme::LinkBackground] =
0387         KColorUtils::tint(_brushes.bg[KColorScheme::NormalBackground].color(),
0388                           _brushes.fg[KColorScheme::LinkText].color());
0389     _brushes.bg[KColorScheme::VisitedBackground] =
0390         KColorUtils::tint(_brushes.bg[KColorScheme::NormalBackground].color(),
0391                           _brushes.fg[KColorScheme::VisitedText].color());
0392     _brushes.bg[KColorScheme::NegativeBackground] =
0393         KColorUtils::tint(_brushes.bg[KColorScheme::NormalBackground].color(),
0394                           _brushes.fg[KColorScheme::NegativeText].color());
0395     _brushes.bg[KColorScheme::NeutralBackground] =
0396         KColorUtils::tint(_brushes.bg[KColorScheme::NormalBackground].color(),
0397                           _brushes.fg[KColorScheme::NeutralText].color());
0398     _brushes.bg[KColorScheme::PositiveBackground] =
0399         KColorUtils::tint(_brushes.bg[KColorScheme::NormalBackground].color(),
0400                           _brushes.fg[KColorScheme::PositiveText].color());
0401 }
0402 
0403 QBrush KColorSchemePrivate::background(KColorScheme::BackgroundRole role) const
0404 {
0405     if (role >= KColorScheme::NormalBackground && role < KColorScheme::NBackgroundRoles) {
0406         return _brushes.bg[role];
0407     } else {
0408         return _brushes.bg[KColorScheme::NormalBackground];
0409     }
0410 }
0411 
0412 QBrush KColorSchemePrivate::foreground(KColorScheme::ForegroundRole role) const
0413 {
0414     if (role >= KColorScheme::NormalText && role < KColorScheme::NForegroundRoles) {
0415         return _brushes.fg[role];
0416     } else {
0417         return _brushes.fg[KColorScheme::NormalText];
0418     }
0419 }
0420 
0421 QBrush KColorSchemePrivate::decoration(KColorScheme::DecorationRole role) const
0422 {
0423     if (role >= KColorScheme::FocusColor && role < KColorScheme::NDecorationRoles) {
0424         return _brushes.deco[role];
0425     } else {
0426         return _brushes.deco[KColorScheme::FocusColor];
0427     }
0428 }
0429 
0430 qreal KColorSchemePrivate::contrast() const
0431 {
0432     return _contrast;
0433 }
0434 //END KColorSchemePrivate
0435 
0436 //BEGIN KColorScheme
0437 KColorScheme::KColorScheme(const KColorScheme &) = default;
0438 KColorScheme &KColorScheme::operator=(const KColorScheme &) = default;
0439 KColorScheme::KColorScheme(KColorScheme &&) = default;
0440 KColorScheme &KColorScheme::operator=(KColorScheme &&) = default;
0441 KColorScheme::~KColorScheme() = default;
0442 
0443 KColorScheme::KColorScheme(QPalette::ColorGroup state, ColorSet set, KSharedConfigPtr config)
0444     : d(new KColorSchemePrivate(config ? config : defaultConfig(), state, set))
0445 {
0446 }
0447 
0448 bool KColorScheme::operator==(const KColorScheme &other) const
0449 {
0450     return d == other.d
0451         || (d->_contrast == other.d->_contrast
0452             && d->_brushes == other.d->_brushes)
0453     ;
0454 }
0455 
0456 // static
0457 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 93)
0458 int KColorScheme::contrast()
0459 {
0460     KConfigGroup g(defaultConfig(), "KDE");
0461     return g.readEntry("contrast", 7);
0462 }
0463 #endif
0464 
0465 // static
0466 qreal KColorScheme::contrastF(const KSharedConfigPtr &config)
0467 {
0468     KConfigGroup g(config ? config : defaultConfig(), "KDE");
0469     return 0.1 * g.readEntry("contrast", 7);
0470 }
0471 
0472 QBrush KColorScheme::background(BackgroundRole role) const
0473 {
0474     return d->background(role);
0475 }
0476 
0477 QBrush KColorScheme::foreground(ForegroundRole role) const
0478 {
0479     return d->foreground(role);
0480 }
0481 
0482 QBrush KColorScheme::decoration(DecorationRole role) const
0483 {
0484     return d->decoration(role);
0485 }
0486 
0487 QColor KColorScheme::shade(ShadeRole role) const
0488 {
0489     return shade(background().color(), role, d->contrast());
0490 }
0491 
0492 QColor KColorScheme::shade(const QColor &color, ShadeRole role)
0493 {
0494     return shade(color, role, KColorScheme::contrastF());
0495 }
0496 
0497 QColor KColorScheme::shade(const QColor &color, ShadeRole role, qreal contrast, qreal chromaAdjust)
0498 {
0499     // nan -> 1.0
0500     contrast = (1.0 > contrast ? (-1.0 < contrast ? contrast : -1.0) : 1.0);
0501     qreal y = KColorUtils::luma(color);
0502     qreal yi = 1.0 - y;
0503 
0504     // handle very dark colors (base, mid, dark, shadow == midlight, light)
0505     if (y < 0.006) {
0506         switch (role) {
0507         case KColorScheme::LightShade:
0508             return KColorUtils::shade(color, 0.05 + 0.95 * contrast, chromaAdjust);
0509         case KColorScheme::MidShade:
0510             return KColorUtils::shade(color, 0.01 + 0.20 * contrast, chromaAdjust);
0511         case KColorScheme::DarkShade:
0512             return KColorUtils::shade(color, 0.02 + 0.40 * contrast, chromaAdjust);
0513         default:
0514             return KColorUtils::shade(color, 0.03 + 0.60 * contrast, chromaAdjust);
0515         }
0516     }
0517 
0518     // handle very light colors (base, midlight, light == mid, dark, shadow)
0519     if (y > 0.93) {
0520         switch (role) {
0521         case KColorScheme::MidlightShade:
0522             return KColorUtils::shade(color, -0.02 - 0.20 * contrast, chromaAdjust);
0523         case KColorScheme::DarkShade:
0524             return KColorUtils::shade(color, -0.06 - 0.60 * contrast, chromaAdjust);
0525         case KColorScheme::ShadowShade:
0526             return KColorUtils::shade(color, -0.10 - 0.90 * contrast, chromaAdjust);
0527         default:
0528             return KColorUtils::shade(color, -0.04 - 0.40 * contrast, chromaAdjust);
0529         }
0530     }
0531 
0532     // handle everything else
0533     qreal lightAmount = (0.05 + y * 0.55) * (0.25 + contrast * 0.75);
0534     qreal darkAmount = (- y) * (0.55 + contrast * 0.35);
0535     switch (role) {
0536     case KColorScheme::LightShade:
0537         return KColorUtils::shade(color, lightAmount, chromaAdjust);
0538     case KColorScheme::MidlightShade:
0539         return KColorUtils::shade(color, (0.15 + 0.35 * yi) * lightAmount, chromaAdjust);
0540     case KColorScheme::MidShade:
0541         return KColorUtils::shade(color, (0.35 + 0.15 * y) * darkAmount, chromaAdjust);
0542     case KColorScheme::DarkShade:
0543         return KColorUtils::shade(color, darkAmount, chromaAdjust);
0544     default:
0545         return KColorUtils::darken(KColorUtils::shade(color, darkAmount, chromaAdjust), 0.5 + 0.3 * y);
0546     }
0547 }
0548 
0549 void KColorScheme::adjustBackground(QPalette &palette, BackgroundRole newRole, QPalette::ColorRole color,
0550                                     ColorSet set, KSharedConfigPtr config)
0551 {
0552     palette.setBrush(QPalette::Active,   color, KColorScheme(QPalette::Active,   set, config).background(newRole));
0553     palette.setBrush(QPalette::Inactive, color, KColorScheme(QPalette::Inactive, set, config).background(newRole));
0554     palette.setBrush(QPalette::Disabled, color, KColorScheme(QPalette::Disabled, set, config).background(newRole));
0555 }
0556 
0557 void KColorScheme::adjustForeground(QPalette &palette, ForegroundRole newRole, QPalette::ColorRole color,
0558                                     ColorSet set, KSharedConfigPtr config)
0559 {
0560     palette.setBrush(QPalette::Active,   color, KColorScheme(QPalette::Active,   set, config).foreground(newRole));
0561     palette.setBrush(QPalette::Inactive, color, KColorScheme(QPalette::Inactive, set, config).foreground(newRole));
0562     palette.setBrush(QPalette::Disabled, color, KColorScheme(QPalette::Disabled, set, config).foreground(newRole));
0563 }
0564 
0565 bool KColorScheme::isColorSetSupported(const KSharedConfigPtr &config, KColorScheme::ColorSet set)
0566 {
0567     switch (set) {
0568         case View:
0569             return config->hasGroup("Colors:View");
0570         case Window:
0571             return config->hasGroup("Colors:Window");
0572         case Button:
0573             return config->hasGroup("Colors:Button");
0574         case Selection:
0575             return config->hasGroup("Colors:Selection");
0576         case Tooltip:
0577             return config->hasGroup("Colors:Tooltip");
0578         case Complementary:
0579             return config->hasGroup("Colors:Complementary");
0580         case Header:
0581             return config->hasGroup("Colors:Header");
0582         case NColorSets:
0583             break;
0584     }
0585 
0586     return false;
0587 }
0588 
0589 QPalette KColorScheme::createApplicationPalette(const KSharedConfigPtr &config)
0590 {
0591     QPalette palette;
0592 
0593     static const QPalette::ColorGroup states[QPalette::NColorGroups] = {
0594         QPalette::Active, QPalette::Inactive, QPalette::Disabled
0595     };
0596 
0597     // TT thinks tooltips shouldn't use active, so we use our active colors for all states
0598     KColorScheme schemeTooltip(QPalette::Active, KColorScheme::Tooltip, config);
0599 
0600     for (auto state : states) {
0601         KColorScheme schemeView(state, KColorScheme::View, config);
0602         KColorScheme schemeWindow(state, KColorScheme::Window, config);
0603         KColorScheme schemeButton(state, KColorScheme::Button, config);
0604         KColorScheme schemeSelection(state, KColorScheme::Selection, config);
0605 
0606         palette.setBrush(state, QPalette::WindowText, schemeWindow.foreground());
0607         palette.setBrush(state, QPalette::Window, schemeWindow.background());
0608         palette.setBrush(state, QPalette::Base, schemeView.background());
0609         palette.setBrush(state, QPalette::Text, schemeView.foreground());
0610         palette.setBrush(state, QPalette::Button, schemeButton.background());
0611         palette.setBrush(state, QPalette::ButtonText, schemeButton.foreground());
0612         palette.setBrush(state, QPalette::Highlight, schemeSelection.background());
0613         palette.setBrush(state, QPalette::HighlightedText, schemeSelection.foreground());
0614         palette.setBrush(state, QPalette::ToolTipBase, schemeTooltip.background());
0615         palette.setBrush(state, QPalette::ToolTipText, schemeTooltip.foreground());
0616 
0617         palette.setColor(state, QPalette::Light, schemeWindow.shade(KColorScheme::LightShade));
0618         palette.setColor(state, QPalette::Midlight, schemeWindow.shade(KColorScheme::MidlightShade));
0619         palette.setColor(state, QPalette::Mid, schemeWindow.shade(KColorScheme::MidShade));
0620         palette.setColor(state, QPalette::Dark, schemeWindow.shade(KColorScheme::DarkShade));
0621         palette.setColor(state, QPalette::Shadow, schemeWindow.shade(KColorScheme::ShadowShade));
0622 
0623         palette.setBrush(state, QPalette::AlternateBase, schemeView.background(KColorScheme::AlternateBackground));
0624         palette.setBrush(state, QPalette::Link, schemeView.foreground(KColorScheme::LinkText));
0625         palette.setBrush(state, QPalette::LinkVisited, schemeView.foreground(KColorScheme::VisitedText));
0626     }
0627 
0628     return palette;
0629 }
0630 
0631 //END KColorScheme