Changeset View
Changeset View
Standalone View
Standalone View
src/ColorScheme.cpp
Show All 15 Lines | 1 | /* | |||
---|---|---|---|---|---|
16 | You should have received a copy of the GNU General Public License | 16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | 17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
19 | 02110-1301 USA. | 19 | 02110-1301 USA. | ||
20 | */ | 20 | */ | ||
21 | 21 | | |||
22 | // Own | 22 | // Own | ||
23 | #include "ColorScheme.h" | 23 | #include "ColorScheme.h" | ||
24 | #include "hsluv.h" | ||||
24 | 25 | | |||
25 | // Qt | 26 | // Qt | ||
26 | #include <QPainter> | 27 | #include <QPainter> | ||
28 | #include <QVariant> | ||||
27 | 29 | | |||
28 | // KDE | 30 | // KDE | ||
29 | #include <KConfig> | 31 | #include <KConfig> | ||
30 | #include <KLocalizedString> | 32 | #include <KLocalizedString> | ||
31 | #include <KConfigGroup> | 33 | #include <KConfigGroup> | ||
32 | 34 | | |||
33 | // STL | 35 | // STL | ||
34 | #include <random> | 36 | #include <random> | ||
35 | 37 | | |||
36 | #include "konsoledebug.h" | 38 | #include "konsoledebug.h" | ||
37 | 39 | | |||
38 | namespace { | 40 | namespace { | ||
39 | const int FGCOLOR_INDEX = 0; | 41 | static const int FGCOLOR_INDEX = 0; | ||
hindenburg: nitpick - you don't need to fix these now - "static definition in anonymous namespace; static… | |||||
40 | const int BGCOLOR_INDEX = 1; | 42 | static const int BGCOLOR_INDEX = 1; | ||
43 | | ||||
44 | static const char RandomHueRangeKey[] = "RandomHueRange"; | ||||
45 | static const char RandomSaturationRangeKey[] = "RandomSaturationRange"; | ||||
46 | static const char RandomLightnessRangeKey[] = "RandomLightnessRange"; | ||||
47 | static const char EnableColorRandomizationKey[] = "ColorRandomization"; | ||||
48 | | ||||
49 | static const double MaxHue = 360.0; | ||||
50 | static const double MaxSaturation = 100.0; | ||||
51 | static const double MaxLightness = 100.0; | ||||
41 | } | 52 | } | ||
42 | 53 | | |||
43 | using namespace Konsole; | 54 | using namespace Konsole; | ||
44 | 55 | | |||
45 | // The following are almost IBM standard color codes, with some slight | 56 | // The following are almost IBM standard color codes, with some slight | ||
46 | // gamma correction for the dim colors to compensate for bright X screens. | 57 | // gamma correction for the dim colors to compensate for bright X screens. | ||
47 | // It contains the 8 ansiterm/xterm colors in 2 intensities. | 58 | // It contains the 8 ansiterm/xterm colors in 2 intensities. | ||
48 | const ColorEntry ColorScheme::defaultTable[TABLE_COLORS] = { | 59 | const ColorEntry ColorScheme::defaultTable[TABLE_COLORS] = { | ||
▲ Show 20 Lines • Show All 139 Lines • ▼ Show 20 Line(s) | 198 | if (other._table != nullptr) { | |||
188 | for (int i = 0; i < TABLE_COLORS; i++) { | 199 | for (int i = 0; i < TABLE_COLORS; i++) { | ||
189 | setColorTableEntry(i, other._table[i]); | 200 | setColorTableEntry(i, other._table[i]); | ||
190 | } | 201 | } | ||
191 | } | 202 | } | ||
192 | 203 | | |||
193 | if (other._randomTable != nullptr) { | 204 | if (other._randomTable != nullptr) { | ||
194 | for (int i = 0; i < TABLE_COLORS; i++) { | 205 | for (int i = 0; i < TABLE_COLORS; i++) { | ||
195 | const RandomizationRange &range = other._randomTable[i]; | 206 | const RandomizationRange &range = other._randomTable[i]; | ||
196 | setRandomizationRange(i, range.hue, range.saturation, range.value); | 207 | setRandomizationRange(i, range.hue, range.saturation, range.lightness); | ||
197 | } | 208 | } | ||
198 | } | 209 | } | ||
199 | } | 210 | } | ||
200 | 211 | | |||
201 | ColorScheme::~ColorScheme() | 212 | ColorScheme::~ColorScheme() | ||
202 | { | 213 | { | ||
203 | delete[] _table; | 214 | delete[] _table; | ||
204 | delete[] _randomTable; | 215 | delete[] _randomTable; | ||
Show All 40 Lines | |||||
245 | } | 256 | } | ||
246 | 257 | | |||
247 | ColorEntry ColorScheme::colorEntry(int index, uint randomSeed) const | 258 | ColorEntry ColorScheme::colorEntry(int index, uint randomSeed) const | ||
248 | { | 259 | { | ||
249 | Q_ASSERT(index >= 0 && index < TABLE_COLORS); | 260 | Q_ASSERT(index >= 0 && index < TABLE_COLORS); | ||
250 | 261 | | |||
251 | ColorEntry entry = colorTable()[index]; | 262 | ColorEntry entry = colorTable()[index]; | ||
252 | 263 | | |||
253 | if (randomSeed == 0 || _randomTable == nullptr || _randomTable[index].isNull()) { | 264 | if (!_colorRandomization || randomSeed == 0 || _randomTable == nullptr | ||
265 | || _randomTable[index].isNull()) { | ||||
254 | return entry; | 266 | return entry; | ||
255 | } | 267 | } | ||
256 | 268 | | |||
269 | double baseHue, baseSaturation, baseLightness; | ||||
270 | rgb2hsluv(entry.redF(), entry.greenF(), entry.blueF(), | ||||
271 | &baseHue, &baseSaturation, &baseLightness); | ||||
272 | | ||||
257 | const RandomizationRange &range = _randomTable[index]; | 273 | const RandomizationRange &range = _randomTable[index]; | ||
258 | 274 | | |||
259 | // 32-bit Mersenne Twister | 275 | // 32-bit Mersenne Twister | ||
260 | // Can't use default_random_engine, because in GCC this maps to | 276 | // Can't use default_random_engine, because in GCC this maps to | ||
261 | // minstd_rand0 which always gives us 0 on the first number. | 277 | // minstd_rand0 which always gives us 0 on the first number. | ||
262 | std::mt19937 randomEngine(randomSeed); | 278 | std::mt19937 randomEngine(randomSeed); | ||
263 | 279 | | |||
264 | int hueDifference = 0; | 280 | // Use hues located around base color's hue. | ||
265 | if (range.hue != 0u) { | 281 | // H=0 [|= =] H=128 [ =|= ] H=360 [= =|] | ||
266 | std::uniform_int_distribution<int> dist(0, range.hue); | 282 | const double minHue = baseHue - range.hue / 2.0; | ||
267 | hueDifference = dist(randomEngine); | 283 | const double maxHue = baseHue + range.hue / 2.0; | ||
268 | } | 284 | std::uniform_real_distribution<> hueDistribution(minHue, maxHue); | ||
269 | 285 | // Hue value is an angle, it wraps after 360°. Adding MAX_HUE | |||
270 | int saturationDifference = 0; | 286 | // guarantees that the sum is not negative. | ||
271 | if (range.saturation != 0u) { | 287 | const double hue = fmod(MaxHue + hueDistribution(randomEngine), MaxHue); | ||
272 | std::uniform_int_distribution<int> dist(0, range.saturation); | 288 | | ||
273 | saturationDifference = dist(randomEngine) - range.saturation / 2; | 289 | // Saturation is always decreased. With more saturation more | ||
274 | } | 290 | // information about hue is preserved in RGB color space | ||
275 | 291 | // (consider red with S=100 and "red" with S=0 which is gray). | |||
276 | int valueDifference = 0; | 292 | // Additionally, I think it can be easier to imagine more | ||
277 | if (range.value != 0u) { | 293 | // toned color than more vivid one. | ||
278 | std::uniform_int_distribution<int> dist(0, range.value); | 294 | // S=0 [|== ] S=50 [ ==| ] S=100 [ ==|] | ||
279 | valueDifference = dist(randomEngine) - range.value / 2; | 295 | const double minSaturation = qMax(baseSaturation - range.saturation, 0.0); | ||
296 | const double maxSaturation = qMax(range.saturation, baseSaturation); | ||||
297 | // Use rising linear distribution as colors with lower | ||||
298 | // saturation are less distinguishable. | ||||
299 | std::piecewise_linear_distribution<> saturationDistribution({minSaturation, maxSaturation}, | ||||
300 | [](double v) { return v; }); | ||||
301 | const double saturation = qFuzzyCompare(minSaturation, maxSaturation) | ||||
302 | ? baseSaturation | ||||
303 | : saturationDistribution(randomEngine); | ||||
304 | | ||||
305 | // Lightness range has base value at its center. The base | ||||
306 | // value is clamped to prevent the range from shrinking. | ||||
307 | // L=0 [=|= ] L=50 [ =|= ] L=100 [ =|=] | ||||
308 | baseLightness = qBound(range.lightness / 2.0, baseLightness , MaxLightness - range.lightness); | ||||
309 | const double minLightness = qMax(baseLightness - range.lightness / 2.0, 0.0); | ||||
310 | const double maxLightness = qMin(baseLightness + range.lightness / 2.0, MaxLightness); | ||||
311 | // Use triangular distribution with peak at L=50.0. | ||||
312 | // Dark and very light colors are less distinguishable. | ||||
313 | std::initializer_list<double> lightnessIntervals; | ||||
314 | if (minLightness < 50.0 && 50.0 < maxLightness) { | ||||
315 | lightnessIntervals = {minLightness, 50.0, maxLightness}; | ||||
316 | } else { | ||||
317 | lightnessIntervals = {minLightness, maxLightness}; | ||||
280 | } | 318 | } | ||
319 | static const auto lightnessWeightsFunc = [](double v) { return 50.0 - qAbs(v - 50.0); }; | ||||
320 | std::piecewise_linear_distribution<> lightnessDistribution(lightnessIntervals, | ||||
321 | lightnessWeightsFunc); | ||||
322 | const double lightness = qFuzzyCompare(minLightness, maxLightness) | ||||
323 | ? baseLightness | ||||
324 | : lightnessDistribution(randomEngine); | ||||
281 | 325 | | |||
282 | QColor &color = entry; | 326 | double red, green, blue; | ||
283 | 327 | hsluv2rgb(hue, saturation, lightness, &red, &green, &blue); | |||
284 | int newHue = qAbs((color.hue() + hueDifference) % MAX_HUE); | | |||
285 | int newValue = qMin(qAbs(color.value() + valueDifference), 255); | | |||
286 | int newSaturation = qMin(qAbs(color.saturation() + saturationDifference), 255); | | |||
287 | | ||||
288 | color.setHsv(newHue, newSaturation, newValue); | | |||
289 | 328 | | |||
290 | return entry; | 329 | return QColor(qRound(red * 255), qRound(green * 255), qRound(blue * 255)); | ||
291 | } | 330 | } | ||
292 | 331 | | |||
293 | void ColorScheme::getColorTable(ColorEntry *table, uint randomSeed) const | 332 | void ColorScheme::getColorTable(ColorEntry *table, uint randomSeed) const | ||
294 | { | 333 | { | ||
295 | for (int i = 0; i < TABLE_COLORS; i++) { | 334 | for (int i = 0; i < TABLE_COLORS; i++) { | ||
296 | table[i] = colorEntry(i, randomSeed); | 335 | table[i] = colorEntry(i, randomSeed); | ||
297 | } | 336 | } | ||
298 | } | 337 | } | ||
299 | 338 | | |||
300 | bool ColorScheme::randomizedBackgroundColor() const | 339 | bool ColorScheme::isColorRandomizationEnabled() const | ||
301 | { | 340 | { | ||
302 | return _randomTable == nullptr ? false : !_randomTable[BGCOLOR_INDEX].isNull(); | 341 | return (_colorRandomization && _randomTable != nullptr); | ||
303 | } | 342 | } | ||
304 | 343 | | |||
305 | void ColorScheme::setRandomizedBackgroundColor(bool randomize) | 344 | void ColorScheme::setColorRandomization(bool randomize) | ||
306 | { | 345 | { | ||
307 | // the hue of the background color is allowed to be randomly | 346 | _colorRandomization = randomize; | ||
308 | // adjusted as much as possible. | | |||
309 | // | | |||
310 | // the value and saturation are left alone to maintain read-ability | | |||
311 | // except for dark background schemes which allow a change in the | | |||
312 | // colour value (one less than the dark background threshold) | | |||
313 | if (randomize) { | 347 | if (randomize) { | ||
314 | quint8 maxValue = 0; | 348 | bool hasAnyRandomizationEntries = false; | ||
315 | 349 | if (_randomTable != nullptr) { | |||
316 | if (hasDarkBackground()) { | 350 | for (int i = 0; !hasAnyRandomizationEntries && i < TABLE_COLORS; i++) { | ||
317 | maxValue = 126; | 351 | hasAnyRandomizationEntries = !_randomTable[i].isNull(); | ||
352 | } | ||||
353 | } | ||||
354 | // Set default randomization settings | ||||
355 | if (!hasAnyRandomizationEntries) { | ||||
356 | static const int ColorIndexesForRandomization[] = { | ||||
357 | ColorFgIndex, ColorBgIndex, | ||||
358 | ColorFgIntenseIndex, ColorBgIntenseIndex, | ||||
359 | ColorFgFaintIndex, ColorBgFaintIndex, | ||||
360 | }; | ||||
361 | for (int index: ColorIndexesForRandomization) { | ||||
362 | setRandomizationRange(index, MaxHue, MaxSaturation, 0.0); | ||||
363 | } | ||||
318 | } | 364 | } | ||
319 | | ||||
320 | setRandomizationRange(BGCOLOR_INDEX, MAX_HUE, 255, maxValue); | | |||
321 | } else if (_randomTable != nullptr) { | | |||
322 | setRandomizationRange(BGCOLOR_INDEX, 0, 0, 0); | | |||
323 | } | 365 | } | ||
324 | } | 366 | } | ||
325 | 367 | | |||
326 | void ColorScheme::setRandomizationRange(int index, quint16 hue, quint8 saturation, quint8 value) | 368 | void ColorScheme::setRandomizationRange(int index, double hue, double saturation, double lightness) | ||
327 | { | 369 | { | ||
328 | Q_ASSERT(hue <= MAX_HUE); | 370 | Q_ASSERT(hue <= MaxHue); | ||
329 | Q_ASSERT(index >= 0 && index < TABLE_COLORS); | 371 | Q_ASSERT(index >= 0 && index < TABLE_COLORS); | ||
330 | 372 | | |||
331 | if (_randomTable == nullptr) { | 373 | if (_randomTable == nullptr) { | ||
332 | _randomTable = new RandomizationRange[TABLE_COLORS]; | 374 | _randomTable = new RandomizationRange[TABLE_COLORS]; | ||
333 | } | 375 | } | ||
334 | 376 | | |||
335 | _randomTable[index].hue = hue; | 377 | _randomTable[index].hue = hue; | ||
336 | _randomTable[index].value = value; | | |||
337 | _randomTable[index].saturation = saturation; | 378 | _randomTable[index].saturation = saturation; | ||
379 | _randomTable[index].lightness = lightness; | ||||
338 | } | 380 | } | ||
339 | 381 | | |||
340 | const ColorEntry *ColorScheme::colorTable() const | 382 | const ColorEntry *ColorScheme::colorTable() const | ||
341 | { | 383 | { | ||
342 | if (_table != nullptr) { | 384 | if (_table != nullptr) { | ||
343 | return _table; | 385 | return _table; | ||
344 | } | 386 | } | ||
345 | return defaultTable; | 387 | return defaultTable; | ||
346 | } | 388 | } | ||
347 | 389 | | |||
348 | QColor ColorScheme::foregroundColor() const | 390 | QColor ColorScheme::foregroundColor() const | ||
349 | { | 391 | { | ||
350 | return colorTable()[FGCOLOR_INDEX]; | 392 | return colorTable()[FGCOLOR_INDEX]; | ||
351 | } | 393 | } | ||
352 | 394 | | |||
353 | QColor ColorScheme::backgroundColor() const | 395 | QColor ColorScheme::backgroundColor() const | ||
354 | { | 396 | { | ||
355 | return colorTable()[BGCOLOR_INDEX]; | 397 | return colorTable()[BGCOLOR_INDEX]; | ||
356 | } | 398 | } | ||
357 | 399 | | |||
358 | bool ColorScheme::hasDarkBackground() const | 400 | bool ColorScheme::hasDarkBackground() const | ||
359 | { | 401 | { | ||
360 | // value can range from 0 - 255, with larger values indicating higher brightness. | 402 | double h, s, l; | ||
361 | // so 127 is in the middle, anything less is deemed 'dark' | 403 | const double r = backgroundColor().redF(); | ||
362 | return backgroundColor().value() < 127; | 404 | const double g = backgroundColor().greenF(); | ||
405 | const double b = backgroundColor().blueF(); | ||||
406 | rgb2hsluv(r, g, b, &h, &s, &l); | ||||
407 | return l < 0.5; | ||||
363 | } | 408 | } | ||
364 | 409 | | |||
365 | void ColorScheme::setOpacity(qreal opacity) | 410 | void ColorScheme::setOpacity(qreal opacity) | ||
366 | { | 411 | { | ||
367 | if (opacity < 0.0 || opacity > 1.0) { | 412 | if (opacity < 0.0 || opacity > 1.0) { | ||
368 | qCDebug(KonsoleDebug)<<"ColorScheme"<<name()<<"has an invalid opacity"<<opacity<<"using 1"; | 413 | qCDebug(KonsoleDebug)<<"ColorScheme"<<name()<<"has an invalid opacity"<<opacity<<"using 1"; | ||
369 | opacity = 1.0; | 414 | opacity = 1.0; | ||
370 | } | 415 | } | ||
Show All 20 Lines | 435 | { | |||
391 | KConfigGroup configGroup = config.group("General"); | 436 | KConfigGroup configGroup = config.group("General"); | ||
392 | 437 | | |||
393 | const QString schemeDescription = configGroup.readEntry("Description", i18nc("@item", "Un-named Color Scheme")); | 438 | const QString schemeDescription = configGroup.readEntry("Description", i18nc("@item", "Un-named Color Scheme")); | ||
394 | 439 | | |||
395 | _description = i18n(schemeDescription.toUtf8().constData()); | 440 | _description = i18n(schemeDescription.toUtf8().constData()); | ||
396 | setOpacity(configGroup.readEntry("Opacity", 1.0)); | 441 | setOpacity(configGroup.readEntry("Opacity", 1.0)); | ||
397 | _blur = configGroup.readEntry("Blur", false); | 442 | _blur = configGroup.readEntry("Blur", false); | ||
398 | setWallpaper(configGroup.readEntry("Wallpaper", QString())); | 443 | setWallpaper(configGroup.readEntry("Wallpaper", QString())); | ||
444 | _colorRandomization = configGroup.readEntry(EnableColorRandomizationKey, false); | ||||
399 | 445 | | |||
400 | for (int i = 0; i < TABLE_COLORS; i++) { | 446 | for (int i = 0; i < TABLE_COLORS; i++) { | ||
401 | readColorEntry(config, i); | 447 | readColorEntry(config, i); | ||
402 | } | 448 | } | ||
403 | } | 449 | } | ||
404 | 450 | | |||
405 | void ColorScheme::readColorEntry(const KConfig &config, int index) | 451 | void ColorScheme::readColorEntry(const KConfig &config, int index) | ||
406 | { | 452 | { | ||
407 | KConfigGroup configGroup = config.group(colorNameForIndex(index)); | 453 | KConfigGroup configGroup = config.group(colorNameForIndex(index)); | ||
408 | 454 | | |||
409 | if (!configGroup.hasKey("Color") && _table != nullptr) { | 455 | if (!configGroup.hasKey("Color") && _table != nullptr) { | ||
410 | setColorTableEntry(index, _table[index%BASE_COLORS]); | 456 | setColorTableEntry(index, _table[index%BASE_COLORS]); | ||
411 | return; | 457 | return; | ||
412 | } | 458 | } | ||
413 | 459 | | |||
414 | ColorEntry entry; | 460 | ColorEntry entry; | ||
415 | 461 | | |||
416 | entry = configGroup.readEntry("Color", QColor()); | 462 | entry = configGroup.readEntry("Color", QColor()); | ||
417 | setColorTableEntry(index, entry); | 463 | setColorTableEntry(index, entry); | ||
418 | 464 | | |||
419 | quint16 hue = static_cast<quint16>(configGroup.readEntry("MaxRandomHue", 0)); | 465 | const auto readAndCheckConfigEntry = [&](const char *key, double min, double max) -> double { | ||
420 | const quint8 value = static_cast<quint8>(configGroup.readEntry("MaxRandomValue", 0)); | 466 | const double value = configGroup.readEntry(key, min); | ||
421 | const quint8 saturation = static_cast<quint8>(configGroup.readEntry("MaxRandomSaturation", 0)); | 467 | if (min > value || value > max) { | ||
422 | 468 | qCDebug(KonsoleDebug) << QStringLiteral( | |||
423 | if (hue > MAX_HUE) { | 469 | "Color scheme \"%1\": color index 2 has an invalid value: %3 = %4. " | ||
424 | qCDebug(KonsoleDebug)<<"ColorScheme"<<name()<<"has an invalid MaxRandomHue"<<hue<<"for index"<< index<<", using"<<MAX_HUE; | 470 | "Allowed value range: %5 - %6. Using %7.") | ||
425 | hue = MAX_HUE; | 471 | .arg(name()).arg(index).arg(QLatin1String(key)).arg(value, 0, 'g', 1) | ||
472 | .arg(min, 0, 'g', 1).arg(max, 0, 'g', 1).arg(min, 0, 'g', 1); | ||||
473 | return min; | ||||
426 | } | 474 | } | ||
475 | return value; | ||||
476 | }; | ||||
427 | 477 | | |||
428 | if (hue != 0 || value != 0 || saturation != 0) { | 478 | double hue = readAndCheckConfigEntry(RandomHueRangeKey, 0.0, MaxHue); | ||
429 | setRandomizationRange(index, hue, saturation, value); | 479 | double saturation = readAndCheckConfigEntry(RandomSaturationRangeKey, 0.0, MaxSaturation); | ||
480 | double lightness = readAndCheckConfigEntry(RandomLightnessRangeKey, 0.0, MaxLightness); | ||||
481 | | ||||
482 | if (!qFuzzyIsNull(hue) || !qFuzzyIsNull(saturation) || !qFuzzyIsNull(lightness)) { | ||||
483 | setRandomizationRange(index, hue, saturation, lightness); | ||||
430 | } | 484 | } | ||
431 | } | 485 | } | ||
432 | 486 | | |||
433 | void ColorScheme::write(KConfig &config) const | 487 | void ColorScheme::write(KConfig &config) const | ||
434 | { | 488 | { | ||
435 | KConfigGroup configGroup = config.group("General"); | 489 | KConfigGroup configGroup = config.group("General"); | ||
436 | 490 | | |||
437 | configGroup.writeEntry("Description", _description); | 491 | configGroup.writeEntry("Description", _description); | ||
438 | configGroup.writeEntry("Opacity", _opacity); | 492 | configGroup.writeEntry("Opacity", _opacity); | ||
439 | configGroup.writeEntry("Blur", _blur); | 493 | configGroup.writeEntry("Blur", _blur); | ||
440 | configGroup.writeEntry("Wallpaper", _wallpaper->path()); | 494 | configGroup.writeEntry("Wallpaper", _wallpaper->path()); | ||
495 | configGroup.writeEntry(EnableColorRandomizationKey, _colorRandomization); | ||||
441 | 496 | | |||
442 | for (int i = 0; i < TABLE_COLORS; i++) { | 497 | for (int i = 0; i < TABLE_COLORS; i++) { | ||
443 | writeColorEntry(config, i); | 498 | writeColorEntry(config, i); | ||
444 | } | 499 | } | ||
445 | } | 500 | } | ||
446 | 501 | | |||
447 | void ColorScheme::writeColorEntry(KConfig &config, int index) const | 502 | void ColorScheme::writeColorEntry(KConfig &config, int index) const | ||
448 | { | 503 | { | ||
449 | KConfigGroup configGroup = config.group(colorNameForIndex(index)); | 504 | KConfigGroup configGroup = config.group(colorNameForIndex(index)); | ||
450 | 505 | | |||
451 | const ColorEntry &entry = colorTable()[index]; | 506 | const ColorEntry &entry = colorTable()[index]; | ||
452 | 507 | | |||
453 | configGroup.writeEntry("Color", entry); | 508 | configGroup.writeEntry("Color", entry); | ||
454 | 509 | | |||
455 | // Remove unused keys | 510 | // Remove unused keys | ||
456 | if (configGroup.hasKey("Transparent")) { | 511 | static const char *obsoleteKeys[] = { | ||
457 | configGroup.deleteEntry("Transparent"); | 512 | "Transparent", | ||
458 | } | 513 | "Transparency", | ||
459 | if (configGroup.hasKey("Transparency")) { | 514 | "Bold", | ||
460 | configGroup.deleteEntry("Transparency"); | 515 | // Uncomment when people stop using Konsole from 2019: | ||
516 | // "MaxRandomHue", | ||||
517 | // "MaxRandomValue", | ||||
518 | // "MaxRandomSaturation" | ||||
519 | }; | ||||
520 | for (const auto key: obsoleteKeys) { | ||||
521 | if (configGroup.hasKey(key)) { | ||||
522 | configGroup.deleteEntry(key); | ||||
461 | } | 523 | } | ||
462 | if (configGroup.hasKey("Bold")) { | | |||
463 | configGroup.deleteEntry("Bold"); | | |||
464 | } | 524 | } | ||
465 | 525 | | |||
466 | RandomizationRange random = _randomTable != nullptr ? _randomTable[index] : RandomizationRange(); | 526 | RandomizationRange random = _randomTable != nullptr ? _randomTable[index] : RandomizationRange(); | ||
467 | 527 | | |||
468 | // record randomization if this color has randomization or | 528 | const auto checkAndMaybeSaveValue = [&](const char *key, double value) { | ||
469 | // if one of the keys already exists | 529 | const bool valueIsNull = qFuzzyCompare(value, 0.0); | ||
470 | if (!random.isNull() || configGroup.hasKey("MaxRandomHue")) { | 530 | const bool keyExists = configGroup.hasKey(key); | ||
471 | configGroup.writeEntry("MaxRandomHue", static_cast<int>(random.hue)); | 531 | const bool keyExistsAndHasDifferentValue = !qFuzzyCompare(configGroup.readEntry(key, value), | ||
472 | configGroup.writeEntry("MaxRandomValue", static_cast<int>(random.value)); | 532 | value); | ||
473 | configGroup.writeEntry("MaxRandomSaturation", static_cast<int>(random.saturation)); | 533 | if ((!valueIsNull && !keyExists) || keyExistsAndHasDifferentValue) { | ||
534 | configGroup.writeEntry(key, value); | ||||
474 | } | 535 | } | ||
536 | }; | ||||
537 | | ||||
538 | checkAndMaybeSaveValue(RandomHueRangeKey, random.hue); | ||||
539 | checkAndMaybeSaveValue(RandomSaturationRangeKey, random.saturation); | ||||
540 | checkAndMaybeSaveValue(RandomLightnessRangeKey, random.lightness); | ||||
475 | } | 541 | } | ||
476 | 542 | | |||
477 | void ColorScheme::setWallpaper(const QString &path) | 543 | void ColorScheme::setWallpaper(const QString &path) | ||
478 | { | 544 | { | ||
479 | _wallpaper = new ColorSchemeWallpaper(path); | 545 | _wallpaper = new ColorSchemeWallpaper(path); | ||
480 | } | 546 | } | ||
481 | 547 | | |||
482 | ColorSchemeWallpaper::Ptr ColorScheme::wallpaper() const | 548 | ColorSchemeWallpaper::Ptr ColorScheme::wallpaper() const | ||
▲ Show 20 Lines • Show All 60 Lines • Show Last 20 Lines |
nitpick - you don't need to fix these now - "static definition in anonymous namespace; static is redundant here"