1 /* This file is part of the KDE project
2  * Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #include "kcolorscheme.h"
20 
21 #include <kconfig.h>
22 #include <kconfiggroup.h>
23 #include <ksharedconfig.h>
24 #include <kcolorutils.h>
25 
26 #include <QColor>
27 #include <QBrush>
28 #include <QWidget>
29 
30 //BEGIN StateEffects
31 class StateEffects
32 {
33 public:
34     explicit StateEffects(QPalette::ColorGroup state, const KSharedConfigPtr &);
~StateEffects()35     ~StateEffects() {} //{ delete chain; } not needed yet
36 
37     QBrush brush(const QBrush &background) const;
38     QBrush brush(const QBrush &foreground, const QBrush &background) const;
39 
40 private:
41     enum Effects {
42         // Effects
43         Intensity = 0,
44         Color = 1,
45         Contrast = 2,
46         // Intensity
47         IntensityNoEffect = 0,
48         IntensityShade = 1,
49         IntensityDarken = 2,
50         IntensityLighten = 3,
51         // Color
52         ColorNoEffect = 0,
53         ColorDesaturate = 1,
54         ColorFade = 2,
55         ColorTint = 3,
56         // Contrast
57         ContrastNoEffect = 0,
58         ContrastFade = 1,
59         ContrastTint = 2
60     };
61 
62     int _effects[3];
63     double _amount[3];
64     QColor _color;
65 //     StateEffects *_chain; not needed yet
66 };
67 
StateEffects(QPalette::ColorGroup state,const KSharedConfigPtr & config)68 StateEffects::StateEffects(QPalette::ColorGroup state, const KSharedConfigPtr &config)
69     : _color(0, 0, 0, 0) //, _chain(0) not needed yet
70 {
71     QString group;
72     if (state == QPalette::Disabled) {
73         group = QLatin1String("ColorEffects:Disabled");
74     } else if (state == QPalette::Inactive) {
75         group = QLatin1String("ColorEffects:Inactive");
76     }
77 
78     _effects[0] = 0;
79     _effects[1] = 0;
80     _effects[2] = 0;
81 
82     // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
83     if (! group.isEmpty()) {
84         KConfigGroup cfg(config, group);
85         const bool enabledByDefault = (state == QPalette::Disabled);
86         if (cfg.readEntry("Enable", enabledByDefault)) {
87             _effects[Intensity] = cfg.readEntry("IntensityEffect",
88                                                 (int)(state == QPalette::Disabled ?  IntensityDarken : IntensityNoEffect));
89             _effects[Color]     = cfg.readEntry("ColorEffect",
90                                                 (int)(state == QPalette::Disabled ?  ColorNoEffect : ColorDesaturate));
91             _effects[Contrast]  = cfg.readEntry("ContrastEffect",
92                                                 (int)(state == QPalette::Disabled ?  ContrastFade : ContrastTint));
93             _amount[Intensity]  = cfg.readEntry("IntensityAmount", state == QPalette::Disabled ? 0.10 :  0.0);
94             _amount[Color]      = cfg.readEntry("ColorAmount", state == QPalette::Disabled ?  0.0 : -0.9);
95             _amount[Contrast]   = cfg.readEntry("ContrastAmount", state == QPalette::Disabled ? 0.65 :  0.25);
96             if (_effects[Color] > ColorNoEffect) {
97                 _color = cfg.readEntry("Color", state == QPalette::Disabled ?  QColor(56, 56, 56) : QColor(112, 111, 110));
98             }
99         }
100     }
101 }
102 
brush(const QBrush & background) const103 QBrush StateEffects::brush(const QBrush &background) const
104 {
105     QColor color = background.color(); // TODO - actually work on brushes
106     switch (_effects[Intensity]) {
107     case IntensityShade:
108         color = KColorUtils::shade(color, _amount[Intensity]);
109         break;
110     case IntensityDarken:
111         color = KColorUtils::darken(color, _amount[Intensity]);
112         break;
113     case IntensityLighten:
114         color = KColorUtils::lighten(color, _amount[Intensity]);
115         break;
116     }
117     switch (_effects[Color]) {
118     case ColorDesaturate:
119         color = KColorUtils::darken(color, 0.0, 1.0 - _amount[Color]);
120         break;
121     case ColorFade:
122         color = KColorUtils::mix(color, _color, _amount[Color]);
123         break;
124     case ColorTint:
125         color = KColorUtils::tint(color, _color, _amount[Color]);
126         break;
127     }
128     return QBrush(color);
129 }
130 
brush(const QBrush & foreground,const QBrush & background) const131 QBrush StateEffects::brush(const QBrush &foreground, const QBrush &background) const
132 {
133     QColor color = foreground.color(); // TODO - actually work on brushes
134     QColor bg = background.color();
135     // Apply the foreground effects
136     switch (_effects[Contrast]) {
137     case ContrastFade:
138         color = KColorUtils::mix(color, bg, _amount[Contrast]);
139         break;
140     case ContrastTint:
141         color = KColorUtils::tint(color, bg, _amount[Contrast]);
142         break;
143     }
144     // Now apply global effects
145     return brush(color);
146 }
147 //END StateEffects
148 
149 //BEGIN default colors
150 struct SetDefaultColors {
151     int NormalBackground[3];
152     int AlternateBackground[3];
153     int NormalText[3];
154     int InactiveText[3];
155     int ActiveText[3];
156     int LinkText[3];
157     int VisitedText[3];
158     int NegativeText[3];
159     int NeutralText[3];
160     int PositiveText[3];
161 };
162 
163 struct DecoDefaultColors {
164     int Hover[3];
165     int Focus[3];
166 };
167 
168 static const SetDefaultColors defaultViewColors = {
169     { 255, 255, 255 }, // Background
170     { 248, 247, 246 }, // Alternate
171     {  31,  28,  27 }, // Normal
172     { 137, 136, 135 }, // Inactive
173     { 146,  76, 157 }, // Active
174     {   0,  87, 174 }, // Link
175     { 100,  74, 155 }, // Visited
176     { 191,   3,   3 }, // Negative
177     { 176, 128,   0 }, // Neutral
178     {   0, 110,  40 }  // Positive
179 };
180 
181 static const SetDefaultColors defaultWindowColors = {
182     { 214, 210, 208 }, // Background
183     { 218, 217, 216 }, // Alternate
184     {  34,  31,  30 }, // Normal
185     { 137, 136, 135 }, // Inactive
186     { 146,  76, 157 }, // Active
187     {   0,  87, 174 }, // Link
188     { 100,  74, 155 }, // Visited
189     { 191,   3,   3 }, // Negative
190     { 176, 128,   0 }, // Neutral
191     { 0,   110,  40 }  // Positive
192 };
193 
194 static const SetDefaultColors defaultButtonColors = {
195     { 223, 220, 217 }, // Background
196     { 224, 223, 222 }, // Alternate
197     {  34,  31,  30 }, // Normal
198     { 137, 136, 135 }, // Inactive
199     { 146,  76, 157 }, // Active
200     {   0,  87, 174 }, // Link
201     { 100,  74, 155 }, // Visited
202     { 191,   3,   3 }, // Negative
203     { 176, 128,   0 }, // Neutral
204     {   0, 110,  40 }  // Positive
205 };
206 
207 static const SetDefaultColors defaultSelectionColors = {
208     {  67, 172, 232 }, // Background
209     {  62, 138, 204 }, // Alternate
210     { 255, 255, 255 }, // Normal
211     { 199, 226, 248 }, // Inactive
212     { 108,  36, 119 }, // Active
213     {   0,  49, 110 }, // Link
214     {  69,  40, 134 }, // Visited
215     { 156,  14,  14 }, // Negative
216     { 255, 221,   0 }, // Neutral
217     { 128, 255, 128 }  // Positive
218 };
219 
220 static const SetDefaultColors defaultTooltipColors = {
221     {  24,  21,  19 }, // Background
222     { 196, 224, 255 }, // Alternate
223     { 231, 253, 255 }, // Normal
224     { 137, 136, 135 }, // Inactive
225     { 255, 128, 224 }, // Active
226     {  88, 172, 255 }, // Link
227     { 150, 111, 232 }, // Visited
228     { 191,   3,   3 }, // Negative
229     { 176, 128,   0 }, // Neutral
230     {   0, 110,  40 }  // Positive
231 };
232 
233 static const DecoDefaultColors defaultDecorationColors = {
234     { 110, 214, 255 }, // Hover
235     {  58, 167, 221 }, // Focus
236 };
237 //END default colors
238 
239 //BEGIN KColorSchemePrivate
240 class KColorSchemePrivate : public QSharedData
241 {
242 public:
243     explicit KColorSchemePrivate(const KSharedConfigPtr &, QPalette::ColorGroup, const char *, SetDefaultColors);
244     explicit KColorSchemePrivate(const KSharedConfigPtr &, QPalette::ColorGroup, const char *, SetDefaultColors, const QBrush &);
~KColorSchemePrivate()245     ~KColorSchemePrivate() {}
246 
247     QBrush background(KColorScheme::BackgroundRole) const;
248     QBrush foreground(KColorScheme::ForegroundRole) const;
249     QBrush decoration(KColorScheme::DecorationRole) const;
250     qreal contrast() const;
251 private:
252     struct {
253         QBrush fg[8], bg[8], deco[2];
254     } _brushes;
255     qreal _contrast;
256 
257     void init(const KSharedConfigPtr &, QPalette::ColorGroup, const char *, SetDefaultColors);
258 };
259 
260 #define DEFAULT(c) QColor( c[0], c[1], c[2] )
261 #define  SET_DEFAULT(a) DEFAULT( defaults.a )
262 #define DECO_DEFAULT(a) DEFAULT( defaultDecorationColors.a )
263 
KColorSchemePrivate(const KSharedConfigPtr & config,QPalette::ColorGroup state,const char * group,SetDefaultColors defaults)264 KColorSchemePrivate::KColorSchemePrivate(const KSharedConfigPtr &config,
265         QPalette::ColorGroup state,
266         const char *group,
267         SetDefaultColors defaults)
268 {
269     KConfigGroup cfg(config, group);
270     _contrast = KColorScheme::contrastF(config);
271 
272     // loaded-from-config colors (no adjustment)
273     _brushes.bg[0] = cfg.readEntry("BackgroundNormal", SET_DEFAULT(NormalBackground));
274     _brushes.bg[1] = cfg.readEntry("BackgroundAlternate", SET_DEFAULT(AlternateBackground));
275 
276     // the rest
277     init(config, state, group, defaults);
278 }
279 
KColorSchemePrivate(const KSharedConfigPtr & config,QPalette::ColorGroup state,const char * group,SetDefaultColors defaults,const QBrush & tint)280 KColorSchemePrivate::KColorSchemePrivate(const KSharedConfigPtr &config,
281         QPalette::ColorGroup state,
282         const char *group,
283         SetDefaultColors defaults,
284         const QBrush &tint)
285 {
286     KConfigGroup cfg(config, group);
287     _contrast = KColorScheme::contrastF(config);
288 
289     // loaded-from-config colors
290     _brushes.bg[0] = cfg.readEntry("BackgroundNormal", SET_DEFAULT(NormalBackground));
291     _brushes.bg[1] = cfg.readEntry("BackgroundAlternate", SET_DEFAULT(AlternateBackground));
292 
293     // adjustment
294     _brushes.bg[0] = KColorUtils::tint(_brushes.bg[0].color(), tint.color(), 0.4);
295     _brushes.bg[1] = KColorUtils::tint(_brushes.bg[1].color(), tint.color(), 0.4);
296 
297     // the rest
298     init(config, state, group, defaults);
299 }
300 
init(const KSharedConfigPtr & config,QPalette::ColorGroup state,const char * group,SetDefaultColors defaults)301 void KColorSchemePrivate::init(const KSharedConfigPtr &config,
302                                QPalette::ColorGroup state,
303                                const char *group,
304                                SetDefaultColors defaults)
305 {
306     KConfigGroup cfg(config, group);
307 
308     // loaded-from-config colors
309     _brushes.fg[0] = cfg.readEntry("ForegroundNormal", SET_DEFAULT(NormalText));
310     _brushes.fg[1] = cfg.readEntry("ForegroundInactive", SET_DEFAULT(InactiveText));
311     _brushes.fg[2] = cfg.readEntry("ForegroundActive", SET_DEFAULT(ActiveText));
312     _brushes.fg[3] = cfg.readEntry("ForegroundLink", SET_DEFAULT(LinkText));
313     _brushes.fg[4] = cfg.readEntry("ForegroundVisited", SET_DEFAULT(VisitedText));
314     _brushes.fg[5] = cfg.readEntry("ForegroundNegative", SET_DEFAULT(NegativeText));
315     _brushes.fg[6] = cfg.readEntry("ForegroundNeutral", SET_DEFAULT(NeutralText));
316     _brushes.fg[7] = cfg.readEntry("ForegroundPositive", SET_DEFAULT(PositiveText));
317 
318     _brushes.deco[0] = cfg.readEntry("DecorationHover", DECO_DEFAULT(Hover));
319     _brushes.deco[1] = cfg.readEntry("DecorationFocus", DECO_DEFAULT(Focus));
320 
321     // apply state adjustments
322     if (state != QPalette::Active) {
323         StateEffects effects(state, config);
324         for (int i = 0; i < 8; i++) {
325             _brushes.fg[i] = effects.brush(_brushes.fg[i], _brushes.bg[0]);
326         }
327         _brushes.deco[0] = effects.brush(_brushes.deco[0], _brushes.bg[0]);
328         _brushes.deco[1] = effects.brush(_brushes.deco[1], _brushes.bg[0]);
329         _brushes.bg[0] = effects.brush(_brushes.bg[0]);
330         _brushes.bg[1] = effects.brush(_brushes.bg[1]);
331     }
332 
333     // calculated backgrounds
334     _brushes.bg[2] = KColorUtils::tint(_brushes.bg[0].color(), _brushes.fg[2].color());
335     _brushes.bg[3] = KColorUtils::tint(_brushes.bg[0].color(), _brushes.fg[3].color());
336     _brushes.bg[4] = KColorUtils::tint(_brushes.bg[0].color(), _brushes.fg[4].color());
337     _brushes.bg[5] = KColorUtils::tint(_brushes.bg[0].color(), _brushes.fg[5].color());
338     _brushes.bg[6] = KColorUtils::tint(_brushes.bg[0].color(), _brushes.fg[6].color());
339     _brushes.bg[7] = KColorUtils::tint(_brushes.bg[0].color(), _brushes.fg[7].color());
340 }
341 
background(KColorScheme::BackgroundRole role) const342 QBrush KColorSchemePrivate::background(KColorScheme::BackgroundRole role) const
343 {
344     switch (role) {
345     case KColorScheme::AlternateBackground:
346         return _brushes.bg[1];
347     case KColorScheme::ActiveBackground:
348         return _brushes.bg[2];
349     case KColorScheme::LinkBackground:
350         return _brushes.bg[3];
351     case KColorScheme::VisitedBackground:
352         return _brushes.bg[4];
353     case KColorScheme::NegativeBackground:
354         return _brushes.bg[5];
355     case KColorScheme::NeutralBackground:
356         return _brushes.bg[6];
357     case KColorScheme::PositiveBackground:
358         return _brushes.bg[7];
359     default:
360         return _brushes.bg[0];
361     }
362 }
363 
foreground(KColorScheme::ForegroundRole role) const364 QBrush KColorSchemePrivate::foreground(KColorScheme::ForegroundRole role) const
365 {
366     switch (role) {
367     case KColorScheme::InactiveText:
368         return _brushes.fg[1];
369     case KColorScheme::ActiveText:
370         return _brushes.fg[2];
371     case KColorScheme::LinkText:
372         return _brushes.fg[3];
373     case KColorScheme::VisitedText:
374         return _brushes.fg[4];
375     case KColorScheme::NegativeText:
376         return _brushes.fg[5];
377     case KColorScheme::NeutralText:
378         return _brushes.fg[6];
379     case KColorScheme::PositiveText:
380         return _brushes.fg[7];
381     default:
382         return _brushes.fg[0];
383     }
384 }
385 
decoration(KColorScheme::DecorationRole role) const386 QBrush KColorSchemePrivate::decoration(KColorScheme::DecorationRole role) const
387 {
388     switch (role) {
389     case KColorScheme::FocusColor:
390         return _brushes.deco[1];
391     default:
392         return _brushes.deco[0];
393     }
394 }
395 
contrast() const396 qreal KColorSchemePrivate::contrast() const
397 {
398     return _contrast;
399 }
400 //END KColorSchemePrivate
401 
402 //BEGIN KColorScheme
KColorScheme(const KColorScheme & other)403 KColorScheme::KColorScheme(const KColorScheme &other) : d(other.d)
404 {
405 }
406 
operator =(const KColorScheme & other)407 KColorScheme &KColorScheme::operator=(const KColorScheme &other)
408 {
409     d = other.d;
410     return *this;
411 }
412 
~KColorScheme()413 KColorScheme::~KColorScheme()
414 {
415 }
416 
KColorScheme(QPalette::ColorGroup state,ColorSet set,KSharedConfigPtr config)417 KColorScheme::KColorScheme(QPalette::ColorGroup state, ColorSet set, KSharedConfigPtr config)
418 {
419     if (!config) {
420         config = KSharedConfig::openConfig();
421     }
422 
423     switch (set) {
424     case Window:
425         d = new KColorSchemePrivate(config, state, "Colors:Window", defaultWindowColors);
426         break;
427     case Button:
428         d = new KColorSchemePrivate(config, state, "Colors:Button", defaultButtonColors);
429         break;
430     case Selection: {
431         KConfigGroup group(config, "ColorEffects:Inactive");
432         // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
433         bool inactiveSelectionEffect = group.readEntry("ChangeSelectionColor", group.readEntry("Enable", true));
434         // if enabled, inactiver/disabled uses Window colors instead, ala gtk
435         // ...except tinted with the Selection:NormalBackground color so it looks more like selection
436         if (state == QPalette::Active || (state == QPalette::Inactive && !inactiveSelectionEffect)) {
437             d = new KColorSchemePrivate(config, state, "Colors:Selection", defaultSelectionColors);
438         } else if (state == QPalette::Inactive)
439             d = new KColorSchemePrivate(config, state, "Colors:Window", defaultWindowColors,
440                                         KColorScheme(QPalette::Active, Selection, config).background());
441         else { // disabled (...and still want this branch when inactive+disabled exists)
442             d = new KColorSchemePrivate(config, state, "Colors:Window", defaultWindowColors);
443         }
444     } break;
445     case Tooltip:
446         d = new KColorSchemePrivate(config, state, "Colors:Tooltip", defaultTooltipColors);
447         break;
448     default:
449         d = new KColorSchemePrivate(config, state, "Colors:View", defaultViewColors);
450     }
451 }
452 
453 // static
contrast()454 int KColorScheme::contrast()
455 {
456     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
457     return g.readEntry("contrast", 7);
458 }
459 
460 // static
contrastF(const KSharedConfigPtr & config)461 qreal KColorScheme::contrastF(const KSharedConfigPtr &config)
462 {
463     if (config) {
464         KConfigGroup g(config, "KDE");
465         return 0.1 * g.readEntry("contrast", 7);
466     }
467     return 0.1 * (qreal)contrast();
468 }
469 
background(BackgroundRole role) const470 QBrush KColorScheme::background(BackgroundRole role) const
471 {
472     return d->background(role);
473 }
474 
foreground(ForegroundRole role) const475 QBrush KColorScheme::foreground(ForegroundRole role) const
476 {
477     return d->foreground(role);
478 }
479 
decoration(DecorationRole role) const480 QBrush KColorScheme::decoration(DecorationRole role) const
481 {
482     return d->decoration(role);
483 }
484 
shade(ShadeRole role) const485 QColor KColorScheme::shade(ShadeRole role) const
486 {
487     return shade(background().color(), role, d->contrast());
488 }
489 
shade(const QColor & color,ShadeRole role)490 QColor KColorScheme::shade(const QColor &color, ShadeRole role)
491 {
492     return shade(color, role, KColorScheme::contrastF());
493 }
494 
shade(const QColor & color,ShadeRole role,qreal contrast,qreal chromaAdjust)495 QColor KColorScheme::shade(const QColor &color, ShadeRole role, qreal contrast, qreal chromaAdjust)
496 {
497     // nan -> 1.0
498     contrast = (1.0 > contrast ? (-1.0 < contrast ? contrast : -1.0) : 1.0);
499     qreal y = KColorUtils::luma(color), yi = 1.0 - y;
500 
501     // handle very dark colors (base, mid, dark, shadow == midlight, light)
502     if (y < 0.006) {
503         switch (role) {
504         case KColorScheme::LightShade:
505             return KColorUtils::shade(color, 0.05 + 0.95 * contrast, chromaAdjust);
506         case KColorScheme::MidShade:
507             return KColorUtils::shade(color, 0.01 + 0.20 * contrast, chromaAdjust);
508         case KColorScheme::DarkShade:
509             return KColorUtils::shade(color, 0.02 + 0.40 * contrast, chromaAdjust);
510         default:
511             return KColorUtils::shade(color, 0.03 + 0.60 * contrast, chromaAdjust);
512         }
513     }
514 
515     // handle very light colors (base, midlight, light == mid, dark, shadow)
516     if (y > 0.93) {
517         switch (role) {
518         case KColorScheme::MidlightShade:
519             return KColorUtils::shade(color, -0.02 - 0.20 * contrast, chromaAdjust);
520         case KColorScheme::DarkShade:
521             return KColorUtils::shade(color, -0.06 - 0.60 * contrast, chromaAdjust);
522         case KColorScheme::ShadowShade:
523             return KColorUtils::shade(color, -0.10 - 0.90 * contrast, chromaAdjust);
524         default:
525             return KColorUtils::shade(color, -0.04 - 0.40 * contrast, chromaAdjust);
526         }
527     }
528 
529     // handle everything else
530     qreal lightAmount = (0.05 + y * 0.55) * (0.25 + contrast * 0.75);
531     qreal darkAmount = (- y) * (0.55 + contrast * 0.35);
532     switch (role) {
533     case KColorScheme::LightShade:
534         return KColorUtils::shade(color, lightAmount, chromaAdjust);
535     case KColorScheme::MidlightShade:
536         return KColorUtils::shade(color, (0.15 + 0.35 * yi) * lightAmount, chromaAdjust);
537     case KColorScheme::MidShade:
538         return KColorUtils::shade(color, (0.35 + 0.15 * y) * darkAmount, chromaAdjust);
539     case KColorScheme::DarkShade:
540         return KColorUtils::shade(color, darkAmount, chromaAdjust);
541     default:
542         return KColorUtils::darken(KColorUtils::shade(color, darkAmount, chromaAdjust), 0.5 + 0.3 * y);
543     }
544 }
545 
adjustBackground(QPalette & palette,BackgroundRole newRole,QPalette::ColorRole color,ColorSet set,KSharedConfigPtr config)546 void KColorScheme::adjustBackground(QPalette &palette, BackgroundRole newRole, QPalette::ColorRole color,
547                                     ColorSet set, KSharedConfigPtr config)
548 {
549     palette.setBrush(QPalette::Active,   color, KColorScheme(QPalette::Active,   set, config).background(newRole));
550     palette.setBrush(QPalette::Inactive, color, KColorScheme(QPalette::Inactive, set, config).background(newRole));
551     palette.setBrush(QPalette::Disabled, color, KColorScheme(QPalette::Disabled, set, config).background(newRole));
552 }
553 
adjustForeground(QPalette & palette,ForegroundRole newRole,QPalette::ColorRole color,ColorSet set,KSharedConfigPtr config)554 void KColorScheme::adjustForeground(QPalette &palette, ForegroundRole newRole, QPalette::ColorRole color,
555                                     ColorSet set, KSharedConfigPtr config)
556 {
557     palette.setBrush(QPalette::Active,   color, KColorScheme(QPalette::Active,   set, config).foreground(newRole));
558     palette.setBrush(QPalette::Inactive, color, KColorScheme(QPalette::Inactive, set, config).foreground(newRole));
559     palette.setBrush(QPalette::Disabled, color, KColorScheme(QPalette::Disabled, set, config).foreground(newRole));
560 }
561 
createApplicationPalette(const KSharedConfigPtr & config)562 QPalette KColorScheme::createApplicationPalette(const KSharedConfigPtr &config)
563 {
564     QPalette palette;
565 
566     static const QPalette::ColorGroup states[3] = { QPalette::Active, QPalette::Inactive, QPalette::Disabled };
567 
568     // TT thinks tooltips shouldn't use active, so we use our active colors for all states
569     KColorScheme schemeTooltip(QPalette::Active, KColorScheme::Tooltip, config);
570 
571     for (int i = 0; i < 3; i++) {
572         QPalette::ColorGroup state = states[i];
573         KColorScheme schemeView(state, KColorScheme::View, config);
574         KColorScheme schemeWindow(state, KColorScheme::Window, config);
575         KColorScheme schemeButton(state, KColorScheme::Button, config);
576         KColorScheme schemeSelection(state, KColorScheme::Selection, config);
577 
578         palette.setBrush(state, QPalette::WindowText, schemeWindow.foreground());
579         palette.setBrush(state, QPalette::Window, schemeWindow.background());
580         palette.setBrush(state, QPalette::Base, schemeView.background());
581         palette.setBrush(state, QPalette::Text, schemeView.foreground());
582         palette.setBrush(state, QPalette::Button, schemeButton.background());
583         palette.setBrush(state, QPalette::ButtonText, schemeButton.foreground());
584         palette.setBrush(state, QPalette::Highlight, schemeSelection.background());
585         palette.setBrush(state, QPalette::HighlightedText, schemeSelection.foreground());
586         palette.setBrush(state, QPalette::ToolTipBase, schemeTooltip.background());
587         palette.setBrush(state, QPalette::ToolTipText, schemeTooltip.foreground());
588 
589         palette.setColor(state, QPalette::Light, schemeWindow.shade(KColorScheme::LightShade));
590         palette.setColor(state, QPalette::Midlight, schemeWindow.shade(KColorScheme::MidlightShade));
591         palette.setColor(state, QPalette::Mid, schemeWindow.shade(KColorScheme::MidShade));
592         palette.setColor(state, QPalette::Dark, schemeWindow.shade(KColorScheme::DarkShade));
593         palette.setColor(state, QPalette::Shadow, schemeWindow.shade(KColorScheme::ShadowShade));
594 
595         palette.setBrush(state, QPalette::AlternateBase, schemeView.background(KColorScheme::AlternateBackground));
596         palette.setBrush(state, QPalette::Link, schemeView.foreground(KColorScheme::LinkText));
597         palette.setBrush(state, QPalette::LinkVisited, schemeView.foreground(KColorScheme::VisitedText));
598     }
599 
600     return palette;
601 }
602 
603 //END KColorScheme
604 
605 //BEGIN KStatefulBrush
606 class KStatefulBrushPrivate : public QBrush // for now, just be a QBrush
607 {
608 public:
KStatefulBrushPrivate()609     KStatefulBrushPrivate() : QBrush() {}
KStatefulBrushPrivate(const QBrush & brush)610     KStatefulBrushPrivate(const QBrush &brush) : QBrush(brush) {} // not explicit
611 };
612 
KStatefulBrush()613 KStatefulBrush::KStatefulBrush()
614 {
615     d = new KStatefulBrushPrivate[3];
616 }
617 
KStatefulBrush(KColorScheme::ColorSet set,KColorScheme::ForegroundRole role,KSharedConfigPtr config)618 KStatefulBrush::KStatefulBrush(KColorScheme::ColorSet set, KColorScheme::ForegroundRole role,
619                                KSharedConfigPtr config)
620 {
621     d = new KStatefulBrushPrivate[3];
622     d[0] = KColorScheme(QPalette::Active,   set, config).foreground(role);
623     d[1] = KColorScheme(QPalette::Disabled, set, config).foreground(role);
624     d[2] = KColorScheme(QPalette::Inactive, set, config).foreground(role);
625 }
626 
KStatefulBrush(KColorScheme::ColorSet set,KColorScheme::BackgroundRole role,KSharedConfigPtr config)627 KStatefulBrush::KStatefulBrush(KColorScheme::ColorSet set, KColorScheme::BackgroundRole role,
628                                KSharedConfigPtr config)
629 {
630     d = new KStatefulBrushPrivate[3];
631     d[0] = KColorScheme(QPalette::Active,   set, config).background(role);
632     d[1] = KColorScheme(QPalette::Disabled, set, config).background(role);
633     d[2] = KColorScheme(QPalette::Inactive, set, config).background(role);
634 }
635 
KStatefulBrush(KColorScheme::ColorSet set,KColorScheme::DecorationRole role,KSharedConfigPtr config)636 KStatefulBrush::KStatefulBrush(KColorScheme::ColorSet set, KColorScheme::DecorationRole role,
637                                KSharedConfigPtr config)
638 {
639     d = new KStatefulBrushPrivate[3];
640     d[0] = KColorScheme(QPalette::Active,   set, config).decoration(role);
641     d[1] = KColorScheme(QPalette::Disabled, set, config).decoration(role);
642     d[2] = KColorScheme(QPalette::Inactive, set, config).decoration(role);
643 }
644 
KStatefulBrush(const QBrush & brush,KSharedConfigPtr config)645 KStatefulBrush::KStatefulBrush(const QBrush &brush, KSharedConfigPtr config)
646 {
647     if (!config) {
648         config = KSharedConfig::openConfig();
649     }
650     d = new KStatefulBrushPrivate[3];
651     d[0] = brush;
652     d[1] = StateEffects(QPalette::Disabled, config).brush(brush);
653     d[2] = StateEffects(QPalette::Inactive, config).brush(brush);
654 }
655 
KStatefulBrush(const QBrush & brush,const QBrush & background,KSharedConfigPtr config)656 KStatefulBrush::KStatefulBrush(const QBrush &brush, const QBrush &background,
657                                KSharedConfigPtr config)
658 {
659     if (!config) {
660         config = KSharedConfig::openConfig();
661     }
662     d = new KStatefulBrushPrivate[3];
663     d[0] = brush;
664     d[1] = StateEffects(QPalette::Disabled, config).brush(brush, background);
665     d[2] = StateEffects(QPalette::Inactive, config).brush(brush, background);
666 }
667 
KStatefulBrush(const KStatefulBrush & other)668 KStatefulBrush::KStatefulBrush(const KStatefulBrush &other)
669 {
670     d = new KStatefulBrushPrivate[3];
671     d[0] = other.d[0];
672     d[1] = other.d[1];
673     d[2] = other.d[2];
674 }
675 
~KStatefulBrush()676 KStatefulBrush::~KStatefulBrush()
677 {
678     delete[] d;
679 }
680 
operator =(const KStatefulBrush & other)681 KStatefulBrush &KStatefulBrush::operator=(const KStatefulBrush &other)
682 {
683     d[0] = other.d[0];
684     d[1] = other.d[1];
685     d[2] = other.d[2];
686     return *this;
687 }
688 
brush(QPalette::ColorGroup state) const689 QBrush KStatefulBrush::brush(QPalette::ColorGroup state) const
690 {
691     switch (state) {
692     case QPalette::Inactive:
693         return d[2];
694     case QPalette::Disabled:
695         return d[1];
696     default:
697         return d[0];
698     }
699 }
700 
brush(const QPalette & pal) const701 QBrush KStatefulBrush::brush(const QPalette &pal) const
702 {
703     return brush(pal.currentColorGroup());
704 }
705 
brush(const QWidget * widget) const706 QBrush KStatefulBrush::brush(const QWidget *widget) const
707 {
708     if (widget) {
709         return brush(widget->palette());
710     } else {
711         return QBrush();
712     }
713 }
714 //END KStatefulBrush
715 
716