• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • edu API Reference
  • KDE Home
  • Contact Us
 

kstars

  • extragear
  • edu
  • kstars
  • kstars
  • auxiliary
schememanager.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * http://www.digikam.org
5  *
6  * Date : 2004-08-02
7  * Description : colors scheme manager
8  *
9  * Copyright (C) 2006-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
10  * Copyright (C) 2007 by Matthew Woehlke <mw_triad at users dot sourceforge dot net>
11  *
12  * This program is free software; you can redistribute it
13  * and/or modify it under the terms of the GNU General
14  * Public License as published by the Free Software Foundation;
15  * either version 2, or (at your option)
16  * any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * ============================================================ */
24 
25 #include "schememanager.h"
26 
27 #include <kconfig.h>
28 #include <kconfiggroup.h>
29 
30 #include <QWidget>
31 #include <QPainter>
32 
33 #include <cmath>
34 
35 class HCYColorSpace
36 {
37 public:
38 
39  explicit HCYColorSpace(const QColor&);
40  explicit HCYColorSpace(qreal h_, qreal c_, qreal y_, qreal a_ = 1.0);
41 
42  QColor qColor() const;
43 
44  static qreal luma(const QColor &);
45 
46 public:
47 
48  qreal h;
49  qreal c;
50  qreal y;
51  qreal a;
52 
53 private:
54 
55  static qreal gamma(qreal);
56  static qreal igamma(qreal);
57  static qreal lumag(qreal, qreal, qreal);
58 };
59 
60 // ------------------------------------------------------------------------------
61 
62 namespace ColorTools
63 {
64 
65 static inline qreal wrap(qreal a, qreal d = 1.0)
66 {
67  qreal r = fmod(a, d);
68 
69  return (r < 0.0 ? d + r : (r > 0.0 ? r : 0.0));
70 }
71 
76 static inline qreal normalize(qreal a)
77 {
78  return (a < 1.0 ? (a > 0.0 ? a : 0.0) : 1.0);
79 }
80 
81 static inline qreal mixQreal(qreal a, qreal b, qreal bias)
82 {
83  return (a + (b - a) * bias);
84 }
85 
92 qreal luma(const QColor& color)
93 {
94  return HCYColorSpace::luma(color);
95 }
96 
100 void getHcy(const QColor& color, qreal* h, qreal* c, qreal* y, qreal* a = 0)
101 {
102  if (!c || !h || !y)
103  {
104  return;
105  }
106 
107  HCYColorSpace khcy(color);
108  *c = khcy.c;
109  *h = khcy.h;
110  *y = khcy.y;
111 
112  if (a)
113  {
114  *a = khcy.a;
115  }
116 }
117 
128 static qreal contrastRatioForLuma(qreal y1, qreal y2)
129 {
130  if (y1 > y2)
131  {
132  return (y1 + 0.05) / (y2 + 0.05);
133  }
134 
135  return (y2 + 0.05) / (y1 + 0.05);
136 }
137 
138 qreal contrastRatio(const QColor& c1, const QColor& c2)
139 {
140  return contrastRatioForLuma(luma(c1), luma(c2));
141 }
142 
146 QColor lighten(const QColor& color, qreal ky = 0.5, qreal kc = 1.0)
147 {
148  HCYColorSpace c(color);
149  c.y = 1.0 - ColorTools::normalize((1.0 - c.y) * (1.0 - ky));
150  c.c = 1.0 - ColorTools::normalize((1.0 - c.c) * kc);
151 
152  return c.qColor();
153 }
154 
158 QColor darken(const QColor& color, qreal ky = 0.5, qreal kc = 1.0)
159 {
160  HCYColorSpace c(color);
161  c.y = ColorTools::normalize(c.y * (1.0 - ky));
162  c.c = ColorTools::normalize(c.c * kc);
163 
164  return c.qColor();
165 }
166 
171 QColor shade(const QColor& color, qreal ky, qreal kc = 0.0)
172 {
173  HCYColorSpace c(color);
174  c.y = ColorTools::normalize(c.y + ky);
175  c.c = ColorTools::normalize(c.c + kc);
176 
177  return c.qColor();
178 }
179 
183 QColor mix(const QColor& c1, const QColor& c2, qreal bias)
184 {
185  if (bias <= 0.0)
186  {
187  return c1;
188  }
189 
190  if (bias >= 1.0)
191  {
192  return c2;
193  }
194 
195  if (qIsNaN(bias))
196  {
197  return c1;
198  }
199 
200  qreal r = mixQreal(c1.redF(), c2.redF(), bias);
201  qreal g = mixQreal(c1.greenF(), c2.greenF(), bias);
202  qreal b = mixQreal(c1.blueF(), c2.blueF(), bias);
203  qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias);
204 
205  return QColor::fromRgbF(r, g, b, a);
206 }
207 
208 static QColor tintHelper(const QColor& base, qreal baseLuma, const QColor& color, qreal amount)
209 {
210  HCYColorSpace result(mix(base, color, pow(amount, 0.3)));
211  result.y = mixQreal(baseLuma, result.y, amount);
212 
213  return result.qColor();
214 }
215 
228 QColor tint(const QColor& base, const QColor& color, qreal amount = 0.3)
229 {
230  if (amount <= 0.0)
231  {
232  return base;
233  }
234 
235  if (amount >= 1.0)
236  {
237  return color;
238  }
239 
240  if (qIsNaN(amount))
241  {
242  return base;
243  }
244 
245  qreal baseLuma = luma(base); //cache value because luma call is expensive
246  double ri = contrastRatioForLuma(baseLuma, luma(color));
247  double rg = 1.0 + ((ri + 1.0) * amount * amount * amount);
248  double u = 1.0, l = 0.0;
249  QColor result;
250 
251  for (int i = 12; i; --i)
252  {
253  double a = 0.5 * (l + u);
254  result = tintHelper(base, baseLuma, color, a);
255  double ra = contrastRatioForLuma(baseLuma, luma(result));
256 
257  if (ra > rg)
258  {
259  u = a;
260  }
261  else
262  {
263  l = a;
264  }
265  }
266 
267  return result;
268 }
269 
278 QColor overlayColors(const QColor& base, const QColor& paint,
279  QPainter::CompositionMode comp)
280 {
281  // This isn't the fastest way, but should be "fast enough".
282  // It's also the only safe way to use QPainter::CompositionMode
283  QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
284  QPainter p(&img);
285  QColor start = base;
286  start.setAlpha(255); // opaque
287  p.fillRect(0, 0, 1, 1, start);
288  p.setCompositionMode(comp);
289  p.fillRect(0, 0, 1, 1, paint);
290  p.end();
291 
292  return img.pixel(0, 0);
293 }
294 
295 } // namespace ColorTools
296 
297 // ------------------------------------------------------------------------------
298 
299 #define HCY_REC 709 // use 709 for now
300 #if HCY_REC == 601
301 static const qreal yc[3] = {0.299, 0.587, 0.114 };
302 #elif HCY_REC == 709
303 static const qreal yc[3] = {0.2126, 0.7152, 0.0722 };
304 #else // use Qt values
305 static const qreal yc[3] = {0.34375, 0.5, 0.15625};
306 #endif
307 
308 qreal HCYColorSpace::gamma(qreal n)
309 {
310  return pow(ColorTools::normalize(n), 2.2);
311 }
312 
313 qreal HCYColorSpace::igamma(qreal n)
314 {
315  return pow(ColorTools::normalize(n), 1.0 / 2.2);
316 }
317 
318 qreal HCYColorSpace::lumag(qreal r, qreal g, qreal b)
319 {
320  return r * yc[0] + g * yc[1] + b * yc[2];
321 }
322 
323 HCYColorSpace::HCYColorSpace(qreal h_, qreal c_, qreal y_, qreal a_)
324 {
325  h = h_;
326  c = c_;
327  y = y_;
328  a = a_;
329 }
330 
331 HCYColorSpace::HCYColorSpace(const QColor& color)
332 {
333  qreal r = gamma(color.redF());
334  qreal g = gamma(color.greenF());
335  qreal b = gamma(color.blueF());
336  a = color.alphaF();
337 
338  // luma component
339  y = lumag(r, g, b);
340 
341  // hue component
342  qreal p = qMax(qMax(r, g), b);
343  qreal n = qMin(qMin(r, g), b);
344  qreal d = 6.0 * (p - n);
345 
346  if (n == p)
347  {
348  h = 0.0;
349  }
350  else if (r == p)
351  {
352  h = ((g - b) / d);
353  }
354  else if (g == p)
355  {
356  h = ((b - r) / d) + (1.0 / 3.0);
357  }
358  else
359  {
360  h = ((r - g) / d) + (2.0 / 3.0);
361  }
362 
363  // chroma component
364  if (r == g && g == b)
365  {
366  c = 0.0;
367  }
368  else
369  {
370  c = qMax((y - n) / y, (p - y) / (1 - y));
371  }
372 }
373 
374 QColor HCYColorSpace::qColor() const
375 {
376  // start with sane component values
377  qreal _h = ColorTools::wrap(h);
378  qreal _c = ColorTools::normalize(c);
379  qreal _y = ColorTools::normalize(y);
380 
381  // calculate some needed variables
382  qreal _hs = _h * 6.0, th, tm;
383 
384  if (_hs < 1.0)
385  {
386  th = _hs;
387  tm = yc[0] + yc[1] * th;
388  }
389  else if (_hs < 2.0)
390  {
391  th = 2.0 - _hs;
392  tm = yc[1] + yc[0] * th;
393  }
394  else if (_hs < 3.0)
395  {
396  th = _hs - 2.0;
397  tm = yc[1] + yc[2] * th;
398  }
399  else if (_hs < 4.0)
400  {
401  th = 4.0 - _hs;
402  tm = yc[2] + yc[1] * th;
403  }
404  else if (_hs < 5.0)
405  {
406  th = _hs - 4.0;
407  tm = yc[2] + yc[0] * th;
408  }
409  else
410  {
411  th = 6.0 - _hs;
412  tm = yc[0] + yc[2] * th;
413  }
414 
415  // calculate RGB channels in sorted order
416  qreal tn, to, tp;
417 
418  if (tm >= _y)
419  {
420  tp = _y + _y * _c * (1.0 - tm) / tm;
421  to = _y + _y * _c * (th - tm) / tm;
422  tn = _y - (_y * _c);
423  }
424  else
425  {
426  tp = _y + (1.0 - _y) * _c;
427  to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm);
428  tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm);
429  }
430 
431  // return RGB channels in appropriate order
432  if (_hs < 1.0)
433  {
434  return QColor::fromRgbF(igamma(tp), igamma(to), igamma(tn), a);
435  }
436  else if (_hs < 2.0)
437  {
438  return QColor::fromRgbF(igamma(to), igamma(tp), igamma(tn), a);
439  }
440  else if (_hs < 3.0)
441  {
442  return QColor::fromRgbF(igamma(tn), igamma(tp), igamma(to), a);
443  }
444  else if (_hs < 4.0)
445  {
446  return QColor::fromRgbF(igamma(tn), igamma(to), igamma(tp), a);
447  }
448  else if (_hs < 5.0)
449  {
450  return QColor::fromRgbF(igamma(to), igamma(tn), igamma(tp), a);
451  }
452  else
453  {
454  return QColor::fromRgbF(igamma(tp), igamma(tn), igamma(to), a);
455  }
456 }
457 
458 qreal HCYColorSpace::luma(const QColor& color)
459 {
460  return lumag(gamma(color.redF()),
461  gamma(color.greenF()),
462  gamma(color.blueF()));
463 }
464 
465 // -------------------------------------------------------------------------------------
466 
467 class StateEffects
468 {
469 public:
470 
471  explicit StateEffects(QPalette::ColorGroup state, const KSharedConfigPtr&);
472  ~StateEffects() = default;
473 
474  QBrush brush(const QBrush& background) const;
475  QBrush brush(const QBrush& foreground, const QBrush& background) const;
476 
477 private:
478 
479  enum Effects
480  {
481  // Effects
482  Intensity = 0,
483  Color = 1,
484  Contrast = 2,
485  // Intensity
486  IntensityNoEffect = 0,
487  IntensityShade = 1,
488  IntensityDarken = 2,
489  IntensityLighten = 3,
490  // Color
491  ColorNoEffect = 0,
492  ColorDesaturate = 1,
493  ColorFade = 2,
494  ColorTint = 3,
495  // Contrast
496  ContrastNoEffect = 0,
497  ContrastFade = 1,
498  ContrastTint = 2
499  };
500 
501 private:
502 
503  int _effects[3];
504  double _amount[3];
505  QColor _color;
506 };
507 
508 StateEffects::StateEffects(QPalette::ColorGroup state, const KSharedConfigPtr& config)
509  : _color(0, 0, 0, 0)
510 {
511  QString group;
512 
513  if (state == QPalette::Disabled)
514  {
515  group = QLatin1String("ColorEffects:Disabled");
516  }
517  else if (state == QPalette::Inactive)
518  {
519  group = QLatin1String("ColorEffects:Inactive");
520  }
521 
522  _effects[0] = 0;
523  _effects[1] = 0;
524  _effects[2] = 0;
525 
526  if (!group.isEmpty())
527  {
528  KConfigGroup cfg(config, group);
529  const bool enabledByDefault = (state == QPalette::Disabled);
530 
531  if (cfg.readEntry("Enable", enabledByDefault))
532  {
533  _effects[Intensity] = cfg.readEntry("IntensityEffect", (int)((state == QPalette::Disabled) ? IntensityDarken : IntensityNoEffect));
534  _effects[Color] = cfg.readEntry("ColorEffect", (int)((state == QPalette::Disabled) ? ColorNoEffect : ColorDesaturate));
535  _effects[Contrast] = cfg.readEntry("ContrastEffect", (int)((state == QPalette::Disabled) ? ContrastFade : ContrastTint));
536  _amount[Intensity] = cfg.readEntry("IntensityAmount", (state == QPalette::Disabled) ? 0.10 : 0.0);
537  _amount[Color] = cfg.readEntry("ColorAmount", (state == QPalette::Disabled) ? 0.0 : -0.9);
538  _amount[Contrast] = cfg.readEntry("ContrastAmount", (state == QPalette::Disabled) ? 0.65 : 0.25);
539 
540  if (_effects[Color] > ColorNoEffect)
541  {
542  _color = cfg.readEntry("Color", (state == QPalette::Disabled) ? QColor(56, 56, 56)
543  : QColor(112, 111, 110));
544  }
545  }
546  }
547 }
548 
549 QBrush StateEffects::brush(const QBrush& background) const
550 {
551  QColor color = background.color(); // TODO - actually work on brushes
552 
553  switch (_effects[Intensity])
554  {
555  case IntensityShade:
556  color = ColorTools::shade(color, _amount[Intensity]);
557  break;
558  case IntensityDarken:
559  color = ColorTools::darken(color, _amount[Intensity]);
560  break;
561  case IntensityLighten:
562  color = ColorTools::lighten(color, _amount[Intensity]);
563  break;
564  }
565 
566  switch (_effects[Color])
567  {
568  case ColorDesaturate:
569  color = ColorTools::darken(color, 0.0, 1.0 - _amount[Color]);
570  break;
571  case ColorFade:
572  color = ColorTools::mix(color, _color, _amount[Color]);
573  break;
574  case ColorTint:
575  color = ColorTools::tint(color, _color, _amount[Color]);
576  break;
577  }
578 
579  return QBrush(color);
580 }
581 
582 QBrush StateEffects::brush(const QBrush& foreground, const QBrush& background) const
583 {
584  QColor color = foreground.color();
585  QColor bg = background.color();
586 
587  // Apply the foreground effects
588 
589  switch (_effects[Contrast])
590  {
591  case ContrastFade:
592  color = ColorTools::mix(color, bg, _amount[Contrast]);
593  break;
594  case ContrastTint:
595  color = ColorTools::tint(color, bg, _amount[Contrast]);
596  break;
597  }
598 
599  // Now apply global effects
600 
601  return brush(color);
602 }
603 
604 // ------------------------------------------------------------------------------------
605 
606 struct SetDefaultColors
607 {
608  int NormalBackground[3];
609  int AlternateBackground[3];
610  int NormalText[3];
611  int InactiveText[3];
612  int ActiveText[3];
613  int LinkText[3];
614  int VisitedText[3];
615  int NegativeText[3];
616  int NeutralText[3];
617  int PositiveText[3];
618 };
619 
620 struct DecoDefaultColors
621 {
622  int Hover[3];
623  int Focus[3];
624 };
625 
626 // these numbers come from the Breeze color scheme
627 static const SetDefaultColors defaultViewColors =
628 {
629  { 252, 252, 252 }, // Background
630  { 239, 240, 241 }, // Alternate
631  { 49, 54, 59 }, // Normal
632  { 127, 140, 141 }, // Inactive
633  { 61, 174, 233 }, // Active
634  { 41, 128, 185 }, // Link
635  { 127, 140, 141 }, // Visited
636  { 218, 68, 83 }, // Negative
637  { 246, 116, 0 }, // Neutral
638  { 39, 174, 96 } // Positive
639 };
640 
641 static const SetDefaultColors defaultWindowColors =
642 {
643  { 239, 240, 241 }, // Background
644  { 189, 195, 199 }, // Alternate
645  { 49, 54, 59 }, // Normal
646  { 127, 140, 141 }, // Inactive
647  { 61, 174, 233 }, // Active
648  { 41, 128, 185 }, // Link
649  { 127, 140, 141 }, // Visited
650  { 218, 68, 83 }, // Negative
651  { 246, 116, 0 }, // Neutral
652  { 39, 174, 96 } // Positive
653 };
654 
655 static const SetDefaultColors defaultButtonColors =
656 {
657  { 239, 240, 241 }, // Background
658  { 189, 195, 199 }, // Alternate
659  { 49, 54, 59 }, // Normal
660  { 127, 140, 141 }, // Inactive
661  { 61, 174, 233 }, // Active
662  { 41, 128, 185 }, // Link
663  { 127, 140, 141 }, // Visited
664  { 218, 68, 83 }, // Negative
665  { 246, 116, 0 }, // Neutral
666  { 39, 174, 96 } // Positive
667 };
668 
669 static const SetDefaultColors defaultSelectionColors =
670 {
671  { 61, 174, 233 }, // Background
672  { 29, 153, 243 }, // Alternate
673  { 239, 240, 241 }, // Normal
674  { 239, 240, 241 }, // Inactive
675  { 252, 252, 252 }, // Active
676  { 253, 188, 75 }, // Link
677  { 189, 195, 199 }, // Visited
678  { 218, 68, 83 }, // Negative
679  { 246, 116, 0 }, // Neutral
680  { 39, 174, 96 } // Positive
681 };
682 
683 static const SetDefaultColors defaultTooltipColors =
684 {
685  { 49, 54, 59 }, // Background
686  { 77, 77, 77 }, // Alternate
687  { 239, 240, 241 }, // Normal
688  { 189, 195, 199 }, // Inactive
689  { 61, 174, 233 }, // Active
690  { 41, 128, 185 }, // Link
691  { 127, 140, 141 }, // Visited
692  { 218, 68, 83 }, // Negative
693  { 246, 116, 0 }, // Neutral
694  { 39, 174, 96 } // Positive
695 };
696 
697 static const SetDefaultColors defaultComplementaryColors =
698 {
699  { 49, 54, 59 }, // Background
700  { 77, 77, 77 }, // Alternate
701  { 239, 240, 241 }, // Normal
702  { 189, 195, 199 }, // Inactive
703  { 61, 174, 233 }, // Active
704  { 41, 128, 185 }, // Link
705  { 127, 140, 141 }, // Visited
706  { 218, 68, 83 }, // Negative
707  { 246, 116, 0 }, // Neutral
708  { 39, 174, 96 } // Positive
709 };
710 
711 static const DecoDefaultColors defaultDecorationColors =
712 {
713  { 147, 206, 233 }, // Hover
714  { 61, 174, 233 }, // Focus
715 };
716 
717 // ------------------------------------------------------------------------------------
718 
719 class SchemeManagerPrivate : public QSharedData
720 {
721 public:
722 
723  explicit SchemeManagerPrivate(const KSharedConfigPtr&, QPalette::ColorGroup, const char*, SetDefaultColors);
724  explicit SchemeManagerPrivate(const KSharedConfigPtr&, QPalette::ColorGroup, const char*, SetDefaultColors, const QBrush&);
725  ~SchemeManagerPrivate() = default;
726 
727  QBrush background(SchemeManager::BackgroundRole) const;
728  QBrush foreground(SchemeManager::ForegroundRole) const;
729  QBrush decoration(SchemeManager::DecorationRole) const;
730  qreal contrast() const;
731 
732 private:
733 
734  void init(const KSharedConfigPtr&, QPalette::ColorGroup, const char*, SetDefaultColors);
735 
736 private:
737 
738  struct
739  {
740  QBrush fg[8],
741  bg[8],
742  deco[2];
743  } _brushes;
744 
745  qreal _contrast;
746 };
747 
748 #define DEFAULT(c) QColor( c[0], c[1], c[2] )
749 #define SET_DEFAULT(a) DEFAULT( defaults.a )
750 #define DECO_DEFAULT(a) DEFAULT( defaultDecorationColors.a )
751 
752 SchemeManagerPrivate::SchemeManagerPrivate(const KSharedConfigPtr& config,
753  QPalette::ColorGroup state,
754  const char* group,
755  SetDefaultColors defaults)
756 {
757  KConfigGroup cfg(config, group);
758  _contrast = SchemeManager::contrastF(config);
759 
760  // loaded-from-config colors (no adjustment)
761  _brushes.bg[0] = cfg.readEntry("BackgroundNormal", SET_DEFAULT(NormalBackground));
762  _brushes.bg[1] = cfg.readEntry("BackgroundAlternate", SET_DEFAULT(AlternateBackground));
763 
764  // the rest
765  init(config, state, group, defaults);
766 }
767 
768 SchemeManagerPrivate::SchemeManagerPrivate(const KSharedConfigPtr& config,
769  QPalette::ColorGroup state,
770  const char* group,
771  SetDefaultColors defaults,
772  const QBrush& tint)
773 {
774  KConfigGroup cfg(config, group);
775  _contrast = SchemeManager::contrastF(config);
776 
777  // loaded-from-config colors
778  _brushes.bg[0] = cfg.readEntry("BackgroundNormal", SET_DEFAULT(NormalBackground));
779  _brushes.bg[1] = cfg.readEntry("BackgroundAlternate", SET_DEFAULT(AlternateBackground));
780 
781  // adjustment
782  _brushes.bg[0] = ColorTools::tint(_brushes.bg[0].color(), tint.color(), 0.4);
783  _brushes.bg[1] = ColorTools::tint(_brushes.bg[1].color(), tint.color(), 0.4);
784 
785  // the rest
786  init(config, state, group, defaults);
787 }
788 
789 void SchemeManagerPrivate::init(const KSharedConfigPtr& config,
790  QPalette::ColorGroup state,
791  const char* group,
792  SetDefaultColors defaults)
793 {
794  KConfigGroup cfg(config, group);
795 
796  // loaded-from-config colors
797  _brushes.fg[0] = cfg.readEntry("ForegroundNormal", SET_DEFAULT(NormalText));
798  _brushes.fg[1] = cfg.readEntry("ForegroundInactive", SET_DEFAULT(InactiveText));
799  _brushes.fg[2] = cfg.readEntry("ForegroundActive", SET_DEFAULT(ActiveText));
800  _brushes.fg[3] = cfg.readEntry("ForegroundLink", SET_DEFAULT(LinkText));
801  _brushes.fg[4] = cfg.readEntry("ForegroundVisited", SET_DEFAULT(VisitedText));
802  _brushes.fg[5] = cfg.readEntry("ForegroundNegative", SET_DEFAULT(NegativeText));
803  _brushes.fg[6] = cfg.readEntry("ForegroundNeutral", SET_DEFAULT(NeutralText));
804  _brushes.fg[7] = cfg.readEntry("ForegroundPositive", SET_DEFAULT(PositiveText));
805  _brushes.deco[0] = cfg.readEntry("DecorationHover", DECO_DEFAULT(Hover));
806  _brushes.deco[1] = cfg.readEntry("DecorationFocus", DECO_DEFAULT(Focus));
807 
808  // apply state adjustments
809 
810  if (state != QPalette::Active)
811  {
812  StateEffects effects(state, config);
813 
814  for (auto &brush : _brushes.fg)
815  {
816  brush = effects.brush(brush, _brushes.bg[0]);
817  }
818 
819  _brushes.deco[0] = effects.brush(_brushes.deco[0], _brushes.bg[0]);
820  _brushes.deco[1] = effects.brush(_brushes.deco[1], _brushes.bg[0]);
821  _brushes.bg[0] = effects.brush(_brushes.bg[0]);
822  _brushes.bg[1] = effects.brush(_brushes.bg[1]);
823  }
824 
825  // calculated backgrounds
826  _brushes.bg[2] = ColorTools::tint(_brushes.bg[0].color(), _brushes.fg[2].color());
827  _brushes.bg[3] = ColorTools::tint(_brushes.bg[0].color(), _brushes.fg[3].color());
828  _brushes.bg[4] = ColorTools::tint(_brushes.bg[0].color(), _brushes.fg[4].color());
829  _brushes.bg[5] = ColorTools::tint(_brushes.bg[0].color(), _brushes.fg[5].color());
830  _brushes.bg[6] = ColorTools::tint(_brushes.bg[0].color(), _brushes.fg[6].color());
831  _brushes.bg[7] = ColorTools::tint(_brushes.bg[0].color(), _brushes.fg[7].color());
832 }
833 
834 QBrush SchemeManagerPrivate::background(SchemeManager::BackgroundRole role) const
835 {
836  switch (role)
837  {
838  case SchemeManager::AlternateBackground:
839  return _brushes.bg[1];
840  case SchemeManager::ActiveBackground:
841  return _brushes.bg[2];
842  case SchemeManager::LinkBackground:
843  return _brushes.bg[3];
844  case SchemeManager::VisitedBackground:
845  return _brushes.bg[4];
846  case SchemeManager::NegativeBackground:
847  return _brushes.bg[5];
848  case SchemeManager::NeutralBackground:
849  return _brushes.bg[6];
850  case SchemeManager::PositiveBackground:
851  return _brushes.bg[7];
852  default:
853  return _brushes.bg[0];
854  }
855 }
856 
857 QBrush SchemeManagerPrivate::foreground(SchemeManager::ForegroundRole role) const
858 {
859  switch (role)
860  {
861  case SchemeManager::InactiveText:
862  return _brushes.fg[1];
863  case SchemeManager::ActiveText:
864  return _brushes.fg[2];
865  case SchemeManager::LinkText:
866  return _brushes.fg[3];
867  case SchemeManager::VisitedText:
868  return _brushes.fg[4];
869  case SchemeManager::NegativeText:
870  return _brushes.fg[5];
871  case SchemeManager::NeutralText:
872  return _brushes.fg[6];
873  case SchemeManager::PositiveText:
874  return _brushes.fg[7];
875  default:
876  return _brushes.fg[0];
877  }
878 }
879 
880 QBrush SchemeManagerPrivate::decoration(SchemeManager::DecorationRole role) const
881 {
882  switch (role)
883  {
884  case SchemeManager::FocusColor:
885  return _brushes.deco[1];
886  default:
887  return _brushes.deco[0];
888  }
889 }
890 
891 qreal SchemeManagerPrivate::contrast() const
892 {
893  return _contrast;
894 }
895 
896 // ------------------------------------------------------------------------------------
897 
898 SchemeManager::SchemeManager(const SchemeManager& other) : d(other.d)
899 {
900 }
901 
902 SchemeManager::~SchemeManager()
903 {
904 }
905 
906 SchemeManager& SchemeManager::operator=(const SchemeManager& other)
907 {
908  d = other.d;
909  return *this;
910 }
911 
912 SchemeManager::SchemeManager(QPalette::ColorGroup state, ColorSet set, KSharedConfigPtr config)
913 {
914  if (!config)
915  {
916  config = KSharedConfig::openConfig();
917  }
918 
919  switch (set)
920  {
921  case Window:
922  d = new SchemeManagerPrivate(config, state, "Colors:Window", defaultWindowColors);
923  break;
924  case Button:
925  d = new SchemeManagerPrivate(config, state, "Colors:Button", defaultButtonColors);
926  break;
927  case Selection:
928  {
929  KConfigGroup group(config, "ColorEffects:Inactive");
930  // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
931  bool inactiveSelectionEffect = group.readEntry("ChangeSelectionColor", group.readEntry("Enable", true));
932  // if enabled, inactiver/disabled uses Window colors instead, ala gtk
933  // ...except tinted with the Selection:NormalBackground color so it looks more like selection
934  if (state == QPalette::Active || (state == QPalette::Inactive && !inactiveSelectionEffect))
935  {
936  d = new SchemeManagerPrivate(config, state, "Colors:Selection", defaultSelectionColors);
937  }
938  else if (state == QPalette::Inactive)
939  {
940  d = new SchemeManagerPrivate(config, state, "Colors:Window", defaultWindowColors,
941  SchemeManager(QPalette::Active, Selection, config).background());
942  }
943  else
944  {
945  // disabled (...and still want this branch when inactive+disabled exists)
946  d = new SchemeManagerPrivate(config, state, "Colors:Window", defaultWindowColors);
947  }
948  }
949  break;
950  case Tooltip:
951  d = new SchemeManagerPrivate(config, state, "Colors:Tooltip", defaultTooltipColors);
952  break;
953  case Complementary:
954  d = new SchemeManagerPrivate(config, state, "Colors:Complementary", defaultComplementaryColors);
955  break;
956  default:
957  d = new SchemeManagerPrivate(config, state, "Colors:View", defaultViewColors);
958  }
959 }
960 
961 int SchemeManager::contrast()
962 {
963  KConfigGroup g(KSharedConfig::openConfig(), "KDE");
964 
965  return g.readEntry("contrast", 7);
966 }
967 
968 qreal SchemeManager::contrastF(const KSharedConfigPtr& config)
969 {
970  if (config)
971  {
972  KConfigGroup g(config, "KDE");
973 
974  return 0.1 * g.readEntry("contrast", 7);
975  }
976 
977  return 0.1 * (qreal)contrast();
978 }
979 
980 QBrush SchemeManager::background(BackgroundRole role) const
981 {
982  return d->background(role);
983 }
984 
985 QBrush SchemeManager::foreground(ForegroundRole role) const
986 {
987  return d->foreground(role);
988 }
989 
990 QBrush SchemeManager::decoration(DecorationRole role) const
991 {
992  return d->decoration(role);
993 }
994 
995 QColor SchemeManager::shade(ShadeRole role) const
996 {
997  return shade(background().color(), role, d->contrast());
998 }
999 
1000 QColor SchemeManager::shade(const QColor& color, ShadeRole role)
1001 {
1002  return shade(color, role, SchemeManager::contrastF());
1003 }
1004 
1005 QColor SchemeManager::shade(const QColor& color, ShadeRole role, qreal contrast, qreal chromaAdjust)
1006 {
1007  // nan -> 1.0
1008  contrast = ((1.0 > contrast) ? ((-1.0 < contrast) ? contrast
1009  : -1.0)
1010  : 1.0);
1011  qreal y = ColorTools::luma(color);
1012  qreal yi = 1.0 - y;
1013 
1014  // handle very dark colors (base, mid, dark, shadow == midlight, light)
1015  if (y < 0.006)
1016  {
1017  switch (role)
1018  {
1019  case SchemeManager::LightShade:
1020  return ColorTools::shade(color, 0.05 + 0.95 * contrast, chromaAdjust);
1021  case SchemeManager::MidShade:
1022  return ColorTools::shade(color, 0.01 + 0.20 * contrast, chromaAdjust);
1023  case SchemeManager::DarkShade:
1024  return ColorTools::shade(color, 0.02 + 0.40 * contrast, chromaAdjust);
1025  default:
1026  return ColorTools::shade(color, 0.03 + 0.60 * contrast, chromaAdjust);
1027  }
1028  }
1029 
1030  // handle very light colors (base, midlight, light == mid, dark, shadow)
1031  if (y > 0.93)
1032  {
1033  switch (role)
1034  {
1035  case SchemeManager::MidlightShade:
1036  return ColorTools::shade(color, -0.02 - 0.20 * contrast, chromaAdjust);
1037  case SchemeManager::DarkShade:
1038  return ColorTools::shade(color, -0.06 - 0.60 * contrast, chromaAdjust);
1039  case SchemeManager::ShadowShade:
1040  return ColorTools::shade(color, -0.10 - 0.90 * contrast, chromaAdjust);
1041  default:
1042  return ColorTools::shade(color, -0.04 - 0.40 * contrast, chromaAdjust);
1043  }
1044  }
1045 
1046  // handle everything else
1047  qreal lightAmount = (0.05 + y * 0.55) * (0.25 + contrast * 0.75);
1048  qreal darkAmount = (- y) * (0.55 + contrast * 0.35);
1049 
1050  switch (role)
1051  {
1052  case SchemeManager::LightShade:
1053  return ColorTools::shade(color, lightAmount, chromaAdjust);
1054  case SchemeManager::MidlightShade:
1055  return ColorTools::shade(color, (0.15 + 0.35 * yi) * lightAmount, chromaAdjust);
1056  case SchemeManager::MidShade:
1057  return ColorTools::shade(color, (0.35 + 0.15 * y) * darkAmount, chromaAdjust);
1058  case SchemeManager::DarkShade:
1059  return ColorTools::shade(color, darkAmount, chromaAdjust);
1060  default:
1061  return ColorTools::darken(ColorTools::shade(color, darkAmount, chromaAdjust), 0.5 + 0.3 * y);
1062  }
1063 }
1064 
1065 void SchemeManager::adjustBackground(QPalette& palette, BackgroundRole newRole, QPalette::ColorRole color,
1066  ColorSet set, KSharedConfigPtr config)
1067 {
1068  palette.setBrush(QPalette::Active, color, SchemeManager(QPalette::Active, set, config).background(newRole));
1069  palette.setBrush(QPalette::Inactive, color, SchemeManager(QPalette::Inactive, set, config).background(newRole));
1070  palette.setBrush(QPalette::Disabled, color, SchemeManager(QPalette::Disabled, set, config).background(newRole));
1071 }
1072 
1073 void SchemeManager::adjustForeground(QPalette& palette, ForegroundRole newRole, QPalette::ColorRole color,
1074  ColorSet set, KSharedConfigPtr config)
1075 {
1076  palette.setBrush(QPalette::Active, color, SchemeManager(QPalette::Active, set, config).foreground(newRole));
1077  palette.setBrush(QPalette::Inactive, color, SchemeManager(QPalette::Inactive, set, config).foreground(newRole));
1078  palette.setBrush(QPalette::Disabled, color, SchemeManager(QPalette::Disabled, set, config).foreground(newRole));
1079 }
1080 
1081 QPalette SchemeManager::createApplicationPalette(const KSharedConfigPtr& config)
1082 {
1083  QPalette palette;
1084 
1085  static const QPalette::ColorGroup states[3] =
1086  {
1087  QPalette::Active,
1088  QPalette::Inactive,
1089  QPalette::Disabled
1090  };
1091 
1092  // TT thinks tooltips shouldn't use active, so we use our active colors for all states
1093  SchemeManager schemeTooltip(QPalette::Active, SchemeManager::Tooltip, config);
1094 
1095  for (auto &state : states)
1096  {
1097  SchemeManager schemeView(state, SchemeManager::View, config);
1098  SchemeManager schemeWindow(state, SchemeManager::Window, config);
1099  SchemeManager schemeButton(state, SchemeManager::Button, config);
1100  SchemeManager schemeSelection(state, SchemeManager::Selection, config);
1101 
1102  palette.setBrush(state, QPalette::WindowText, schemeWindow.foreground());
1103  palette.setBrush(state, QPalette::Window, schemeWindow.background());
1104  palette.setBrush(state, QPalette::Base, schemeView.background());
1105  palette.setBrush(state, QPalette::Text, schemeView.foreground());
1106  palette.setBrush(state, QPalette::Button, schemeButton.background());
1107  palette.setBrush(state, QPalette::ButtonText, schemeButton.foreground());
1108  palette.setBrush(state, QPalette::Highlight, schemeSelection.background());
1109  palette.setBrush(state, QPalette::HighlightedText, schemeSelection.foreground());
1110  palette.setBrush(state, QPalette::ToolTipBase, schemeTooltip.background());
1111  palette.setBrush(state, QPalette::ToolTipText, schemeTooltip.foreground());
1112 
1113  palette.setColor(state, QPalette::Light, schemeWindow.shade(SchemeManager::LightShade));
1114  palette.setColor(state, QPalette::Midlight, schemeWindow.shade(SchemeManager::MidlightShade));
1115  palette.setColor(state, QPalette::Mid, schemeWindow.shade(SchemeManager::MidShade));
1116  palette.setColor(state, QPalette::Dark, schemeWindow.shade(SchemeManager::DarkShade));
1117  palette.setColor(state, QPalette::Shadow, schemeWindow.shade(SchemeManager::ShadowShade));
1118 
1119  palette.setBrush(state, QPalette::AlternateBase, schemeView.background(SchemeManager::AlternateBackground));
1120  palette.setBrush(state, QPalette::Link, schemeView.foreground(SchemeManager::LinkText));
1121  palette.setBrush(state, QPalette::LinkVisited, schemeView.foreground(SchemeManager::VisitedText));
1122  }
1123 
1124  return palette;
1125 }
1126 
QPalette::setBrush
void setBrush(ColorRole role, const QBrush &brush)
SchemeManager::LinkBackground
Fourth color; corresponds to (unvisited) links.
Definition: schememanager.h:168
SchemeManager::PositiveBackground
Eigth color; for example, success messages, trusted content.
Definition: schememanager.h:188
QPainter::end
bool end()
ColorTools::darken
QColor darken(const QColor &color, qreal ky=0.5, qreal kc=1.0)
Adjust the luma of a color by changing its distance from black.
Definition: schememanager.cpp:158
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
QPainter::setCompositionMode
void setCompositionMode(CompositionMode mode)
QColor::alphaF
qreal alphaF() const
SchemeManager::Complementary
Complementary areas.
Definition: schememanager.h:125
QPalette::setColor
void setColor(ColorGroup group, ColorRole role, const QColor &color)
QColor::redF
qreal redF() const
QColor::blueF
qreal blueF() const
Button
SchemeManager
A set of methods used to work with colors.
Definition: schememanager.h:66
SchemeManager::VisitedBackground
Fifth color; corresponds to visited links.
Definition: schememanager.h:176
QColor::setAlpha
void setAlpha(int alpha)
SchemeManager::MidlightShade
The midlight color is in between base() and light().
Definition: schememanager.h:295
QBrush
defaultSelectionColors
static const SetDefaultColors defaultSelectionColors
Definition: schememanager.cpp:669
defaultComplementaryColors
static const SetDefaultColors defaultComplementaryColors
Definition: schememanager.cpp:697
SchemeManager::foreground
QBrush foreground(ForegroundRole=NormalText) const
Retrieve the requested foreground brush.
Definition: schememanager.cpp:985
SchemeManager::View
Views; for example, frames, input fields, etc.
Definition: schememanager.h:84
SET_DEFAULT
#define SET_DEFAULT(a)
Definition: schememanager.cpp:749
SchemeManager::SchemeManager
SchemeManager(const SchemeManager &)
Construct a copy of another SchemeManager.
Definition: schememanager.cpp:898
ColorTools::mixQreal
static qreal mixQreal(qreal a, qreal b, qreal bias)
Definition: schememanager.cpp:81
SchemeManager::Window
Non-editable window elements; for example, menus.
Definition: schememanager.h:90
SchemeManager::FocusColor
Color used to draw decorations for items which have input focus.
Definition: schememanager.h:269
QBrush::color
const QColor & color() const
SchemeManager::~SchemeManager
virtual ~SchemeManager()
Definition: schememanager.cpp:902
SchemeManager::contrast
static int contrast()
Returns the contrast for borders.
Definition: schememanager.cpp:961
ColorTools::lighten
QColor lighten(const QColor &color, qreal ky=0.5, qreal kc=1.0)
Adjust the luma of a color by changing its distance from white.
Definition: schememanager.cpp:146
QImage::pixel
QRgb pixel(int x, int y) const
QSharedData
ColorTools::luma
qreal luma(const QColor &color)
Calculate the luma of a color.
Definition: schememanager.cpp:92
SchemeManager::NeutralText
Seventh color; for example, warnings, secure/encrypted content.
Definition: schememanager.h:247
SchemeManager::NeutralBackground
Seventh color; for example, warnings, secure/encrypted content.
Definition: schememanager.h:184
ColorTools::contrastRatioForLuma
static qreal contrastRatioForLuma(qreal y1, qreal y2)
Calculate the contrast ratio between two colors, according to the W3C/WCAG2.0 algorithm, (Lmax + 0.05)/(Lmin + 0.05), where Lmax and Lmin are the luma values of the lighter color and the darker color, respectively.
Definition: schememanager.cpp:128
SchemeManager::PositiveText
Eigth color; for example, additions, success messages, trusted content.
Definition: schememanager.h:252
SchemeManager::decoration
QBrush decoration(DecorationRole) const
Retrieve the requested decoration brush.
Definition: schememanager.cpp:990
QPainter
QString::isEmpty
bool isEmpty() const
ColorTools::tintHelper
static QColor tintHelper(const QColor &base, qreal baseLuma, const QColor &color, qreal amount)
Definition: schememanager.cpp:208
ColorTools::mix
QColor mix(const QColor &c1, const QColor &c2, qreal bias)
Blend two colors into a new color by linear combination.
Definition: schememanager.cpp:183
QColor::greenF
qreal greenF() const
SchemeManager::ColorSet
ColorSet
This enumeration describes the color set for which a color is being selected.
Definition: schememanager.h:77
SchemeManager::NegativeText
Sixth color; for example, errors, untrusted content, deletions, etc.
Definition: schememanager.h:243
SchemeManager::contrastF
static qreal contrastF(const KSharedConfigPtr &config=KSharedConfigPtr())
Returns the contrast for borders as a floating point value.
Definition: schememanager.cpp:968
QString
QColor
SchemeManager::Button
Buttons and button-like controls.
Definition: schememanager.h:98
SchemeManager::Tooltip
Tooltips.
Definition: schememanager.h:115
SchemeManager::VisitedText
Fifth color; used for (visited) links.
Definition: schememanager.h:238
SchemeManager::shade
QColor shade(ShadeRole) const
Retrieve the requested shade color, using SchemeManager::background(SchemeManager::NormalBackground) ...
Definition: schememanager.cpp:995
schememanager.h
SchemeManager::NegativeBackground
Sixth color; for example, errors, untrusted content, etc.
Definition: schememanager.h:180
QColor::fromRgbF
QColor fromRgbF(qreal r, qreal g, qreal b, qreal a)
ColorTools::contrastRatio
qreal contrastRatio(const QColor &c1, const QColor &c2)
Definition: schememanager.cpp:138
defaultTooltipColors
static const SetDefaultColors defaultTooltipColors
Definition: schememanager.cpp:683
QImage
ColorTools::shade
QColor shade(const QColor &color, qreal ky, qreal kc=0.0)
Adjust the luma and chroma components of a color.
Definition: schememanager.cpp:171
SchemeManager::ActiveBackground
Third color; for example, items which are new, active, requesting attention, etc. ...
Definition: schememanager.h:159
SchemeManager::ForegroundRole
ForegroundRole
This enumeration describes the foreground color being selected from the given set.
Definition: schememanager.h:207
SchemeManager::DarkShade
The dark color is in between mid() and shadow().
Definition: schememanager.h:303
ColorTools::wrap
static qreal wrap(qreal a, qreal d=1.0)
Definition: schememanager.cpp:65
QLatin1String
NaN::d
const double d
Definition: nan.h:34
DECO_DEFAULT
#define DECO_DEFAULT(a)
Definition: schememanager.cpp:750
defaultButtonColors
static const SetDefaultColors defaultButtonColors
Definition: schememanager.cpp:655
SchemeManager::ActiveText
Third color; for example items which are new, active, requesting attention, etc.
Definition: schememanager.h:224
ColorTools::tint
QColor tint(const QColor &base, const QColor &color, qreal amount=0.3)
Create a new color by tinting one color with another.
Definition: schememanager.cpp:228
SchemeManager::AlternateBackground
Alternate background; for example, for use in lists.
Definition: schememanager.h:149
SchemeManager::operator=
SchemeManager & operator=(const SchemeManager &)
Standard assignment operator.
Definition: schememanager.cpp:906
SchemeManager::MidShade
The mid color is in between base() and dark().
Definition: schememanager.h:299
SchemeManager::LightShade
The light color is lighter than dark() or shadow() and contrasts with the base color.
Definition: schememanager.h:291
SchemeManager::BackgroundRole
BackgroundRole
This enumeration describes the background color being selected from the given set.
Definition: schememanager.h:137
ColorTools::normalize
static qreal normalize(qreal a)
normalize: like qBound(a, 0.0, 1.0) but without needing the args and with "safer" behavior on NaN (is...
Definition: schememanager.cpp:76
defaultViewColors
static const SetDefaultColors defaultViewColors
Definition: schememanager.cpp:627
SchemeManager::background
QBrush background(BackgroundRole=NormalBackground) const
Retrieve the requested background brush.
Definition: schememanager.cpp:980
defaultWindowColors
static const SetDefaultColors defaultWindowColors
Definition: schememanager.cpp:641
ColorTools::overlayColors
QColor overlayColors(const QColor &base, const QColor &paint, QPainter::CompositionMode comp)
Blend two colors into a new color by painting the second color over the first using the specified com...
Definition: schememanager.cpp:278
SchemeManager::adjustBackground
static void adjustBackground(QPalette &, BackgroundRole newRole=NormalBackground, QPalette::ColorRole color=QPalette::Base, ColorSet set=View, KSharedConfigPtr=KSharedConfigPtr())
Adjust a QPalette by replacing the specified QPalette::ColorRole with the requested background color ...
Definition: schememanager.cpp:1065
SchemeManager::LinkText
Fourth color; use for (unvisited) links.
Definition: schememanager.h:230
SchemeManager::adjustForeground
static void adjustForeground(QPalette &, ForegroundRole newRole=NormalText, QPalette::ColorRole color=QPalette::Text, ColorSet set=View, KSharedConfigPtr=KSharedConfigPtr())
Adjust a QPalette by replacing the specified QPalette::ColorRole with the requested foreground color ...
Definition: schememanager.cpp:1073
defaultDecorationColors
static const DecoDefaultColors defaultDecorationColors
Definition: schememanager.cpp:711
SchemeManager::ShadowShade
The shadow color is darker than light() or midlight() and contrasts the base color.
Definition: schememanager.h:308
SchemeManager::Selection
Selected items in views.
Definition: schememanager.h:106
SchemeManager::InactiveText
Second color; for example, comments, items which are old, inactive or disabled.
Definition: schememanager.h:219
ColorTools::getHcy
void getHcy(const QColor &color, qreal *h, qreal *c, qreal *y, qreal *a=0)
Calculate hue, chroma and luma of a color in one call.
Definition: schememanager.cpp:100
yc
static const qreal yc[3]
Definition: schememanager.cpp:303
SchemeManager::createApplicationPalette
static QPalette createApplicationPalette(const KSharedConfigPtr &config)
Used to obtain the QPalette that will be used to set the application palette from KDE Platform theme...
Definition: schememanager.cpp:1081
QPalette
SchemeManager::DecorationRole
DecorationRole
This enumeration describes the decoration color being selected from the given set.
Definition: schememanager.h:264
SchemeManager::ShadeRole
ShadeRole
This enumeration describes the color shade being selected from the given set.
Definition: schememanager.h:285
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Wed Dec 11 2019 07:20:58 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

edu API Reference

Skip menu "edu API Reference"
  •     core
  • kstars

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal