1 /****************************************************************************
4 ** KRDB - puts current KDE color scheme into preprocessor statements
5 ** cats specially written application default files and uses xrdb -merge to
6 ** write to RESOURCE_MANAGER. Thus it gives a simple way to make non-KDE
7 ** applications fit in with the desktop
9 ** Copyright (C) 1998 by Mark Donohoe
10 ** Copyright (C) 1999 by Dirk A. Mueller (reworked for KDE 2.0)
11 ** Copyright (C) 2001 by Matthias Ettrich (add support for GTK applications )
12 ** Copyright (C) 2001 by Waldo Bastian <bastian@kde.org>
13 ** Copyright (C) 2002 by Karol Szwed <gallium@kde.org>
14 ** This application is freely distributable under the GNU Public License.
16 *****************************************************************************/
18 #include <config-workspace.h>
27 #include <QtCore/QSettings>
28 #include <QtCore/QTextCodec>
32 #include <QTextStream>
36 #include <ktoolinvocation.h>
37 #include <klauncher_iface.h>
38 #include <kapplication.h>
40 #include <kconfiggroup.h>
42 #include <kglobalsettings.h>
43 #include <kstandarddirs.h>
44 #include <ksavefile.h>
45 #include <ktemporaryfile.h>
52 #include <QtGui/qx11info_x11.h>
54 inline const char * gtkEnvVar(int version)
56 return 2==version ? "GTK2_RC_FILES" : "GTK_RC_FILES";
59 inline const char * sysGtkrc(int version)
63 if(access("/etc/opt/gnome/gtk-2.0", F_OK) == 0)
64 return "/etc/opt/gnome/gtk-2.0/gtkrc";
66 return "/etc/gtk-2.0/gtkrc";
70 if(access("/etc/opt/gnome/gtk", F_OK) == 0)
71 return "/etc/opt/gnome/gtk/gtkrc";
73 return "/etc/gtk/gtkrc";
77 inline const char * userGtkrc(int version)
79 return 2==version ? "/.gtkrc-2.0" : "/.gtkrc";
82 // -----------------------------------------------------------------------------
83 static void applyGtkStyles(bool active, int version)
85 QString gtkkde = KStandardDirs::locateLocal("config", 2==version?"gtkrc-2.0":"gtkrc");
86 QByteArray gtkrc = getenv(gtkEnvVar(version));
87 QStringList list = QFile::decodeName(gtkrc).split( ':');
88 QString userHomeGtkrc = QDir::homePath()+userGtkrc(version);
89 if (!list.contains(userHomeGtkrc))
90 list.prepend(userHomeGtkrc);
91 QLatin1String systemGtkrc = QLatin1String(sysGtkrc(version));
92 if (!list.contains(systemGtkrc))
93 list.prepend(systemGtkrc);
95 list.removeAll(gtkkde);
98 // Pass env. var to kdeinit.
99 QString name = gtkEnvVar(version);
100 QString value = list.join(":");
101 KToolInvocation::klauncher()->setLaunchEnv(name, value);
104 // -----------------------------------------------------------------------------
106 static void applyQtColors( QSettings& settings, QPalette& newPal )
108 QStringList actcg, inactcg, discg;
109 /* export kde color settings */
111 for (i = 0; i < QPalette::NColorRoles; i++)
112 actcg << newPal.color(QPalette::Active,
113 (QPalette::ColorRole) i).name();
114 for (i = 0; i < QPalette::NColorRoles; i++)
115 inactcg << newPal.color(QPalette::Inactive,
116 (QPalette::ColorRole) i).name();
117 for (i = 0; i < QPalette::NColorRoles; i++)
118 discg << newPal.color(QPalette::Disabled,
119 (QPalette::ColorRole) i).name();
121 settings.setValue("Qt/Palette/active", actcg);
122 settings.setValue("Qt/Palette/inactive", inactcg);
123 settings.setValue("Qt/Palette/disabled", discg);
126 // -----------------------------------------------------------------------------
128 static void applyQtSettings( KSharedConfigPtr kglobalcfg, QSettings& settings )
130 #warning FIXME: KGlobalSettings race, settings may not be reloaded yet
131 /* export font settings */
132 settings.setValue("Qt/font", KGlobalSettings::generalFont().toString());
134 /* export effects settings */
135 KConfigGroup kglobalgrp( kglobalcfg, "KDE-Global GUI Settings" );
136 int graphicEffects = kglobalgrp.readEntry("GraphicEffectsLevel", int(KGlobalSettings::graphicEffectsLevelDefault()));
137 KGlobalSettings::GraphicEffects graphicEffectsFlags = KGlobalSettings::GraphicEffects(graphicEffects);
138 bool effectsEnabled = (graphicEffectsFlags != KGlobalSettings::NoEffects);
139 bool fadeMenus = (graphicEffectsFlags & KGlobalSettings::ComplexAnimationEffects);
140 bool fadeTooltips = (graphicEffectsFlags & KGlobalSettings::ComplexAnimationEffects);
141 bool animateCombobox = (graphicEffectsFlags & KGlobalSettings::SimpleAnimationEffects);
142 // qDebug() << Q_FUNC_INFO << effectsEnabled << fadeMenus << fadeTooltips << animateCombobox;
144 QStringList guieffects;
145 if (effectsEnabled) {
146 guieffects << QString("general");
148 guieffects << QString("fademenu");
150 guieffects << QString("animatecombo");
152 guieffects << QString("fadetooltip");
154 guieffects << QString("none");
157 settings.setValue("Qt/GUIEffects", guieffects);
160 // -----------------------------------------------------------------------------
162 static void addColorDef(QString& s, const char* n, const QColor& col)
166 tmp.sprintf("#define %s #%02x%02x%02x\n",
167 n, col.red(), col.green(), col.blue());
173 // -----------------------------------------------------------------------------
175 static void copyFile(QFile& tmp, QString const& filename, bool )
178 if ( f.open(QIODevice::ReadOnly) ) {
179 QByteArray buf( 8192, ' ' );
180 while ( !f.atEnd() ) {
181 int read = f.read( buf.data(), buf.size() );
183 tmp.write( buf.data(), read );
189 // -----------------------------------------------------------------------------
191 static QString item( int i ) {
192 return QString::number( i / 255.0, 'f', 3 );
195 static QString color( const QColor& col )
197 return QString( "{ %1, %2, %3 }" ).arg( item( col.red() ) ).arg( item( col.green() ) ).arg( item( col.blue() ) );
200 static void createGtkrc( bool exportColors, const QPalette& cg, int version )
202 // lukas: why does it create in ~/.kde/share/config ???
203 // pfeiffer: so that we don't overwrite the user's gtkrc.
204 // it is found via the GTK_RC_FILES environment variable.
205 KSaveFile saveFile( KStandardDirs::locateLocal( "config", 2==version?"gtkrc-2.0":"gtkrc" ) );
206 if ( !saveFile.open() ) {
210 QTextStream t ( &saveFile );
211 t.setCodec( QTextCodec::codecForLocale () );
214 "# created by KDE, %1\n"
216 "# If you do not want KDE to override your GTK settings, select\n"
217 "# Appearance -> Colors in the System Settings and disable the checkbox\n"
218 "# \"Apply colors to non-KDE4 applications\"\n"
220 "#\n", QDateTime::currentDateTime().toString());
222 if ( 2==version ) { // we should maybe check for MacOS settings here
224 t << "gtk-alternative-button-order = 1" << endl;
230 t << "style \"default\"" << endl;
232 t << " bg[NORMAL] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
233 t << " bg[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
234 t << " bg[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
235 t << " bg[ACTIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl;
236 t << " bg[PRELIGHT] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
238 t << " base[NORMAL] = " << color( cg.color( QPalette::Active, QPalette::Base ) ) << endl;
239 t << " base[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
240 t << " base[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
241 t << " base[ACTIVE] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
242 t << " base[PRELIGHT] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
244 t << " text[NORMAL] = " << color( cg.color(QPalette::Active, QPalette::Text) ) << endl;
245 t << " text[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
246 t << " text[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl;
247 t << " text[ACTIVE] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
248 t << " text[PRELIGHT] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
250 t << " fg[NORMAL] = " << color ( cg.color( QPalette::Active, QPalette::Foreground ) ) << endl;
251 t << " fg[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
252 t << " fg[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl;
253 t << " fg[ACTIVE] = " << color( cg.color( QPalette::Active, QPalette::Foreground ) ) << endl;
254 t << " fg[PRELIGHT] = " << color( cg.color( QPalette::Active, QPalette::Foreground ) ) << endl;
257 t << "class \"*\" style \"default\"" << endl;
260 // tooltips don't have the standard background color
261 t << "style \"ToolTip\"" << endl;
263 QPalette group = QToolTip::palette();
264 t << " bg[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Background ) ) << endl;
265 t << " base[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Base ) ) << endl;
266 t << " text[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Text ) ) << endl;
267 t << " fg[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Foreground ) ) << endl;
270 t << "widget \"gtk-tooltip\" style \"ToolTip\"" << endl;
271 t << "widget \"gtk-tooltips\" style \"ToolTip\"" << endl;
275 // highlight the current (mouse-hovered) menu-item
276 // not every button, checkbox, etc.
277 t << "style \"MenuItem\"" << endl;
279 t << " bg[PRELIGHT] = " << color( cg.color(QPalette::Highlight) ) << endl;
280 t << " fg[PRELIGHT] = " << color( cg.color(QPalette::HighlightedText) ) << endl;
283 t << "class \"*MenuItem\" style \"MenuItem\"" << endl;
289 // -----------------------------------------------------------------------------
291 void runRdb( uint flags )
293 // Obtain the application palette that is about to be set.
294 bool exportColors = flags & KRdbExportColors;
295 bool exportQtColors = flags & KRdbExportQtColors;
296 bool exportQtSettings = flags & KRdbExportQtSettings;
297 bool exportXftSettings = flags & KRdbExportXftSettings;
299 KSharedConfigPtr kglobalcfg = KSharedConfig::openConfig( "kdeglobals" );
300 KConfigGroup kglobals(kglobalcfg, "KDE");
301 QPalette newPal = KGlobalSettings::createApplicationPalette(kglobalcfg);
303 KTemporaryFile tmpFile;
306 kDebug() << "Couldn't open temp file";
310 KConfigGroup generalCfgGroup(kglobalcfg, "General");
312 createGtkrc( exportColors, newPal, 1 );
313 createGtkrc( exportColors, newPal, 2 );
315 // Export colors to non-(KDE/Qt) apps (e.g. Motif, GTK+ apps)
318 KGlobal::dirs()->addResourceType("appdefaults", "data", "kdisplay/app-defaults/");
319 KGlobal::locale()->insertCatalog("krdb");
322 QColor backCol = newPal.color( QPalette::Active, QPalette::Background );
323 addColorDef(preproc, "FOREGROUND" , newPal.color( QPalette::Active, QPalette::Foreground ) );
324 addColorDef(preproc, "BACKGROUND" , backCol);
325 addColorDef(preproc, "HIGHLIGHT" , backCol.light(100+(2*KGlobalSettings::contrast()+4)*16/1));
326 addColorDef(preproc, "LOWLIGHT" , backCol.dark(100+(2*KGlobalSettings::contrast()+4)*10));
327 addColorDef(preproc, "SELECT_BACKGROUND" , newPal.color( QPalette::Active, QPalette::Highlight));
328 addColorDef(preproc, "SELECT_FOREGROUND" , newPal.color( QPalette::Active, QPalette::HighlightedText));
329 addColorDef(preproc, "WINDOW_BACKGROUND" , newPal.color( QPalette::Active, QPalette::Base ) );
330 addColorDef(preproc, "WINDOW_FOREGROUND" , newPal.color( QPalette::Active, QPalette::Text ) );
331 addColorDef(preproc, "INACTIVE_BACKGROUND", KGlobalSettings::inactiveTitleColor());
332 addColorDef(preproc, "INACTIVE_FOREGROUND", KGlobalSettings::inactiveTitleColor());
333 addColorDef(preproc, "ACTIVE_BACKGROUND" , KGlobalSettings::activeTitleColor());
334 addColorDef(preproc, "ACTIVE_FOREGROUND" , KGlobalSettings::activeTitleColor());
335 //---------------------------------------------------------------
337 tmpFile.write( preproc.toLatin1(), preproc.length() );
341 const QStringList adPaths = KGlobal::dirs()->findDirs("appdefaults", "");
342 for (QStringList::ConstIterator it = adPaths.constBegin(); it != adPaths.constEnd(); ++it) {
345 if ( dSys.exists() ) {
346 dSys.setFilter( QDir::Files );
347 dSys.setSorting( QDir::Name );
348 dSys.setNameFilters(QStringList("*.ad"));
349 list += dSys.entryList();
353 for (QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it)
354 copyFile(tmpFile, KStandardDirs::locate("appdefaults", *it ), true);
357 // Merge ~/.Xresources or fallback to ~/.Xdefaults
358 QString homeDir = QDir::homePath();
359 QString xResources = homeDir + "/.Xresources";
361 // very primitive support for ~/.Xresources by appending it
362 if ( QFile::exists( xResources ) )
363 copyFile(tmpFile, xResources, true);
365 copyFile(tmpFile, homeDir + "/.Xdefaults", true);
367 // Export the Xcursor theme & size settings
368 KConfigGroup mousecfg(KSharedConfig::openConfig( "kcminputrc" ), "Mouse" );
369 QString theme = mousecfg.readEntry("cursorTheme", QString());
370 QString size = mousecfg.readEntry("cursorSize", QString());
374 contents = "Xcursor.theme: " + theme + '\n';
377 contents += "Xcursor.size: " + size + '\n';
379 if (exportXftSettings)
381 if (generalCfgGroup.hasKey("XftAntialias"))
383 contents += "Xft.antialias: ";
384 if(generalCfgGroup.readEntry("XftAntialias", true))
390 if (generalCfgGroup.hasKey("XftHintStyle"))
392 QString hintStyle = generalCfgGroup.readEntry("XftHintStyle", "hintmedium");
393 contents += "Xft.hinting: ";
394 if(hintStyle.isEmpty())
398 if(hintStyle!="hintnone")
402 contents += "Xft.hintstyle: " + hintStyle + '\n';
406 if (generalCfgGroup.hasKey("XftSubPixel"))
408 QString subPixel = generalCfgGroup.readEntry("XftSubPixel");
409 if(!subPixel.isEmpty())
410 contents += "Xft.rgba: " + subPixel + '\n';
413 KConfig _cfgfonts( "kcmfonts" );
414 KConfigGroup cfgfonts(&_cfgfonts, "General");
416 if( cfgfonts.readEntry( "forceFontDPI", 0 ) != 0 )
417 contents += "Xft.dpi: " + cfgfonts.readEntry( "forceFontDPI" ) + '\n';
421 proc.start("xrdb", QStringList() << "-quiet" << "-remove" << "-nocpp");
422 if (proc.waitForStarted())
424 proc.write( QByteArray( "Xft.dpi\n" ) );
425 proc.closeWriteChannel();
426 proc.waitForFinished();
431 if (contents.length() > 0)
432 tmpFile.write( contents.toLatin1(), contents.length() );
436 QStringList procargs;
438 procargs << "-merge" << tmpFile.fileName();
440 procargs << "-quiet" << "-merge" << tmpFile.fileName();
442 QProcess::execute("xrdb", procargs);
444 applyGtkStyles(exportColors, 1);
445 applyGtkStyles(exportColors, 2);
448 if ( exportQtColors || exportQtSettings )
451 QSettings settings(QLatin1String("Katie"), QSettings::NativeFormat);
453 if ( exportQtColors )
454 applyQtColors( settings, newPal ); // For kcmcolors
456 if ( exportQtSettings )
457 applyQtSettings( kglobalcfg, settings ); // For kcmstyle
460 QApplication::flush();
462 // We let KIPC take care of ourselves, as we are in a KDE app with
463 // QApp::setDesktopSettingsAware(false);
464 // Instead of calling QApp::x11_apply_settings() directly, we instead
465 // modify the timestamp which propagates the settings changes onto
466 // Katie-only apps without adversely affecting ourselves.
468 // Cheat and use the current timestamp, since we just saved to qtrc.
469 QDateTime settingsstamp = QDateTime::currentDateTime();
471 static const QByteArray atomname("_QT_SETTINGS_TIMESTAMP");
472 static Atom qt_settings_timestamp = XInternAtom( QX11Info::display(), atomname.constData(), False);
475 QDataStream s(&stamp.buffer(), QIODevice::WriteOnly);
477 XChangeProperty( QX11Info::display(), QX11Info::appRootWindow(), qt_settings_timestamp,
478 qt_settings_timestamp, 8, PropModeReplace,
479 (unsigned char*) stamp.buffer().data(),
480 stamp.buffer().size() );
481 QApplication::flush();