26
26
#include <QtGui/QBrush>
27
#include <QtCore/QFile>
28
#include <QtCore/QFileInfo>
29
27
#include <QtGui/QPainter>
32
30
#include <KColorScheme>
32
#include <KLocalizedString>
36
33
#include <KConfigGroup>
37
#include <KStandardDirs>
36
const int FGCOLOR_INDEX = 0;
37
const int BGCOLOR_INDEX = 1;
39
40
using namespace Konsole;
42
// The following are almost IBM standard color codes, with some slight
43
// gamma correction for the dim colors to compensate for bright X screens.
44
// It contains the 8 ansiterm/xterm colors in 2 intensities.
41
45
const ColorEntry ColorScheme::defaultTable[TABLE_COLORS] =
42
// The following are almost IBM standard color codes, with some slight
43
// gamma correction for the dim colors to compensate for bright X screens.
44
// It contains the 8 ansiterm/xterm colors in 2 intensities.
46
ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
47
QColor(0xFF,0xFF,0xFF), 1), // Dfore, Dback
48
ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
49
QColor(0xB2,0x18,0x18), 0), // Black, Red
50
ColorEntry( QColor(0x18,0xB2,0x18), 0), ColorEntry(
51
QColor(0xB2,0x68,0x18), 0), // Green, Yellow
52
ColorEntry( QColor(0x18,0x18,0xB2), 0), ColorEntry(
53
QColor(0xB2,0x18,0xB2), 0), // Blue, Magenta
54
ColorEntry( QColor(0x18,0xB2,0xB2), 0), ColorEntry(
55
QColor(0xB2,0xB2,0xB2), 0), // Cyan, White
57
ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
58
QColor(0xFF,0xFF,0xFF), 1),
59
ColorEntry( QColor(0x68,0x68,0x68), 0), ColorEntry(
60
QColor(0xFF,0x54,0x54), 0),
61
ColorEntry( QColor(0x54,0xFF,0x54), 0), ColorEntry(
62
QColor(0xFF,0xFF,0x54), 0),
63
ColorEntry( QColor(0x54,0x54,0xFF), 0), ColorEntry(
64
QColor(0xFF,0x54,0xFF), 0),
65
ColorEntry( QColor(0x54,0xFF,0xFF), 0), ColorEntry(
66
QColor(0xFF,0xFF,0xFF), 0)
47
ColorEntry(QColor(0x00, 0x00, 0x00)), // Dfore
48
ColorEntry(QColor(0xFF, 0xFF, 0xFF)), // Dback
49
ColorEntry(QColor(0x00, 0x00, 0x00)), // Black
50
ColorEntry(QColor(0xB2, 0x18, 0x18)), // Red
51
ColorEntry(QColor(0x18, 0xB2, 0x18)), // Green
52
ColorEntry(QColor(0xB2, 0x68, 0x18)), // Yellow
53
ColorEntry(QColor(0x18, 0x18, 0xB2)), // Blue
54
ColorEntry(QColor(0xB2, 0x18, 0xB2)), // Magenta
55
ColorEntry(QColor(0x18, 0xB2, 0xB2)), // Cyan
56
ColorEntry(QColor(0xB2, 0xB2, 0xB2)), // White
58
ColorEntry(QColor(0x00, 0x00, 0x00)),
59
ColorEntry(QColor(0xFF, 0xFF, 0xFF)),
60
ColorEntry(QColor(0x68, 0x68, 0x68)),
61
ColorEntry(QColor(0xFF, 0x54, 0x54)),
62
ColorEntry(QColor(0x54, 0xFF, 0x54)),
63
ColorEntry(QColor(0xFF, 0xFF, 0x54)),
64
ColorEntry(QColor(0x54, 0x54, 0xFF)),
65
ColorEntry(QColor(0xFF, 0x54, 0xFF)),
66
ColorEntry(QColor(0x54, 0xFF, 0xFF)),
67
ColorEntry(QColor(0xFF, 0xFF, 0xFF))
69
const char* const ColorScheme::colorNames[TABLE_COLORS] =
70
const char* const ColorScheme::colorNames[TABLE_COLORS] = {
92
const char* const ColorScheme::translatedColorNames[TABLE_COLORS] =
92
const char* const ColorScheme::translatedColorNames[TABLE_COLORS] = {
94
93
I18N_NOOP2("@item:intable palette", "Foreground"),
95
94
I18N_NOOP2("@item:intable palette", "Background"),
96
95
I18N_NOOP2("@item:intable palette", "Color 1"),
151
161
delete[] _randomTable;
154
void ColorScheme::setDescription(const QString& description) { _description = description; }
155
QString ColorScheme::description() const { return _description; }
164
void ColorScheme::setDescription(const QString& aDescription)
166
_description = aDescription;
168
QString ColorScheme::description() const
157
void ColorScheme::setName(const QString& name) { _name = name; }
158
QString ColorScheme::name() const { return _name; }
173
void ColorScheme::setName(const QString& aName)
177
QString ColorScheme::name() const
160
182
void ColorScheme::setColorTableEntry(int index , const ColorEntry& entry)
162
Q_ASSERT( index >= 0 && index < TABLE_COLORS );
184
Q_ASSERT(index >= 0 && index < TABLE_COLORS);
166
187
_table = new ColorEntry[TABLE_COLORS];
168
for (int i=0;i<TABLE_COLORS;i++)
189
for (int i = 0; i < TABLE_COLORS; i++)
169
190
_table[i] = defaultTable[i];
172
_table[index] = entry;
193
_table[index] = entry;
174
195
ColorEntry ColorScheme::colorEntry(int index , uint randomSeed) const
176
Q_ASSERT( index >= 0 && index < TABLE_COLORS );
197
Q_ASSERT(index >= 0 && index < TABLE_COLORS);
178
if ( randomSeed != 0 )
179
200
qsrand(randomSeed);
181
202
ColorEntry entry = colorTable()[index];
183
if ( randomSeed != 0 &&
185
!_randomTable[index].isNull() )
204
if (randomSeed != 0 &&
206
!_randomTable[index].isNull()) {
187
207
const RandomizationRange& range = _randomTable[index];
190
int hueDifference = range.hue ? (qrand() % range.hue) - range.hue/2 : 0;
191
int saturationDifference = range.saturation ? (qrand() % range.saturation) - range.saturation/2 : 0;
192
int valueDifference = range.value ? (qrand() % range.value) - range.value/2 : 0;
209
int hueDifference = range.hue ? (qrand() % range.hue) - range.hue / 2 : 0;
210
int saturationDifference = range.saturation ? (qrand() % range.saturation) - range.saturation / 2 : 0;
211
int valueDifference = range.value ? (qrand() % range.value) - range.value / 2 : 0;
194
213
QColor& color = entry.color;
196
int newHue = qAbs( (color.hue() + hueDifference) % MAX_HUE );
197
int newValue = qMin( qAbs(color.value() + valueDifference) , 255 );
198
int newSaturation = qMin( qAbs(color.saturation() + saturationDifference) , 255 );
215
int newHue = qAbs((color.hue() + hueDifference) % MAX_HUE);
216
int newValue = qMin(qAbs(color.value() + valueDifference) , 255);
217
int newSaturation = qMin(qAbs(color.saturation() + saturationDifference) , 255);
200
color.setHsv(newHue,newSaturation,newValue);
219
color.setHsv(newHue, newSaturation, newValue);
205
224
void ColorScheme::getColorTable(ColorEntry* table , uint randomSeed) const
207
for ( int i = 0 ; i < TABLE_COLORS ; i++ )
208
table[i] = colorEntry(i,randomSeed);
226
for (int i = 0 ; i < TABLE_COLORS ; i++)
227
table[i] = colorEntry(i, randomSeed);
210
229
bool ColorScheme::randomizedBackgroundColor() const
212
return _randomTable == 0 ? false : !_randomTable[1].isNull();
231
return _randomTable == 0 ? false : !_randomTable[BGCOLOR_INDEX].isNull();
214
233
void ColorScheme::setRandomizedBackgroundColor(bool randomize)
263
279
// so 127 is in the middle, anything less is deemed 'dark'
264
280
return backgroundColor().value() < 127;
266
void ColorScheme::setOpacity(qreal opacity) { _opacity = opacity; }
267
qreal ColorScheme::opacity() const { return _opacity; }
282
void ColorScheme::setOpacity(qreal aOpacity)
286
qreal ColorScheme::opacity() const
269
void ColorScheme::read(KConfig& config)
291
void ColorScheme::read(const KConfig& config)
271
293
KConfigGroup configGroup = config.group("General");
273
QString description = configGroup.readEntry("Description", I18N_NOOP("Un-named Color Scheme"));
295
const QString schemeDescription = configGroup.readEntry("Description", I18N_NOOP("Un-named Color Scheme"));
275
_description = i18n(description.toUtf8());
276
_opacity = configGroup.readEntry("Opacity",qreal(1.0));
297
_description = i18n(schemeDescription.toUtf8());
298
_opacity = configGroup.readEntry("Opacity", qreal(1.0));
277
299
setWallpaper(configGroup.readEntry("Wallpaper", QString()));
279
for (int i=0 ; i < TABLE_COLORS ; i++)
281
readColorEntry(config,i);
284
void ColorScheme::write(KConfig& config) const
286
KConfigGroup configGroup = config.group("General");
288
configGroup.writeEntry("Description",_description);
289
configGroup.writeEntry("Opacity",_opacity);
290
configGroup.writeEntry("Wallpaper", _wallpaper->path());
292
for (int i=0 ; i < TABLE_COLORS ; i++)
294
RandomizationRange random = _randomTable != 0 ? _randomTable[i] : RandomizationRange();
295
writeColorEntry(config,colorNameForIndex(i),colorTable()[i],random);
299
QString ColorScheme::colorNameForIndex(int index)
301
Q_ASSERT( index >= 0 && index < TABLE_COLORS );
303
return QString(colorNames[index]);
305
QString ColorScheme::translatedColorNameForIndex(int index)
307
Q_ASSERT( index >= 0 && index < TABLE_COLORS );
309
return i18nc("@item:intable palette", translatedColorNames[index]);
311
void ColorScheme::readColorEntry(KConfig& config , int index)
313
KConfigGroup configGroup(&config,colorNameForIndex(index));
301
for (int i = 0 ; i < TABLE_COLORS ; i++) {
302
readColorEntry(config, i);
306
void ColorScheme::readColorEntry(const KConfig& config , int index)
308
KConfigGroup configGroup = config.group(colorNameForIndex(index));
315
310
ColorEntry entry;
317
entry.color = configGroup.readEntry("Color",QColor());
318
entry.transparent = configGroup.readEntry("Transparent",false);
312
entry.color = configGroup.readEntry("Color", QColor());
320
314
// Deprecated key from KDE 4.0 which set 'Bold' to true to force
321
315
// a color to be bold or false to use the current format
323
317
// TODO - Add a new tri-state key which allows for bold, normal or
324
318
// current format
325
319
if (configGroup.hasKey("Bold"))
326
entry.fontWeight = configGroup.readEntry("Bold",false) ? ColorEntry::Bold :
327
ColorEntry::UseCurrentFormat;
329
quint16 hue = configGroup.readEntry("MaxRandomHue",0);
330
quint8 value = configGroup.readEntry("MaxRandomValue",0);
331
quint8 saturation = configGroup.readEntry("MaxRandomSaturation",0);
333
setColorTableEntry( index , entry );
335
if ( hue != 0 || value != 0 || saturation != 0 )
336
setRandomizationRange( index , hue , saturation , value );
338
void ColorScheme::writeColorEntry(KConfig& config , const QString& colorName, const ColorEntry& entry , const RandomizationRange& random) const
340
KConfigGroup configGroup(&config,colorName);
342
configGroup.writeEntry("Color",entry.color);
343
configGroup.writeEntry("Transparency",(bool)entry.transparent);
344
if (entry.fontWeight != ColorEntry::UseCurrentFormat)
346
configGroup.writeEntry("Bold",entry.fontWeight == ColorEntry::Bold);
349
// record randomization if this color has randomization or
350
// if one of the keys already exists
351
if ( !random.isNull() || configGroup.hasKey("MaxRandomHue") )
353
configGroup.writeEntry("MaxRandomHue",(int)random.hue);
354
configGroup.writeEntry("MaxRandomValue",(int)random.value);
355
configGroup.writeEntry("MaxRandomSaturation",(int)random.saturation);
320
entry.fontWeight = configGroup.readEntry("Bold", false) ? ColorEntry::Bold :
321
ColorEntry::UseCurrentFormat;
323
setColorTableEntry(index , entry);
325
const quint16 hue = configGroup.readEntry("MaxRandomHue", 0);
326
const quint8 value = configGroup.readEntry("MaxRandomValue", 0);
327
const quint8 saturation = configGroup.readEntry("MaxRandomSaturation", 0);
329
if (hue != 0 || value != 0 || saturation != 0)
330
setRandomizationRange(index , hue , saturation , value);
333
void ColorScheme::write(KConfig& config) const
335
KConfigGroup configGroup = config.group("General");
337
configGroup.writeEntry("Description", _description);
338
configGroup.writeEntry("Opacity", _opacity);
339
configGroup.writeEntry("Wallpaper", _wallpaper->path());
341
for (int i = 0 ; i < TABLE_COLORS ; i++) {
342
writeColorEntry(config, i);
346
void ColorScheme::writeColorEntry(KConfig& config , int index) const
348
KConfigGroup configGroup = config.group(colorNameForIndex(index));
350
const ColorEntry& entry = colorTable()[index];
352
configGroup.writeEntry("Color", entry.color);
353
if ( configGroup.hasKey("Transparent") ) {
354
configGroup.deleteEntry("Transparent");
356
if (entry.fontWeight != ColorEntry::UseCurrentFormat) {
357
configGroup.writeEntry("Bold", entry.fontWeight == ColorEntry::Bold);
360
RandomizationRange random = _randomTable != 0 ? _randomTable[index] : RandomizationRange();
362
// record randomization if this color has randomization or
363
// if one of the keys already exists
364
if (!random.isNull() || configGroup.hasKey("MaxRandomHue")) {
365
configGroup.writeEntry("MaxRandomHue", (int)random.hue);
366
configGroup.writeEntry("MaxRandomValue", (int)random.value);
367
configGroup.writeEntry("MaxRandomSaturation", (int)random.saturation);
359
371
void ColorScheme::setWallpaper(const QString& path)
361
_wallpaper.attach(new ColorSchemeWallpaper(path));
373
_wallpaper = new ColorSchemeWallpaper(path);
364
376
ColorSchemeWallpaper::Ptr ColorScheme::wallpaper() const
449
461
const KColorScheme colorScheme(QPalette::Active);
451
QBrush colors[ColorRoleCount] =
453
colorScheme.foreground( colorScheme.NormalText ),
454
colorScheme.background( colorScheme.NormalBackground ),
463
QBrush colors[ColorRoleCount] = {
464
colorScheme.foreground(colorScheme.NormalText),
465
colorScheme.background(colorScheme.NormalBackground),
456
colorScheme.foreground( colorScheme.InactiveText ),
457
colorScheme.foreground( colorScheme.ActiveText ),
458
colorScheme.foreground( colorScheme.LinkText ),
459
colorScheme.foreground( colorScheme.VisitedText ),
460
colorScheme.foreground( colorScheme.NegativeText ),
461
colorScheme.foreground( colorScheme.NeutralText )
467
colorScheme.foreground(colorScheme.InactiveText),
468
colorScheme.foreground(colorScheme.ActiveText),
469
colorScheme.foreground(colorScheme.LinkText),
470
colorScheme.foreground(colorScheme.VisitedText),
471
colorScheme.foreground(colorScheme.NegativeText),
472
colorScheme.foreground(colorScheme.NeutralText)
464
for ( int i = 0 ; i < TABLE_COLORS ; i++ )
475
for (int i = 0 ; i < TABLE_COLORS ; i++) {
466
476
ColorEntry entry;
467
477
entry.color = colors[ i % ColorRoleCount ].color();
469
setColorTableEntry( i , entry );
473
KDE3ColorSchemeReader::KDE3ColorSchemeReader( QIODevice* device ) :
477
ColorScheme* KDE3ColorSchemeReader::read()
479
Q_ASSERT( _device->openMode() == QIODevice::ReadOnly ||
480
_device->openMode() == QIODevice::ReadWrite );
482
ColorScheme* scheme = new ColorScheme();
484
QRegExp comment("#.*$");
485
while ( !_device->atEnd() )
487
QString line(_device->readLine());
488
line.remove(comment);
489
line = line.simplified();
491
if ( line.isEmpty() )
494
if ( line.startsWith(QLatin1String("color")) )
496
if (!readColorLine(line,scheme))
497
kWarning() << "Failed to read KDE 3 color scheme line" << line;
499
else if ( line.startsWith(QLatin1String("title")) )
501
if (!readTitleLine(line,scheme))
502
kWarning() << "Failed to read KDE 3 color scheme title line" << line;
506
kWarning() << "KDE 3 color scheme contains an unsupported feature, '" <<
513
bool KDE3ColorSchemeReader::readColorLine(const QString& line,ColorScheme* scheme)
515
QStringList list = line.split(QChar(' '));
517
if (list.count() != 7)
519
if (list.first() != "color")
522
int index = list[1].toInt();
523
int red = list[2].toInt();
524
int green = list[3].toInt();
525
int blue = list[4].toInt();
526
int transparent = list[5].toInt();
527
int bold = list[6].toInt();
529
const int MAX_COLOR_VALUE = 255;
531
if( (index < 0 || index >= TABLE_COLORS )
532
|| (red < 0 || red > MAX_COLOR_VALUE )
533
|| (blue < 0 || blue > MAX_COLOR_VALUE )
534
|| (green < 0 || green > MAX_COLOR_VALUE )
535
|| (transparent != 0 && transparent != 1 )
536
|| (bold != 0 && bold != 1) )
540
entry.color = QColor(red,green,blue);
541
entry.transparent = ( transparent != 0 );
542
entry.fontWeight = ( bold != 0 ) ? ColorEntry::Bold : ColorEntry::UseCurrentFormat;
544
scheme->setColorTableEntry(index,entry);
547
bool KDE3ColorSchemeReader::readTitleLine(const QString& line,ColorScheme* scheme)
549
if( !line.startsWith(QLatin1String("title")) )
552
int spacePos = line.indexOf(' ');
556
QString description = line.mid(spacePos+1);
558
scheme->setDescription(i18n(description.toUtf8()));
561
ColorSchemeManager::ColorSchemeManager()
562
: _haveLoadedAll(false)
565
ColorSchemeManager::~ColorSchemeManager()
567
QHashIterator<QString,const ColorScheme*> iter(_colorSchemes);
568
while (iter.hasNext())
574
void ColorSchemeManager::loadAllColorSchemes()
579
QList<QString> nativeColorSchemes = listColorSchemes();
581
QListIterator<QString> nativeIter(nativeColorSchemes);
582
while ( nativeIter.hasNext() )
584
if ( loadColorScheme( nativeIter.next() ) )
590
QList<QString> kde3ColorSchemes = listKDE3ColorSchemes();
591
QListIterator<QString> kde3Iter(kde3ColorSchemes);
592
while ( kde3Iter.hasNext() )
594
if ( loadKDE3ColorScheme( kde3Iter.next() ) )
601
kWarning() << "failed to load " << failed << " color schemes.";
603
_haveLoadedAll = true;
605
QList<const ColorScheme*> ColorSchemeManager::allColorSchemes()
607
if ( !_haveLoadedAll )
609
loadAllColorSchemes();
612
return _colorSchemes.values();
614
bool ColorSchemeManager::loadKDE3ColorScheme(const QString& filePath)
616
QFile file(filePath);
617
if (!filePath.endsWith(QLatin1String(".schema")) || !file.open(QIODevice::ReadOnly))
620
KDE3ColorSchemeReader reader(&file);
621
ColorScheme* scheme = reader.read();
622
scheme->setName(QFileInfo(file).baseName());
625
if (scheme->name().isEmpty())
627
kWarning() << "color scheme name is not valid.";
632
QFileInfo info(filePath);
634
if ( !_colorSchemes.contains(info.baseName()) )
635
_colorSchemes.insert(scheme->name(),scheme);
638
kWarning() << "color scheme with name" << scheme->name() << "has already been" <<
645
void ColorSchemeManager::addColorScheme(ColorScheme* scheme)
647
_colorSchemes.insert(scheme->name(),scheme);
649
// save changes to disk
650
QString path = KGlobal::dirs()->saveLocation("data","konsole/") + scheme->name() + ".colorscheme";
651
KConfig config(path , KConfig::NoGlobals);
653
scheme->write(config);
655
bool ColorSchemeManager::loadColorScheme(const QString& filePath)
657
if ( !filePath.endsWith(QLatin1String(".colorscheme")) || !QFile::exists(filePath) )
660
QFileInfo info(filePath);
662
KConfig config(filePath , KConfig::NoGlobals);
663
ColorScheme* scheme = new ColorScheme();
664
scheme->setName(info.baseName());
665
scheme->read(config);
667
if (scheme->name().isEmpty())
669
kWarning() << "Color scheme in" << filePath << "does not have a valid name and was not loaded.";
674
if ( !_colorSchemes.contains(info.baseName()) )
676
_colorSchemes.insert(scheme->name(),scheme);
680
kDebug() << "color scheme with name" << scheme->name() << "has already been" <<
688
QList<QString> ColorSchemeManager::listKDE3ColorSchemes()
690
return KGlobal::dirs()->findAllResources("data",
692
KStandardDirs::NoDuplicates);
695
QList<QString> ColorSchemeManager::listColorSchemes()
697
return KGlobal::dirs()->findAllResources("data",
698
"konsole/*.colorscheme",
699
KStandardDirs::NoDuplicates);
701
const ColorScheme ColorSchemeManager::_defaultColorScheme;
702
const ColorScheme* ColorSchemeManager::defaultColorScheme() const
704
return &_defaultColorScheme;
706
bool ColorSchemeManager::deleteColorScheme(const QString& name)
708
Q_ASSERT( _colorSchemes.contains(name) );
710
// lookup the path and delete
711
QString path = findColorSchemePath(name);
712
if ( QFile::remove(path) )
714
_colorSchemes.remove(name);
719
kWarning() << "Failed to remove color scheme -" << path;
723
QString ColorSchemeManager::findColorSchemePath(const QString& name) const
725
QString path = KStandardDirs::locate("data","konsole/"+name+".colorscheme");
727
if ( !path.isEmpty() )
730
path = KStandardDirs::locate("data","konsole/"+name+".schema");
734
const ColorScheme* ColorSchemeManager::findColorScheme(const QString& name)
736
if ( name.isEmpty() )
737
return defaultColorScheme();
739
if ( _colorSchemes.contains(name) )
740
return _colorSchemes[name];
743
// look for this color scheme
744
QString path = findColorSchemePath(name);
745
if ( !path.isEmpty() && loadColorScheme(path) )
747
return findColorScheme(name);
751
if (!path.isEmpty() && loadKDE3ColorScheme(path))
752
return findColorScheme(name);
755
kWarning() << "Could not find color scheme - " << name;
760
K_GLOBAL_STATIC( ColorSchemeManager , theColorSchemeManager )
761
ColorSchemeManager* ColorSchemeManager::instance()
763
return theColorSchemeManager;
479
setColorTableEntry(i , entry);