1 /*****************************************************************************
2 * Copyright (C) 2000-2002 Shie Erlich <erlich@users.sourceforge.net> *
3 * Copyright (C) 2000-2002 Rafi Yanai <yanai@users.sourceforge.net> *
4 * Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] *
5 * *
6 * This file is part of Krusader [https://krusader.org]. *
7 * *
8 * Krusader is free software: you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation, either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * Krusader is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with Krusader. If not, see [http://www.gnu.org/licenses/]. *
20 *****************************************************************************/
21
22 #include "krcolorcache.h"
23 #include "../krglobal.h"
24 #include "../defaults.h"
25
26 // QtCore
27 #include <QDebug>
28 #include <QFile>
29 #include <QList>
30 // QtGui
31 #include <QPixmapCache>
32 // QtWidgets
33 #include <QApplication>
34
35 #include <KConfigCore/KSharedConfig>
36
37 // Macro: set target = col, if col is valid
38 #define SETCOLOR(target, col) { if (col.isValid()) target = col; }
39
40 // Static class, which lists all allowed keywords for a quick access.
41 // Just call a method to initialize it.
42 class KrColorSettingNames
43 {
44 static QMap<QString, bool> s_colorNames;
45 static QMap<QString, bool> s_numNames;
46 static QMap<QString, bool> s_boolNames;
47 static void initialize();
48 public:
49 static QStringList getColorNames();
50 static bool isColorNameValid(const QString & settingName);
51 static QStringList getNumNames();
52 static bool isNumNameValid(const QString & settingName);
53 static QStringList getBoolNames();
54 static bool isBoolNameValid(const QString & settingName);
55 } krColorSettingNames;
56
57 QMap<QString, bool> KrColorSettingNames::s_colorNames;
58 QMap<QString, bool> KrColorSettingNames::s_numNames;
59 QMap<QString, bool> KrColorSettingNames::s_boolNames;
60
initialize()61 void KrColorSettingNames::initialize()
62 {
63 if (!s_colorNames.empty())
64 return;
65 s_colorNames["Foreground"] = true;
66 s_colorNames["Inactive Foreground"] = true;
67 s_colorNames["Directory Foreground"] = true;
68 s_colorNames["Inactive Directory Foreground"] = true;
69 s_colorNames["Executable Foreground"] = true;
70 s_colorNames["Inactive Executable Foreground"] = true;
71 s_colorNames["Symlink Foreground"] = true;
72 s_colorNames["Inactive Symlink Foreground"] = true;
73 s_colorNames["Invalid Symlink Foreground"] = true;
74 s_colorNames["Inactive Invalid Symlink Foreground"] = true;
75 s_colorNames["Marked Foreground"] = true;
76 s_colorNames["Inactive Marked Foreground"] = true;
77 s_colorNames["Marked Background"] = true;
78 s_colorNames["Inactive Marked Background"] = true;
79 s_colorNames["Current Foreground"] = true;
80 s_colorNames["Inactive Current Foreground"] = true;
81 s_colorNames["Current Background"] = true;
82 s_colorNames["Inactive Current Background"] = true;
83 s_colorNames["Marked Current Foreground"] = true;
84 s_colorNames["Inactive Marked Current Foreground"] = true;
85 s_colorNames["Alternate Background"] = true;
86 s_colorNames["Inactive Alternate Background"] = true;
87 s_colorNames["Background"] = true;
88 s_colorNames["Inactive Background"] = true;
89 s_colorNames["Alternate Marked Background"] = true;
90 s_colorNames["Inactive Alternate Marked Background"] = true;
91 s_colorNames["Dim Target Color"] = true;
92
93 s_numNames["Dim Factor"] = true;
94
95 s_boolNames["KDE Default"] = true;
96 s_boolNames["Enable Alternate Background"] = true;
97 s_boolNames["Show Current Item Always"] = true;
98 s_boolNames["Dim Inactive Colors"] = true;
99 }
100
getColorNames()101 QStringList KrColorSettingNames::getColorNames()
102 {
103 initialize();
104 return s_colorNames.keys();
105 }
106
isColorNameValid(const QString & settingName)107 bool KrColorSettingNames::isColorNameValid(const QString & settingName)
108 {
109 initialize();
110 return s_colorNames.contains(settingName);
111 }
112
getNumNames()113 QStringList KrColorSettingNames::getNumNames()
114 {
115 initialize();
116 return s_numNames.keys();
117 }
118
isNumNameValid(const QString & settingName)119 bool KrColorSettingNames::isNumNameValid(const QString & settingName)
120 {
121 initialize();
122 return s_numNames.contains(settingName);
123 }
124
getBoolNames()125 QStringList KrColorSettingNames::getBoolNames()
126 {
127 initialize();
128 return s_boolNames.keys();
129 }
130
isBoolNameValid(const QString & settingName)131 bool KrColorSettingNames::isBoolNameValid(const QString & settingName)
132 {
133 initialize();
134 return s_boolNames.contains(settingName);
135 }
136
137
138
139 /*
140 KrColorSettings implementation. Contains all properties in QMaps. loadFromConfig initializes them from krConfig.
141 */
142 class KrColorSettingsImpl
143 {
144 friend class KrColorSettings;
145 QMap<QString, QString> m_colorTextValues;
146 QMap<QString, QColor> m_colorValues;
147 QMap<QString, int> m_numValues;
148 QMap<QString, bool> m_boolValues;
149 void loadFromConfig();
150 };
151
loadFromConfig()152 void KrColorSettingsImpl::loadFromConfig()
153 {
154 KConfigGroup group(krConfig, "Colors");
155 QStringList names = KrColorSettingNames::getColorNames();
156 for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) {
157 m_colorTextValues[*it] = group.readEntry(*it, QString());
158 if (m_colorTextValues[*it].count(',') == 2)
159 m_colorValues[*it] = group.readEntry(*it, QColor());
160 else
161 m_colorValues[*it] = QColor();
162 }
163 names = KrColorSettingNames::getNumNames();
164 for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) {
165 if (!group.readEntry(*it, QString()).isEmpty()) {
166 m_numValues[*it] = group.readEntry(*it, (long long)0);
167 }
168 }
169 names = KrColorSettingNames::getBoolNames();
170 for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) {
171 if (!group.readEntry(*it, QString()).isEmpty()) {
172 m_boolValues[*it] = group.readEntry(*it, false);
173 }
174 }
175 }
176
KrColorSettings()177 KrColorSettings::KrColorSettings()
178 {
179 m_impl = new KrColorSettingsImpl();
180 m_impl->loadFromConfig();
181 }
182
KrColorSettings(const KrColorSettings & src)183 KrColorSettings::KrColorSettings(const KrColorSettings & src)
184 {
185 m_impl = new KrColorSettingsImpl();
186 operator =(src);
187 }
188
~KrColorSettings()189 KrColorSettings::~KrColorSettings()
190 {
191 delete m_impl;
192 }
193
operator =(const KrColorSettings & src)194 const KrColorSettings & KrColorSettings::operator= (const KrColorSettings & src)
195 {
196 if (this == & src)
197 return * this;
198 QStringList names = KrColorSettingNames::getColorNames();
199 for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) {
200 m_impl->m_colorTextValues[*it] = src.m_impl->m_colorTextValues[*it];
201 m_impl->m_colorValues[*it] = src.m_impl->m_colorValues[*it];
202 }
203 for (QMap<QString, int>::Iterator it = src.m_impl->m_numValues.begin(); it != src.m_impl->m_numValues.end(); ++it) {
204 m_impl->m_numValues[it.key()] = it.value();
205 }
206 for (QMap<QString, bool>::Iterator it = src.m_impl->m_boolValues.begin(); it != src.m_impl->m_boolValues.end(); ++it) {
207 m_impl->m_boolValues[it.key()] = it.value();
208 }
209 return * this;
210 }
211
getColorNames()212 QList<QString> KrColorSettings::getColorNames()
213 {
214 return KrColorSettingNames::getColorNames();
215 }
216
isColorNameValid(const QString & settingName)217 bool KrColorSettings::isColorNameValid(const QString & settingName)
218 {
219 return KrColorSettingNames::isColorNameValid(settingName);
220 }
221
setColorValue(const QString & settingName,const QColor & color)222 bool KrColorSettings::setColorValue(const QString & settingName, const QColor & color)
223 {
224 if (!isColorNameValid(settingName)) {
225 qWarning() << "Invalid color setting name: " << settingName;
226 return false;
227 }
228 m_impl->m_colorValues[settingName] = color;
229 return true;
230 }
231
getColorValue(const QString & settingName) const232 QColor KrColorSettings::getColorValue(const QString & settingName) const
233 {
234 if (!isColorNameValid(settingName)) {
235 qWarning() << "Invalid color setting name: " << settingName;
236 return QColor();
237 }
238 return m_impl->m_colorValues[settingName];
239 }
240
setColorTextValue(const QString & settingName,const QString & colorText)241 bool KrColorSettings::setColorTextValue(const QString & settingName, const QString & colorText)
242 {
243 if (!isColorNameValid(settingName)) {
244 qWarning() << "Invalid color setting name: " << settingName;
245 return false;
246 }
247 m_impl->m_colorTextValues[settingName] = colorText;
248 return true;
249 }
250
getColorTextValue(const QString & settingName) const251 QString KrColorSettings::getColorTextValue(const QString & settingName) const
252 {
253 if (!isColorNameValid(settingName)) {
254 qWarning() << "Invalid color setting name: " << settingName;
255 return QString();
256 }
257 return m_impl->m_colorTextValues[settingName];
258 }
259
getNumNames()260 QList<QString> KrColorSettings::getNumNames()
261 {
262 return KrColorSettingNames::getNumNames();
263 }
264
isNumNameValid(const QString & settingName)265 bool KrColorSettings::isNumNameValid(const QString & settingName)
266 {
267 return KrColorSettingNames::isNumNameValid(settingName);
268 }
269
setNumValue(const QString & settingName,int value)270 bool KrColorSettings::setNumValue(const QString & settingName, int value)
271 {
272 if (!isNumNameValid(settingName)) {
273 qWarning() << "Invalid number setting name: " << settingName;
274 return false;
275 }
276 m_impl->m_numValues[settingName] = value;
277 return true;
278 }
279
getNumValue(const QString & settingName,int defaultValue) const280 int KrColorSettings::getNumValue(const QString & settingName, int defaultValue) const
281 {
282 if (!isNumNameValid(settingName)) {
283 qWarning() << "Invalid number setting name: " << settingName;
284 return 0;
285 }
286 if (!m_impl->m_numValues.contains(settingName))
287 return defaultValue;
288 return m_impl->m_numValues[settingName];
289 }
290
getBoolNames()291 QList<QString> KrColorSettings::getBoolNames()
292 {
293 return KrColorSettingNames::getBoolNames();
294 }
295
isBoolNameValid(const QString & settingName)296 bool KrColorSettings::isBoolNameValid(const QString & settingName)
297 {
298 return KrColorSettingNames::isBoolNameValid(settingName);
299 }
300
setBoolValue(const QString & settingName,bool value)301 bool KrColorSettings::setBoolValue(const QString & settingName, bool value)
302 {
303 if (!isBoolNameValid(settingName)) {
304 qWarning() << "Invalid bool setting name: " << settingName;
305 return false;
306 }
307 m_impl->m_boolValues[settingName] = value;
308 return true;
309 }
310
getBoolValue(const QString & settingName,bool defaultValue) const311 int KrColorSettings::getBoolValue(const QString & settingName, bool defaultValue) const
312 {
313 if (!isBoolNameValid(settingName)) {
314 qWarning() << "Invalid bool setting name: " << settingName;
315 return false;
316 }
317 if (!m_impl->m_boolValues.contains(settingName))
318 return defaultValue;
319 return m_impl->m_boolValues[settingName];
320 }
321
322
323
KrColorItemType()324 KrColorItemType::KrColorItemType()
325 {
326 m_fileType = File;
327 m_alternateBackgroundColor = false;
328 m_activePanel = false;
329 m_currentItem = false;
330 m_selectedItem = false;
331 }
332
KrColorItemType(FileType type,bool alternateBackgroundColor,bool activePanel,bool currentItem,bool selectedItem)333 KrColorItemType::KrColorItemType(FileType type, bool alternateBackgroundColor, bool activePanel, bool currentItem, bool selectedItem)
334 {
335 m_fileType = type;
336 m_alternateBackgroundColor = alternateBackgroundColor;
337 m_activePanel = activePanel;
338 m_currentItem = currentItem;
339 m_selectedItem = selectedItem;
340 }
341
KrColorItemType(const KrColorItemType & src)342 KrColorItemType::KrColorItemType(const KrColorItemType & src)
343 {
344 operator= (src);
345 }
346
operator =(const KrColorItemType & src)347 const KrColorItemType & KrColorItemType::operator= (const KrColorItemType & src)
348 {
349 if (this == & src)
350 return * this;
351 m_fileType = src.m_fileType;
352 m_alternateBackgroundColor = src.m_alternateBackgroundColor;
353 m_activePanel = src.m_activePanel;
354 m_currentItem = src.m_currentItem;
355 m_selectedItem = src.m_selectedItem;
356 return * this;
357 }
358
359
360
361
362 /*
363 KrColorCache implementation. Contains the KrColorSettings used for teh calculation and the cache for the results.
364 getColors is the only method to call. All other are taken from the previous versions.
365 */
366 class KrColorCacheImpl
367 {
368 friend class KrColorCache;
369 QMap<QString, KrColorGroup> m_cachedColors;
370 KrColorSettings m_colorSettings;
371
372 KrColorGroup getColors(const KrColorItemType & type) const;
373 static const QColor & setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2);
374 QColor getForegroundColor(bool isActive) const;
375 QColor getSpecialForegroundColor(const QString & type, bool isActive) const;
376 QColor getBackgroundColor(bool isActive) const;
377 QColor getAlternateBackgroundColor(bool isActive) const;
378 QColor getMarkedForegroundColor(bool isActive) const;
379 QColor getMarkedBackgroundColor(bool isActive) const;
380 QColor getAlternateMarkedBackgroundColor(bool isActive) const;
381 QColor getCurrentForegroundColor(bool isActive) const;
382 QColor getCurrentBackgroundColor(bool isActive) const;
383 QColor getCurrentMarkedForegroundColor(bool isActive) const;
384 QColor dimColor(QColor color, bool isBackgroundColor) const;
385 };
386
getColors(const KrColorItemType & type) const387 KrColorGroup KrColorCacheImpl::getColors(const KrColorItemType & type) const
388 {
389 KrColorGroup result;
390 if (m_colorSettings.getBoolValue("KDE Default", _KDEDefaultColors)) {
391 bool enableAlternateBackground = m_colorSettings.getBoolValue("Enable Alternate Background", _AlternateBackground);
392
393 QPalette p = QGuiApplication::palette();
394 QColor background = enableAlternateBackground && type.m_alternateBackgroundColor ?
395 p.color(QPalette::Active, QPalette::Base)
396 : p.color(QPalette::Active, QPalette::AlternateBase);
397 result.setBackground(background);
398 result.setText(p.color(QPalette::Active, QPalette::Text));
399 result.setHighlight(p.color(QPalette::Active, QPalette::Highlight));
400 result.setHighlightedText(p.color(QPalette::Active, QPalette::HighlightedText));
401
402 /* if (type.m_currentItem && type.m_activePanel)
403 {
404 QColor currentBackground = KColorScheme(QPalette::Active).background(KColorScheme::ActiveBackground).color();
405 // set the background
406 result.setColor(QColorGroup::Highlight, currentBackground);
407 result.setColor(QColorGroup::Base, currentBackground);
408 result.setColor(QColorGroup::Background, currentBackground);
409 }*/
410 return result;
411 }
412 bool markCurrentAlways = m_colorSettings.getBoolValue("Show Current Item Always", _ShowCurrentItemAlways);
413 bool dimBackground = m_colorSettings.getBoolValue("Dim Inactive Colors", false);
414
415 // cache m_activePanel flag. If color dimming is turned on, it is set to true, as the inactive colors
416 // are calculated from the active ones at the end.
417 bool isActive = type.m_activePanel;
418 if (dimBackground)
419 isActive = true;
420
421 // First calculate fore- and background.
422 QColor background = type.m_alternateBackgroundColor ?
423 getAlternateBackgroundColor(isActive)
424 : getBackgroundColor(isActive);
425 QColor foreground;
426 switch (type.m_fileType) {
427 case KrColorItemType::Directory :
428 foreground = getSpecialForegroundColor("Directory", isActive);
429 break;
430 case KrColorItemType::Executable :
431 foreground = getSpecialForegroundColor("Executable", isActive);
432 break;
433 case KrColorItemType::InvalidSymlink :
434 foreground = getSpecialForegroundColor("Invalid Symlink", isActive);
435 break;
436 case KrColorItemType::Symlink :
437 foreground = getSpecialForegroundColor("Symlink", isActive);
438 break;
439 default:
440 foreground = getForegroundColor(isActive);
441 }
442
443 // set the background color
444 result.setBackground(background);
445
446 // set the foreground color
447 result.setText(foreground);
448
449 // now the color of a marked item
450 QColor markedBackground = type.m_alternateBackgroundColor ?
451 getAlternateMarkedBackgroundColor(isActive)
452 : getMarkedBackgroundColor(isActive);
453 QColor markedForeground = getMarkedForegroundColor(isActive);
454 if (!markedForeground.isValid()) // transparent
455 // choose fore- or background, depending on its contrast compared to markedBackground
456 markedForeground = setColorIfContrastIsSufficient(markedBackground, foreground, background);
457
458 // set it in the color group (different group color than normal foreground!)
459 result.setHighlightedText(markedForeground);
460 result.setHighlight(markedBackground);
461
462 // In case the current item is a selected one, set the fore- and background colors for the contrast calculation below
463 if (type.m_selectedItem) {
464 background = markedBackground;
465 foreground = markedForeground;
466 }
467
468 // finally the current item
469 if (type.m_currentItem && (markCurrentAlways || isActive)) {
470 // if this is the current item AND the panels has the focus OR the current should be marked always
471 QColor currentBackground = getCurrentBackgroundColor(isActive);
472
473 if (!currentBackground.isValid()) // transparent
474 currentBackground = background;
475
476 // set the background
477 result.setHighlight(currentBackground);
478 result.setBackground(currentBackground);
479
480 QColor color;
481 if (type.m_selectedItem)
482 color = getCurrentMarkedForegroundColor(isActive);
483 if (!color.isValid()) { // not used
484 color = getCurrentForegroundColor(isActive);
485 if (!color.isValid()) // transparent
486 // choose fore- or background, depending on its contrast compared to markedBackground
487 color = setColorIfContrastIsSufficient(currentBackground, foreground, background);
488 }
489
490 // set the foreground
491 result.setText(color);
492 result.setHighlightedText(color);
493 }
494
495 if (dimBackground && !type.m_activePanel) {
496 // if color dimming is chosen, dim the colors for the inactive panel
497 result.setBackground(dimColor(result.background(), true));
498 result.setText(dimColor(result.text(), false));
499 result.setHighlightedText(dimColor(result.highlightedText(), false));
500 result.setHighlight(dimColor(result.highlight(), true));
501 }
502 return result;
503 }
504
setColorIfContrastIsSufficient(const QColor & background,const QColor & color1,const QColor & color2)505 const QColor & KrColorCacheImpl::setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2)
506 {
507 #define sqr(x) ((x)*(x))
508 int contrast = sqr(color1.red() - background.red()) + sqr(color1.green() - background.green()) + sqr(color1.blue() - background.blue());
509
510 // if the contrast between background and color1 is too small, take color2 instead.
511 if (contrast < 1000)
512 return color2;
513 return color1;
514 }
515
getForegroundColor(bool isActive) const516 QColor KrColorCacheImpl::getForegroundColor(bool isActive) const
517 {
518 QPalette p = QGuiApplication::palette();
519 QColor color = p.color(QPalette::Active, QPalette::Text);
520 SETCOLOR(color, m_colorSettings.getColorValue("Foreground"));
521 if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Foreground"));
522 return color;
523 }
524
getSpecialForegroundColor(const QString & type,bool isActive) const525 QColor KrColorCacheImpl::getSpecialForegroundColor(const QString & type, bool isActive) const
526 {
527 QString colorName = "Inactive " + type + " Foreground";
528 if (!isActive && m_colorSettings.getColorTextValue(colorName) == "Inactive Foreground")
529 return getForegroundColor(false);
530 QColor color = m_colorSettings.getColorValue(type + " Foreground");
531 if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue(colorName));
532 if (!color.isValid())
533 return getForegroundColor(isActive);
534 return color;
535 }
536
getBackgroundColor(bool isActive) const537 QColor KrColorCacheImpl::getBackgroundColor(bool isActive) const
538 {
539 QColor color = QGuiApplication::palette().color(QPalette::Active, QPalette::Base);
540 SETCOLOR(color, m_colorSettings.getColorValue("Background"));
541 if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Background"));
542 return color;
543 }
544
getAlternateBackgroundColor(bool isActive) const545 QColor KrColorCacheImpl::getAlternateBackgroundColor(bool isActive) const
546 {
547 QPalette p = QGuiApplication::palette();
548 if (isActive && m_colorSettings.getColorTextValue("Alternate Background") == "Background")
549 return getBackgroundColor(true);
550 if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Background").isEmpty())
551 return getAlternateBackgroundColor(true);
552 if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Background") == "Inactive Background")
553 return getBackgroundColor(false);
554 QColor color = isActive ?
555 m_colorSettings.getColorValue("Alternate Background")
556 : m_colorSettings.getColorValue("Inactive Alternate Background");
557 if (!color.isValid())
558 color = p.color(QPalette::Active, QPalette::AlternateBase);
559 if (!color.isValid())
560 color = p.color(QPalette::Active, QPalette::Base);
561 return color;
562 }
563
getMarkedForegroundColor(bool isActive) const564 QColor KrColorCacheImpl::getMarkedForegroundColor(bool isActive) const
565 {
566 QString colorName = isActive ? "Marked Foreground" : "Inactive Marked Foreground";
567 if (m_colorSettings.getColorTextValue(colorName) == "transparent")
568 return QColor();
569 if (isActive && m_colorSettings.getColorTextValue(colorName).isEmpty())
570 return QGuiApplication::palette().color(QPalette::Active, QPalette::HighlightedText);
571 if (!isActive && m_colorSettings.getColorTextValue(colorName).isEmpty())
572 return getMarkedForegroundColor(true);
573 return m_colorSettings.getColorValue(colorName);
574 }
575
getMarkedBackgroundColor(bool isActive) const576 QColor KrColorCacheImpl::getMarkedBackgroundColor(bool isActive) const
577 {
578 if (isActive && m_colorSettings.getColorTextValue("Marked Background").isEmpty())
579 return QGuiApplication::palette().color(QPalette::Active, QPalette::Highlight);
580 if (isActive && m_colorSettings.getColorTextValue("Marked Background") == "Background")
581 return getBackgroundColor(true);
582 if (!isActive && m_colorSettings.getColorTextValue("Inactive Marked Background").isEmpty())
583 return getMarkedBackgroundColor(true);
584 if (!isActive && m_colorSettings.getColorTextValue("Inactive Marked Background") == "Inactive Background")
585 return getBackgroundColor(false);
586 return isActive ?
587 m_colorSettings.getColorValue("Marked Background")
588 : m_colorSettings.getColorValue("Inactive Marked Background");
589 }
590
getAlternateMarkedBackgroundColor(bool isActive) const591 QColor KrColorCacheImpl::getAlternateMarkedBackgroundColor(bool isActive) const
592 {
593 if (isActive && m_colorSettings.getColorTextValue("Alternate Marked Background") == "Alternate Background")
594 return getAlternateBackgroundColor(true);
595 if (isActive && m_colorSettings.getColorTextValue("Alternate Marked Background").isEmpty())
596 return getMarkedBackgroundColor(true);
597 if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background").isEmpty())
598 return getAlternateMarkedBackgroundColor(true);
599 if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "Inactive Alternate Background")
600 return getAlternateBackgroundColor(false);
601 if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "Inactive Marked Background")
602 return getMarkedBackgroundColor(false);
603 return isActive ?
604 m_colorSettings.getColorValue("Alternate Marked Background")
605 : m_colorSettings.getColorValue("Inactive Alternate Marked Background");
606 }
607
getCurrentForegroundColor(bool isActive) const608 QColor KrColorCacheImpl::getCurrentForegroundColor(bool isActive) const
609 {
610 QColor color = m_colorSettings.getColorValue("Current Foreground");
611 if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Current Foreground"));
612 return color;
613 }
614
getCurrentBackgroundColor(bool isActive) const615 QColor KrColorCacheImpl::getCurrentBackgroundColor(bool isActive) const
616 {
617 if (isActive && m_colorSettings.getColorTextValue("Current Background").isEmpty())
618 return QColor();
619 if (isActive && m_colorSettings.getColorTextValue("Current Background") == "Background")
620 return getBackgroundColor(true);
621 if (!isActive && m_colorSettings.getColorTextValue("Inactive Current Background").isEmpty())
622 return getCurrentBackgroundColor(true);
623 if (!isActive && m_colorSettings.getColorTextValue("Inactive Current Background") == "Inactive Background")
624 return getBackgroundColor(false);
625 return isActive ?
626 m_colorSettings.getColorValue("Current Background")
627 : m_colorSettings.getColorValue("Inactive Current Background");
628 }
629
getCurrentMarkedForegroundColor(bool isActive) const630 QColor KrColorCacheImpl::getCurrentMarkedForegroundColor(bool isActive) const
631 {
632 QString colorName = isActive ? "Marked Current Foreground" : "Inactive Marked Current Foreground";
633 if (isActive && m_colorSettings.getColorTextValue(colorName).isEmpty())
634 return QColor();
635 if (isActive && m_colorSettings.getColorTextValue(colorName) == "Marked Foreground")
636 return getMarkedForegroundColor(true);
637 if (!isActive && m_colorSettings.getColorTextValue(colorName).isEmpty())
638 return getCurrentMarkedForegroundColor(true);
639 if (!isActive && m_colorSettings.getColorTextValue(colorName) == "Inactive Marked Foreground")
640 return getMarkedForegroundColor(false);
641 return m_colorSettings.getColorValue(colorName);
642 }
643
dimColor(QColor color,bool) const644 QColor KrColorCacheImpl::dimColor(QColor color, bool /* isBackgroundColor */) const
645 {
646 int dimFactor = m_colorSettings.getNumValue("Dim Factor", 100);
647 QColor targetColor = m_colorSettings.getColorValue("Dim Target Color");
648 if (!targetColor.isValid())
649 targetColor = QColor(255, 255, 255);
650 bool dimBackground = m_colorSettings.getBoolValue("Dim Inactive Colors", false);
651 bool dim = dimFactor >= 0 && dimFactor < 100 && dimBackground;
652 if (dim)
653 color = KrColorCache::dimColor(color, dimFactor, targetColor);
654 return color;
655 }
656
657
658
659
660
661
662 KrColorCache * KrColorCache::m_instance = 0;
663
KrColorCache()664 KrColorCache::KrColorCache()
665 {
666 m_impl = new KrColorCacheImpl;
667 }
668
~KrColorCache()669 KrColorCache::~KrColorCache()
670 {
671 delete m_impl;
672 }
673
getColorCache()674 KrColorCache & KrColorCache::getColorCache()
675 {
676 if (!m_instance) {
677 m_instance = new KrColorCache;
678 m_instance->refreshColors();
679 }
680 return * m_instance;
681 }
682
getColors(KrColorGroup & result,const KrColorItemType & type) const683 void KrColorCache::getColors(KrColorGroup & result, const KrColorItemType & type) const
684 {
685 // for the cache lookup: calculate a unique key from the type
686 char hashKey[128];
687 switch (type.m_fileType) {
688 case KrColorItemType::Directory :
689 strcpy(hashKey, "Directory");
690 break;
691 case KrColorItemType::Executable :
692 strcpy(hashKey, "Executable");
693 break;
694 case KrColorItemType::InvalidSymlink :
695 strcpy(hashKey, "InvalidSymlink");
696 break;
697 case KrColorItemType::Symlink :
698 strcpy(hashKey, "Symlink");
699 break;
700 default:
701 strcpy(hashKey, "File");
702 }
703 if (type.m_activePanel)
704 strcat(hashKey, "-Active");
705 if (type.m_alternateBackgroundColor)
706 strcat(hashKey, "-Alternate");
707 if (type.m_currentItem)
708 strcat(hashKey, "-Current");
709 if (type.m_selectedItem)
710 strcat(hashKey, "-Selected");
711
712 // lookup in cache
713 if (!m_impl->m_cachedColors.contains(hashKey))
714 // not found: calculate color group and store it in cache
715 m_impl->m_cachedColors[hashKey] = m_impl->getColors(type);
716
717 // get color group from cache
718 const KrColorGroup & col = m_impl->m_cachedColors[hashKey];
719
720 // copy colors in question to result color group
721 result.setBackground(col.background());
722 result.setText(col.text());
723 result.setHighlightedText(col.highlightedText());
724 result.setHighlight(col.highlight());
725 }
726
getDimSettings(QColor & dimColor,int & dimFactor)727 bool KrColorCache::getDimSettings(QColor & dimColor, int & dimFactor)
728 {
729 if (m_impl->m_colorSettings.getBoolValue("Dim Inactive Colors", false)) {
730 dimFactor = m_impl->m_colorSettings.getNumValue("Dim Factor", 100);
731 dimColor = m_impl->m_colorSettings.getColorValue("Dim Target Color");
732 if (!dimColor.isValid())
733 dimColor.setRgb(255, 255, 255);
734 return dimFactor >= 0 && dimFactor < 100;
735 }
736 return false;
737 }
738
dimColor(const QColor & color,int dim,const QColor & targetColor)739 QColor KrColorCache::dimColor(const QColor & color, int dim, const QColor & targetColor)
740 {
741 return QColor((targetColor.red() * (100 - dim) + color.red() * dim) / 100,
742 (targetColor.green() * (100 - dim) + color.green() * dim) / 100,
743 (targetColor.blue() * (100 - dim) + color.blue() * dim) / 100);
744 }
745
refreshColors()746 void KrColorCache::refreshColors()
747 {
748 m_impl->m_cachedColors.clear();
749 m_impl->m_colorSettings = KrColorSettings();
750 QPixmapCache::clear(); // dimmed icons are cached
751 colorsRefreshed();
752 }
753
setColors(const KrColorSettings & colorSettings)754 void KrColorCache::setColors(const KrColorSettings & colorSettings)
755 {
756 m_impl->m_cachedColors.clear();
757 m_impl->m_colorSettings = colorSettings;
758 QPixmapCache::clear(); // dimmed icons are cached
759 colorsRefreshed();
760 }
761
762