File indexing completed on 2024-04-28 05:32:13
0001 /* 0002 this file is part of the oxygen gtk engine 0003 SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0004 SPDX-FileCopyrightText: 2010 Ruslan Kabatsayev <b7.10110111@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "oxygenqtsettings.h" 0010 #include "oxygencoloreffect.h" 0011 #include "oxygencolorutils.h" 0012 #include "oxygenfontinfo.h" 0013 #include "oxygengtkicons.h" 0014 #include "oxygengtkrc.h" 0015 #include "oxygenshadowhelper.h" 0016 #include "oxygentimeline.h" 0017 #include "config.h" 0018 0019 #include <glib.h> 0020 #include <glib/gstdio.h> 0021 #include <gtk/gtk.h> 0022 0023 #include <algorithm> 0024 #include <cstdio> 0025 #include <cstdlib> 0026 #include <cstring> 0027 #include <sys/stat.h> 0028 #include <fstream> 0029 #include <iostream> 0030 #include <sstream> 0031 0032 #ifdef GDK_WINDOWING_X11 0033 #include <gdk/gdkx.h> 0034 #include <X11/Xatom.h> 0035 #endif 0036 0037 namespace Oxygen 0038 { 0039 0040 //_________________________________________________________ 0041 const std::string QtSettings::_defaultKdeIconPath = "/usr/share/icons/"; 0042 0043 //_________________________________________________________ 0044 /* 0045 Note: the default values set in the constructor are actually ignored. 0046 Real default values are set via Oxygen::QtSettings::loadKdeGlobalsOptions, 0047 from the oxygenrc file provided with oxygen-gtk 0048 */ 0049 QtSettings::QtSettings( void ): 0050 _wmShadowsSupported( false ), 0051 _kdeIconTheme( "oxygen" ), 0052 _kdeFallbackIconTheme( "gnome" ), 0053 _inactiveChangeSelectionColor( false ), 0054 _useIconEffect( true ), 0055 _useBackgroundGradient( true ), 0056 _checkBoxStyle( CS_CHECK ), 0057 _tabStyle( TS_SINGLE ), 0058 _scrollBarAddLineButtons( 2 ), 0059 _scrollBarSubLineButtons( 1 ), 0060 _toolBarDrawItemSeparator( true ), 0061 _tooltipTransparent( true ), 0062 _tooltipDrawStyledFrames( true ), 0063 _viewDrawFocusIndicator( true ), 0064 _viewDrawTreeBranchLines( true ), 0065 _viewDrawTriangularExpander( true ), 0066 _viewTriangularExpanderSize( ArrowSmall ), 0067 _viewInvertSortIndicator( false ), 0068 _menuHighlightMode( MM_DARK ), 0069 _windowDragEnabled( true ), 0070 _windowDragMode( WD_FULL ), 0071 _useWMMoveResize( true ), 0072 _startDragDist( 4 ), 0073 _startDragTime( 500 ), 0074 _animationsEnabled( true ), 0075 _genericAnimationsEnabled( true ), 0076 _menuBarAnimationType( Fade ), 0077 _menuAnimationType( Fade ), 0078 _toolBarAnimationType( Fade ), 0079 _genericAnimationsDuration( 150 ), 0080 _menuBarAnimationsDuration( 150 ), 0081 _menuBarFollowMouseAnimationsDuration( 80 ), 0082 _menuAnimationsDuration( 150 ), 0083 _menuFollowMouseAnimationsDuration( 40 ), 0084 _toolBarAnimationsDuration( 50 ), 0085 _buttonSize( ButtonDefault ), 0086 _frameBorder( BorderDefault ), 0087 _windecoBlendType( FollowStyleHint ), 0088 _activeShadowConfiguration( Palette::Active ), 0089 _inactiveShadowConfiguration( Palette::Inactive ), 0090 _backgroundOpacity( 255 ), 0091 _argbEnabled( true ), 0092 _widgetExplorerEnabled( true ), 0093 _initialized( false ), 0094 _kdeColorsInitialized( false ), 0095 _gtkColorsInitialized( false ), 0096 _KDESession( false ) 0097 {} 0098 0099 //_________________________________________________________ 0100 bool QtSettings::initialize( unsigned int flags ) 0101 { 0102 0103 const bool forced( flags&Forced ); 0104 0105 // no attempt at initializing if gtk settings is not yet set 0106 if( !gtk_settings_get_default() ) return false; 0107 0108 if( _initialized && !forced ) return false; 0109 else if( !forced ) _initialized = true; 0110 0111 if( g_getenv( "KDE_FULL_SESSION" ) ) 0112 { _KDESession = true; } 0113 0114 // init application name 0115 if( flags & AppName ) 0116 { 0117 initUserConfigDir(); 0118 initApplicationName(); 0119 initArgb(); 0120 } 0121 0122 // keep track of whats changed 0123 bool changed( false ); 0124 0125 // support for wm shadows 0126 { 0127 const bool wmShadowsSupported( isAtomSupported( ShadowHelper::netWMShadowAtomName ) ); 0128 if( wmShadowsSupported != _wmShadowsSupported ) 0129 { 0130 _wmShadowsSupported = wmShadowsSupported; 0131 changed |= true; 0132 } 0133 } 0134 0135 // configuration path 0136 { 0137 const PathList old( _kdeConfigPathList ); 0138 _kdeConfigPathList = kdeConfigPathList(); 0139 changed |= (old != _kdeConfigPathList ); 0140 } 0141 0142 // icon path 0143 { 0144 const PathList old( _kdeIconPathList ); 0145 _kdeIconPathList = kdeIconPathList(); 0146 changed |= (old != _kdeIconPathList ); 0147 } 0148 0149 // load kdeglobals and oxygen option maps 0150 const bool kdeGlobalsChanged = loadKdeGlobals(); 0151 const bool oxygenChanged = loadOxygen(); 0152 0153 // do nothing if settings not changed 0154 if( forced && !(changed||kdeGlobalsChanged||oxygenChanged) ) return false; 0155 0156 // dialog button ordering 0157 /* TODO: in principle this should be needed only once */ 0158 if( flags & Extra ) 0159 { 0160 GtkSettings* settings( gtk_settings_get_default() ); 0161 gtk_settings_set_long_property( settings, "gtk-alternative-button-order", 1, "oxygen-gtk" ); 0162 } 0163 0164 // clear gtkrc 0165 _rc.clear(); 0166 0167 // kde globals options 0168 if( flags & KdeGlobals ) 0169 { loadKdeGlobalsOptions(); } 0170 0171 // oxygen options 0172 if( flags & Oxygen ) 0173 { loadOxygenOptions(); } 0174 0175 #if !OXYGEN_FORCE_KDE_ICONS_AND_FONTS 0176 // TODO: Add support for gtk schemes when not _KDESession 0177 if( _KDESession ) 0178 #endif 0179 { 0180 0181 // reload fonts 0182 if( flags & Fonts ) 0183 { loadKdeFonts(); } 0184 0185 // reload icons 0186 #if OXYGEN_ICON_HACK 0187 if( flags & Icons ) 0188 { loadKdeIcons(); } 0189 #endif 0190 0191 } 0192 0193 // color palette 0194 if( flags & Colors ) 0195 { 0196 loadKdePalette( forced ); 0197 generateGtkColors(); 0198 } 0199 0200 // apply extra programatically set metrics metrics 0201 if( flags & Extra ) 0202 { loadExtraOptions(); } 0203 0204 // print generated Gtkrc and commit 0205 #if OXYGEN_DEBUG 0206 std::cerr << "Oxygen::QtSettings::initialize - Gtkrc: " << std::endl; 0207 std::cerr << _rc << std::endl; 0208 #endif 0209 0210 // pass all resources to gtk and clear 0211 _rc.commit(); 0212 0213 #if OXYGEN_DEBUG 0214 std::cerr << "Oxygen::QtSettings::initialize - done. " << std::endl; 0215 #endif 0216 0217 return true; 0218 0219 } 0220 0221 //_________________________________________________________ 0222 bool QtSettings::runCommand( const std::string& command, char*& result ) const 0223 { return g_spawn_command_line_sync( command.c_str(), &result, 0L, 0L, 0L ) && result; } 0224 0225 //_________________________________________________________ 0226 bool QtSettings::loadKdeGlobals( void ) 0227 { 0228 0229 // save backup 0230 OptionMap old = _kdeGlobals; 0231 0232 // clear and reload 0233 _kdeGlobals.clear(); 0234 for( PathList::const_reverse_iterator iter = _kdeConfigPathList.rbegin(); iter != _kdeConfigPathList.rend(); ++iter ) 0235 { 0236 const std::string filename( sanitizePath( *iter + "/kdeglobals" ) ); 0237 _kdeGlobals.merge( OptionMap( filename ) ); 0238 monitorFile( filename ); 0239 } 0240 0241 #if OXYGEN_DEBUG 0242 std::cerr << "Oxygen::QtSettings::loadKdeGlobals - kdeglobals: " << std::endl; 0243 std::cerr << _kdeGlobals << std::endl; 0244 #endif 0245 0246 // check change 0247 return old != _kdeGlobals; 0248 0249 } 0250 0251 //_______________________________________________________ 0252 bool QtSettings::isAtomSupported( const std::string& atomNameQuery ) const 0253 { 0254 0255 // create atom 0256 #ifdef GDK_WINDOWING_X11 0257 0258 // get screen and check 0259 GdkScreen* screen = gdk_screen_get_default(); 0260 if( !screen ) return false; 0261 0262 // get display and check 0263 GdkDisplay *gdkDisplay( gdk_screen_get_display( screen ) ); 0264 Display* display( GDK_DISPLAY_XDISPLAY( gdkDisplay ) ); 0265 0266 // create atom 0267 Atom netSupportedAtom( XInternAtom( display, "_NET_SUPPORTED", False) ); 0268 if( !netSupportedAtom ) return false; 0269 0270 // root window 0271 Window root( GDK_WINDOW_XID( gdk_screen_get_root_window( screen ) ) ); 0272 if( !root ) return false; 0273 0274 Atom type; 0275 int format; 0276 unsigned char *data; 0277 unsigned long count; 0278 unsigned long after; 0279 int length = 32768; 0280 0281 while( true ) 0282 { 0283 0284 // get atom property on root window 0285 // length is incremented until after is zero 0286 if( XGetWindowProperty( 0287 display, root, 0288 netSupportedAtom, 0l, length, 0289 false, XA_ATOM, &type, 0290 &format, &count, &after, &data) != Success ) return false; 0291 0292 if( after == 0 ) break; 0293 0294 // free data, increase length 0295 XFree( data ); 0296 length *= 2; 0297 continue; 0298 0299 } 0300 0301 Atom* atoms = reinterpret_cast<Atom*>( data ); 0302 bool found( false ); 0303 for( unsigned long i = 0; i<count && !found; i++ ) 0304 { 0305 char* atomName = XGetAtomName( display, atoms[i]); 0306 if( strcmp( atomName, atomNameQuery.c_str() ) == 0 ) found = true; 0307 XFree( atomName ); 0308 } 0309 0310 return found; 0311 0312 #else 0313 return false; 0314 #endif 0315 0316 } 0317 0318 //_________________________________________________________ 0319 bool QtSettings::loadOxygen( void ) 0320 { 0321 0322 // save backup 0323 OptionMap old = _oxygen; 0324 0325 // clear and reload 0326 _oxygen.clear(); 0327 for( PathList::const_reverse_iterator iter = _kdeConfigPathList.rbegin(); iter != _kdeConfigPathList.rend(); ++iter ) 0328 { 0329 const std::string filename( sanitizePath( *iter + "/oxygenrc" ) ); 0330 _oxygen.merge( filename ); 0331 monitorFile( filename ); 0332 } 0333 0334 #if OXYGEN_DEBUG 0335 std::cerr << "Oxygen::QtSettings::loadOxygen - Oxygenrc: " << std::endl; 0336 std::cerr << _oxygen << std::endl; 0337 #endif 0338 0339 // check change 0340 return old != _oxygen; 0341 0342 } 0343 0344 //_________________________________________________________ 0345 PathList QtSettings::kdeConfigPathList( void ) const 0346 { 0347 0348 PathList out; 0349 0350 // load icon install prefix 0351 gchar* path = 0L; 0352 if( runCommand( "kde4-config --path config", path ) && path ) 0353 { 0354 0355 out.split( path ); 0356 g_free( path ); 0357 0358 } else { 0359 0360 out.push_back( userConfigDir() ); 0361 0362 } 0363 0364 out.push_back( GTK_THEME_DIR ); 0365 0366 #if OXYGEN_DEBUG 0367 std::cerr << "Oxygen::QtSettings::kdeConfigPathList - loading configuration from path: " << std::endl; 0368 std::cerr << out << std::endl; 0369 #endif 0370 0371 return out; 0372 0373 } 0374 0375 //_________________________________________________________ 0376 PathList QtSettings::kdeIconPathList( void ) const 0377 { 0378 0379 // load icon install prefix 0380 PathList out; 0381 char* path = 0L; 0382 if( runCommand( "kde4-config --path icon", path ) && path ) 0383 { 0384 out.split( path ); 0385 g_free( path ); 0386 } 0387 0388 // make sure defaultKdeIconPath is included in the list 0389 if( std::find( out.begin(), out.end(), _defaultKdeIconPath ) == out.end() ) 0390 { out.push_back( _defaultKdeIconPath ); } 0391 0392 return out; 0393 0394 } 0395 0396 //_________________________________________________________ 0397 void QtSettings::initUserConfigDir( void ) 0398 { 0399 0400 // create directory name 0401 _userConfigDir = std::string( g_get_user_config_dir() ) + "/oxygen-gtk"; 0402 0403 // make sure that corresponding directory does exist 0404 struct stat st; 0405 if( stat( _userConfigDir.c_str(), &st ) != 0 ) 0406 { 0407 #ifdef G_OS_WIN32 0408 // S_IRWXG and S_IRWXO are undefined on Windows, and g_mkdir() 0409 // ignores its second parameter on Windows anyway. 0410 g_mkdir( _userConfigDir.c_str(), 0 ); 0411 #else 0412 g_mkdir( _userConfigDir.c_str(), S_IRWXU|S_IRWXG|S_IRWXO ); 0413 #endif 0414 } 0415 0416 // note: in some cases, the target might exist and not be a directory 0417 // nothing we can do about it. We won't overwrite the file to prevent dataloss 0418 0419 } 0420 0421 //_________________________________________________________ 0422 void QtSettings::initArgb( void ) 0423 { 0424 // get program name 0425 const char* appName = g_get_prgname(); 0426 if( !appName ) return; 0427 0428 // user-defined configuration file 0429 const std::string userConfig( userConfigDir() + "/argb-apps.conf"); 0430 0431 // make sure user configuration file exists 0432 std::ofstream newConfig( userConfig.c_str(), std::ios::app ); 0433 if( newConfig ) 0434 { 0435 // if the file is empty (newly created), put a hint there 0436 if( !newConfig.tellp() ) 0437 { newConfig << "# argb-apps.conf\n# Put your user-specific ARGB app settings here\n\n"; } 0438 newConfig.close(); 0439 0440 } 0441 0442 // check for ARGB hack being disabled 0443 if(g_getenv("OXYGEN_DISABLE_ARGB_HACK")) 0444 { 0445 std::cerr << "Oxygen::QtSettings::initArgb - ARGB hack is disabled; program name: " << appName << std::endl; 0446 std::cerr << "Oxygen::QtSettings::initArgb - if disabling ARGB hack helps, please add this string:\n\ndisable:" << appName << "\n\nto ~/.config/oxygen-gtk/argb-apps.conf\nand report it here: https://bugs.kde.org/show_bug.cgi?id=260640" << std::endl; 0447 _argbEnabled = false; 0448 return; 0449 } 0450 0451 // get debug flag from environement 0452 const bool OXYGEN_ARGB_DEBUG = g_getenv("OXYGEN_ARGB_DEBUG"); 0453 0454 // read blacklist 0455 // system-wide configuration file 0456 const std::string configFile( std::string( GTK_THEME_DIR ) + "/argb-apps.conf" ); 0457 std::ifstream systemIn( configFile.c_str() ); 0458 if( !systemIn ) 0459 { 0460 0461 if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) ) 0462 { std::cerr << "Oxygen::QtSettings::initArgb - ARGB config file \"" << configFile << "\" not found" << std::endl; } 0463 0464 } 0465 0466 // load options into a string 0467 std::string contents; 0468 std::vector<std::string> lines; 0469 while( std::getline( systemIn, contents, '\n' ) ) 0470 { 0471 if( contents.empty() || contents[0] == '#' ) continue; 0472 lines.push_back( contents ); 0473 } 0474 0475 // user specific blacklist 0476 std::ifstream userIn( userConfig.c_str() ); 0477 if( !userIn ) 0478 { 0479 0480 if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) ) 0481 { std::cerr << "Oxygen::QtSettings::initArgb - user-defined ARGB config file \"" << userConfig << "\" not found - only system-wide one will be used" << std::endl; } 0482 0483 } 0484 0485 // load options into a string 0486 while( std::getline( userIn, contents, '\n' ) ) 0487 { 0488 if( contents.empty() || contents[0] == '#' ) continue; 0489 lines.push_back( contents ); 0490 } 0491 0492 // true if application was found in one of the lines 0493 bool found( false ); 0494 for( std::vector<std::string>::const_reverse_iterator iter = lines.rbegin(); iter != lines.rend() && !found; ++iter ) 0495 { 0496 0497 // store line locally 0498 std::string contents( *iter ); 0499 0500 // split string using ":" as a delimiter 0501 std::vector<std::string> appNames; 0502 size_t position( std::string::npos ); 0503 while( ( position = contents.find( ':' ) ) != std::string::npos ) 0504 { 0505 std::string appName( contents.substr(0, position ) ); 0506 if( !appName.empty() ) { appNames.push_back( appName ); } 0507 contents = contents.substr( position+1 ); 0508 } 0509 0510 if( !contents.empty() ) appNames.push_back( contents ); 0511 if( appNames.empty() ) continue; 0512 0513 // check line type 0514 bool enabled( true ); 0515 if( appNames[0] == "enable" ) enabled = true; 0516 else if( appNames[0] == "disable" ) enabled = false; 0517 else continue; 0518 0519 // compare application names to this application 0520 for( unsigned int i = 1; i < appNames.size(); i++ ) 0521 { 0522 if( appNames[i] == "all" || appNames[i] == appName ) 0523 { 0524 found = true; 0525 _argbEnabled = enabled; 0526 break; 0527 } 0528 } 0529 0530 } 0531 0532 } 0533 0534 //_________________________________________________________ 0535 void QtSettings::addIconTheme( PathList& pathList, const std::string& theme ) 0536 { 0537 0538 // do nothing if theme have already been included in the loop 0539 if( _iconThemes.find( theme ) != _iconThemes.end() ) return; 0540 _iconThemes.insert( theme ); 0541 0542 #if OXYGEN_DEBUG 0543 std::cerr << "Oxygen::QtSettings::addIconTheme - adding " << theme << std::endl; 0544 #endif 0545 0546 // add all possible path (based on _kdeIconPathList) and look for possible parent 0547 std::string parentTheme; 0548 for( PathList::const_iterator iter = _kdeIconPathList.begin(); iter != _kdeIconPathList.end(); ++iter ) 0549 { 0550 0551 // create path and check for existence 0552 std::string path( sanitizePath( *iter + '/' + theme ) ); 0553 struct stat st; 0554 if( stat( path.c_str(), &st ) != 0 ) continue; 0555 0556 // add to path list 0557 pathList.push_back( path ); 0558 if( parentTheme.empty() ) 0559 { 0560 const std::string index( sanitizePath( *iter + '/' + theme + "/index.theme" ) ); 0561 OptionMap themeOptions( index ); 0562 parentTheme = themeOptions.getValue( "[Icon Theme]", "Inherits" ); 0563 } 0564 0565 } 0566 0567 // add parent if needed 0568 if( !parentTheme.empty() ) 0569 { 0570 // split using "," as a separator 0571 PathList parentThemes( parentTheme, "," ); 0572 for( PathList::const_iterator iter = parentThemes.begin(); iter != parentThemes.end(); ++iter ) 0573 { addIconTheme( pathList, *iter ); } 0574 } 0575 0576 return; 0577 0578 } 0579 0580 //_________________________________________________________ 0581 void QtSettings::loadKdeIcons( void ) 0582 { 0583 0584 // update icon search path 0585 // put existing default path in a set 0586 PathSet searchPath( defaultIconSearchPath() ); 0587 0588 // add kde's path. Loop is reversed because added path must be prepended. 0589 for( PathList::const_reverse_iterator iter = _kdeIconPathList.rbegin(); iter != _kdeIconPathList.rend(); ++iter ) 0590 { 0591 0592 // remove trailing backslash, if any 0593 std::string path( *iter ); 0594 if( path.empty() ) continue; 0595 if( path[path.size()-1] == '/' ) path = path.substr( 0, path.size()-1 ); 0596 0597 // check if already present and prepend if not 0598 if( searchPath.find( path ) == searchPath.end() ) 0599 { gtk_icon_theme_prepend_search_path(gtk_icon_theme_get_default(), path.c_str() ); } 0600 } 0601 0602 // load icon theme and path to gtk 0603 _iconThemes.clear(); 0604 _kdeIconTheme = _kdeGlobals.getValue( "[Icons]", "Theme", "oxygen" ); 0605 0606 // store to settings 0607 GtkSettings* settings( gtk_settings_get_default() ); 0608 0609 gtk_settings_set_string_property( settings, "gtk-icon-theme-name", _kdeIconTheme.c_str(), "oxygen-gtk" ); 0610 gtk_settings_set_string_property( settings, "gtk-fallback-icon-theme-name", _kdeFallbackIconTheme.c_str(), "oxygen-gtk" ); 0611 0612 // load icon sizes from kde 0613 // const int desktopIconSize( _kdeGlobals.getOption( "[DesktopIcons]", "Size" ).toInt( 48 ) ); 0614 const int dialogIconSize( _kdeGlobals.getOption( "[DialogIcons]", "Size" ).toInt( 32 ) ); 0615 const int panelIconSize( _kdeGlobals.getOption( "[PanelIcons]", "Size" ).toInt( 32 ) ); 0616 const int mainToolbarIconSize( _kdeGlobals.getOption( "[MainToolbarIcons]", "Size" ).toInt( 22 ) ); 0617 const int smallIconSize( _kdeGlobals.getOption( "[SmallIcons]", "Size" ).toInt( 16 ) ); 0618 const int toolbarIconSize( _kdeGlobals.getOption( "[ToolbarIcons]", "Size" ).toInt( 22 ) ); 0619 0620 // set gtk icon sizes 0621 _icons.setIconSize( "panel-menu", smallIconSize ); 0622 _icons.setIconSize( "panel", panelIconSize ); 0623 _icons.setIconSize( "gtk-small-toolbar", toolbarIconSize ); 0624 _icons.setIconSize( "gtk-large-toolbar", mainToolbarIconSize ); 0625 _icons.setIconSize( "gtk-dnd", mainToolbarIconSize ); 0626 _icons.setIconSize( "gtk-button", smallIconSize ); 0627 _icons.setIconSize( "gtk-menu", smallIconSize ); 0628 _icons.setIconSize( "gtk-dialog", dialogIconSize ); 0629 _icons.setIconSize( "", smallIconSize ); 0630 0631 // load translation table, generate full translation list, and path to gtk 0632 _icons.loadTranslations( sanitizePath( std::string( GTK_THEME_DIR ) + "/icons4" ) ); 0633 0634 // generate full path list 0635 PathList iconThemeList; 0636 addIconTheme( iconThemeList, _kdeIconTheme ); 0637 addIconTheme( iconThemeList, _kdeFallbackIconTheme ); 0638 0639 _rc.merge( _icons.generate( iconThemeList ) ); 0640 0641 } 0642 0643 //_________________________________________________________ 0644 PathSet QtSettings::defaultIconSearchPath( void ) const 0645 { 0646 PathSet searchPath; 0647 0648 // load icon theme 0649 GtkIconTheme* theme( gtk_icon_theme_get_default() ); 0650 if( !GTK_IS_ICON_THEME( theme ) ) return searchPath; 0651 0652 // get default 0653 gchar** gtkSearchPath; 0654 int nElements; 0655 0656 gtk_icon_theme_get_search_path( theme, >kSearchPath, &nElements ); 0657 for( int i=0; i<nElements; i++ ) 0658 { searchPath.insert( gtkSearchPath[i] ); } 0659 0660 // free 0661 g_strfreev( gtkSearchPath ); 0662 0663 return searchPath; 0664 } 0665 0666 //_________________________________________________________ 0667 void QtSettings::loadKdePalette( bool forced ) 0668 { 0669 0670 if( _kdeColorsInitialized && !forced ) return; 0671 _kdeColorsInitialized = true; 0672 0673 // contrast 0674 ColorUtils::setContrast( _kdeGlobals.getOption( "[KDE]", "contrast" ).toVariant<double>( 7 ) / 10 ); 0675 0676 // palette 0677 _palette.clear(); 0678 _palette.setColor( Palette::Active, Palette::Window, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Window]", "BackgroundNormal" ) ) ); 0679 _palette.setColor( Palette::Active, Palette::WindowText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Window]", "ForegroundNormal" ) ) ); 0680 0681 _palette.setColor( Palette::Active, Palette::Button, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Button]", "BackgroundNormal" ) ) ); 0682 _palette.setColor( Palette::Active, Palette::ButtonText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Button]", "ForegroundNormal" ) ) ); 0683 0684 _palette.setColor( Palette::Active, Palette::Selected, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Selection]", "BackgroundNormal" ) ) ); 0685 _palette.setColor( Palette::Active, Palette::SelectedText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Selection]", "ForegroundNormal" ) ) ); 0686 0687 _palette.setColor( Palette::Active, Palette::Tooltip, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Tooltip]", "BackgroundNormal" ) ) ); 0688 _palette.setColor( Palette::Active, Palette::TooltipText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Tooltip]", "ForegroundNormal" ) ) ); 0689 0690 _palette.setColor( Palette::Active, Palette::Focus, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "DecorationFocus" ) ) ); 0691 _palette.setColor( Palette::Active, Palette::Hover, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "DecorationHover" ) ) ); 0692 0693 _palette.setColor( Palette::Active, Palette::Base, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "BackgroundNormal" ) ) ); 0694 _palette.setColor( Palette::Active, Palette::BaseAlternate, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "BackgroundAlternate" ) ) ); 0695 _palette.setColor( Palette::Active, Palette::Text, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "ForegroundNormal" ) ) ); 0696 _palette.setColor( Palette::Active, Palette::NegativeText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "ForegroundNegative" ) ) ); 0697 0698 _palette.setColor( Palette::Active, Palette::ActiveWindowBackground, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[WM]", "activeBackground" ) ) ); 0699 _palette.setColor( Palette::Active, Palette::InactiveWindowBackground, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[WM]", "inactiveBackground" ) ) ); 0700 0701 // load effects 0702 const ColorUtils::Effect disabledEffect( Palette::Disabled, _kdeGlobals ); 0703 const ColorUtils::Effect inactiveEffect( Palette::Inactive, _kdeGlobals ); 0704 0705 // generate inactive and disabled palette from active, applying effects from kdeglobals 0706 _inactiveChangeSelectionColor = ( _kdeGlobals.getOption( "[ColorEffects:Inactive]", "ChangeSelectionColor" ).toVariant<std::string>( "false" ) == "true" ); 0707 _palette.generate( Palette::Active, Palette::Inactive, inactiveEffect, _inactiveChangeSelectionColor ); 0708 _palette.generate( Palette::Active, Palette::Disabled, disabledEffect ); 0709 0710 #if OXYGEN_DEBUG 0711 std::cerr << "Oxygen::QtSettings::loadKdePalette - disabled effect: " << std::endl; 0712 std::cerr << disabledEffect << std::endl; 0713 0714 std::cerr << "Oxygen::QtSettings::loadKdePalette - inactive effect: " << std::endl; 0715 std::cerr << inactiveEffect << std::endl; 0716 0717 std::cerr << "Oxygen::QtSettings::loadKdePalette - palette: " << std::endl; 0718 std::cerr << _palette << std::endl; 0719 #endif 0720 0721 } 0722 0723 //_________________________________________________________ 0724 void QtSettings::generateGtkColors( void ) 0725 { 0726 0727 #if OXYGEN_DEBUG 0728 std::cerr << "Oxygen::QtSettings::generateGtkColors" << std::endl; 0729 #endif 0730 0731 // customize gtk palette 0732 _palette.setGroup( Palette::Active ); 0733 0734 // default colors 0735 _rc.setCurrentSection( Gtk::RC::defaultSection() ); 0736 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Window ) ) ); 0737 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[PRELIGHT]", _palette.color( Palette::Window ) ) ); 0738 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[ACTIVE]", _palette.color( Palette::Window ) ) ); 0739 0740 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[SELECTED]", _palette.color( Palette::Selected ) ) ); 0741 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[INSENSITIVE]", _palette.color( Palette::Window ) ) ); 0742 0743 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::WindowText ) ) ); 0744 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 0745 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 0746 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[SELECTED]", _palette.color( Palette::WindowText ) ) ); 0747 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::WindowText ) ) ); 0748 0749 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[NORMAL]", _palette.color( Palette::Base ) ) ); 0750 0751 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[ACTIVE]", _palette.color( Palette::Inactive, Palette::Selected ) ) ); 0752 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[PRELIGHT]", _palette.color( Palette::Base ) ) ); 0753 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[SELECTED]", _palette.color( Palette::Selected ) ) ); 0754 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Base ) ) ); 0755 0756 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::Text ) ) ); 0757 0758 if( _inactiveChangeSelectionColor ) _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::Text ) ) ); 0759 else _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::SelectedText ) ) ); 0760 0761 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::Text ) ) ); 0762 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[SELECTED]", _palette.color( Palette::SelectedText ) ) ); 0763 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Text ) ) ); 0764 addLinkColors( "[Colors:Window]" ); 0765 0766 // buttons 0767 _rc.addSection( "oxygen-buttons-internal", Gtk::RC::defaultSection() ); 0768 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Button ) ) ); 0769 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[ACTIVE]", _palette.color( Palette::Button ) ) ); 0770 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[PRELIGHT]", _palette.color( Palette::Button ) ) ); 0771 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Button ) ) ); 0772 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::ButtonText ) ) ); 0773 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::ButtonText ) ) ); 0774 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::ButtonText ) ) ); 0775 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::ButtonText ) ) ); 0776 addLinkColors( "[Colors:Button]" ); 0777 0778 _rc.matchClassToSection( "*Button", "oxygen-buttons-internal" ); 0779 _rc.matchClassToSection( "GtkOptionMenu", "oxygen-buttons-internal" ); 0780 _rc.matchWidgetClassToSection( "*<GtkButton>.<GtkLabel>", "oxygen-buttons-internal" ); 0781 _rc.matchWidgetClassToSection( "*<GtkButton>.<GtkAlignment>.<GtkBox>.<GtkLabel>", "oxygen-buttons-internal" ); 0782 0783 // combobox 0784 _rc.addSection( "oxygen-combobox-internal", "oxygen-buttons-internal" ); 0785 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::ButtonText ) ) ); 0786 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::ButtonText ) ) ); 0787 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::ButtonText ) ) ); 0788 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::ButtonText ) ) ); 0789 _rc.matchWidgetClassToSection( "*<GtkComboBox>.*<GtkCellView>", "oxygen-combobox-internal" ); 0790 0791 // checkboxes and radio buttons 0792 _rc.addSection( "oxygen-checkbox-buttons-internal", "oxygen-buttons-internal" ); 0793 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::WindowText ) ) ); 0794 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 0795 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 0796 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::WindowText ) ) ); 0797 _rc.matchWidgetClassToSection( "*<GtkCheckButton>.<GtkLabel>", "oxygen-checkbox-buttons-internal" ); 0798 0799 // progressbar labels 0800 _rc.addSection( "oxygen-progressbar-internal", Gtk::RC::defaultSection() ); 0801 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::WindowText ) ) ); 0802 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 0803 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 0804 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::WindowText ) ) ); 0805 0806 _rc.matchClassToSection( "GtkProgressBar", "oxygen-progressbar-internal" ); 0807 0808 // menu items 0809 _rc.addSection( "oxygen-menubar-item-internal", "oxygen-menu-font-internal" ); 0810 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::Text ) ) ); 0811 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::WindowText ) ) ); 0812 0813 if( _menuHighlightMode == MM_STRONG ) 0814 { 0815 0816 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::Text ) ) ); 0817 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[SELECTED]", _palette.color( Palette::SelectedText ) ) ); 0818 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::SelectedText ) ) ); 0819 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 0820 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[SELECTED]", _palette.color( Palette::SelectedText ) ) ); 0821 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::SelectedText ) ) ); 0822 0823 } else { 0824 0825 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::Text ) ) ); 0826 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[SELECTED]", _palette.color( Palette::Text ) ) ); 0827 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::Text ) ) ); 0828 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 0829 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[SELECTED]", _palette.color( Palette::WindowText ) ) ); 0830 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 0831 0832 } 0833 _rc.matchWidgetClassToSection( "*<GtkMenuItem>.<GtkLabel>", "oxygen-menubar-item-internal" ); 0834 0835 0836 if( _menuHighlightMode == MM_STRONG ) 0837 { 0838 _rc.addSection( "oxygen-menu-item-internal", "oxygen-menubar-item-internal" ); 0839 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::SelectedText ) ) ); 0840 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::SelectedText ) ) ); 0841 _rc.matchWidgetClassToSection( "*<GtkMenu>.<GtkMenuItem>.<GtkLabel>", "oxygen-menu-item-internal" ); 0842 } 0843 0844 // text entries 0845 _rc.addSection( "oxygen-entry-internal", Gtk::RC::defaultSection() ); 0846 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Base ) ) ); 0847 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Base ) ) ); 0848 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Base ) ) ); 0849 addLinkColors( "[Colors:View]" ); 0850 _rc.matchClassToSection( "GtkSpinButton", "oxygen-entry-internal" ); 0851 _rc.matchClassToSection( "GtkEntry", "oxygen-entry-internal" ); 0852 _rc.matchClassToSection( "GtkTextView", "oxygen-entry-internal" ); 0853 _rc.matchWidgetClassToSection( "*<GtkComboBoxEntry>.<GtkButton>", "oxygen-entry-internal" ); 0854 _rc.matchWidgetClassToSection( "*<GtkCombo>.<GtkButton>", "oxygen-entry-internal" ); 0855 0856 // tooltips 0857 _rc.addSection( "oxygen-tooltips-internal", Gtk::RC::defaultSection() ); 0858 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Tooltip ) ) ); 0859 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::TooltipText ) ) ); 0860 _rc.addToCurrentSection( Gtk::RCOption<int>( " xthickness", 3 ) ); 0861 _rc.addToCurrentSection( Gtk::RCOption<int>( " ythickness", 3 ) ); 0862 addLinkColors( "[Colors:Tooltip]" ); 0863 0864 _rc.matchWidgetToSection( "gtk-tooltip*", "oxygen-tooltips-internal" ); 0865 0866 // special case for google chrome 0867 /* based on http://code.google.com/p/chromium/wiki/LinuxGtkThemeIntegration */ 0868 _rc.addSection( "oxygen-chrome-gtk-frame-internal", Gtk::RC::defaultSection() ); 0869 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " ChromeGtkFrame::frame-color", _palette.color( Palette::Window ) ) ); 0870 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " ChromeGtkFrame::inactive-frame-color", _palette.color( Palette::Window ) ) ); 0871 _rc.matchClassToSection( "ChromeGtkFrame", "oxygen-chrome-gtk-frame-internal" ); 0872 0873 } 0874 0875 0876 //_________________________________________________________ 0877 void QtSettings::addLinkColors( const std::string& section ) 0878 { 0879 0880 { 0881 // link colors 0882 // from http://ubuntuforums.org/showthread.php?p=7009302 0883 const ColorUtils::Rgba linkColor( ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( section, "ForegroundLink" ) ) ); 0884 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkWidget::link-color", linkColor ) ); 0885 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkHTML::alink_color", linkColor ) ); 0886 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkHTML::link_color", linkColor ) ); 0887 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GnomeHref::link-color", linkColor ) ); 0888 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkIMHtml::hyperlink-color", linkColor ) ); 0889 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkIMHtml::hyperlink-prelight-color", linkColor ) ); 0890 } 0891 0892 { 0893 // visited link colors 0894 // from http://ubuntuforums.org/showthread.php?p=7009302 0895 const ColorUtils::Rgba visitedLinkColor( ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( section, "ForegroundVisited" ) ) ); 0896 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkWidget::visited-link-color", visitedLinkColor ) ); 0897 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkHTML::vlink_color", visitedLinkColor ) ); 0898 } 0899 0900 } 0901 0902 //_________________________________________________________ 0903 void QtSettings::loadKdeFonts( void ) 0904 { 0905 0906 // try load default font 0907 FontInfo::Map fonts; 0908 FontInfo defaultFont; 0909 if( _kdeGlobals.hasOption( "[General]", "font" ) ) 0910 { 0911 0912 defaultFont = FontInfo::fromKdeOption( _kdeGlobals.getValue( "[General]", "font", "" ) ); 0913 0914 } else { 0915 0916 #if OXYGEN_DEBUG 0917 std::cerr << "Oxygen::QtSettings::loadKdeFonts - cannot load default font" << std::endl; 0918 #endif 0919 0920 } 0921 0922 fonts[FontInfo::Default] = defaultFont; 0923 0924 // load extra fonts 0925 typedef std::map<FontInfo::FontType, std::string> FontNameMap; 0926 FontNameMap optionNames; 0927 optionNames.insert( std::make_pair( FontInfo::Desktop, "desktopFont" ) ); 0928 optionNames.insert( std::make_pair( FontInfo::Fixed, "fixed" ) ); 0929 optionNames.insert( std::make_pair( FontInfo::Menu, "menuFont" ) ); 0930 optionNames.insert( std::make_pair( FontInfo::ToolBar, "toolBarFont" ) ); 0931 for( FontNameMap::const_iterator iter = optionNames.begin(); iter != optionNames.end(); ++iter ) 0932 { 0933 FontInfo local; 0934 if( _kdeGlobals.hasOption( "[General]", iter->second ) ) 0935 { 0936 0937 local = FontInfo::fromKdeOption( _kdeGlobals.getValue( "[General]", iter->second, "" ) ); 0938 0939 } else { 0940 0941 #if OXYGEN_DEBUG 0942 std::cerr << "Oxygen::QtSettings::loadKdeFonts - cannot load font named " << iter->second << std::endl; 0943 #endif 0944 local = defaultFont; 0945 0946 } 0947 0948 // store in map 0949 fonts[iter->first] = local; 0950 0951 } 0952 0953 // pass fonts to RC 0954 if( fonts[FontInfo::Default].isValid() ) 0955 { 0956 // pass to settings 0957 GtkSettings* settings( gtk_settings_get_default() ); 0958 gtk_settings_set_string_property( settings, "gtk-font-name", fonts[FontInfo::Default].toString( false ).c_str(), "oxygen-gtk" ); 0959 0960 _rc.setCurrentSection( Gtk::RC::defaultSection() ); 0961 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " font_name", fonts[FontInfo::Default].toString() ) ); 0962 } 0963 0964 if( fonts[FontInfo::Menu].isValid() ) 0965 { 0966 _rc.addSection( "oxygen-menu-font-internal", Gtk::RC::defaultSection() ); 0967 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " font_name", fonts[FontInfo::Menu].toString() ) ); 0968 _rc.matchWidgetClassToSection( "*<GtkMenuItem>.<GtkLabel>", "oxygen-menu-font-internal" ); 0969 } 0970 0971 if( fonts[FontInfo::ToolBar].isValid() ) 0972 { 0973 _rc.addSection( "oxygen-toolbar-font-internal", Gtk::RC::defaultSection() ); 0974 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " font_name", fonts[FontInfo::ToolBar].toString() ) ); 0975 _rc.matchWidgetClassToSection( "*<GtkToolbar>.*", "oxygen-toolbar-font-internal" ); 0976 } 0977 0978 // don't check for section and tag presence - use default font if not present 0979 _WMFont=FontInfo::fromKdeOption( _kdeGlobals.getValue( "[WM]", "activeFont", "Sans Serif,8,-1,5,50,0,0,0,0,0" ) ); 0980 0981 } 0982 0983 //_________________________________________________________ 0984 void QtSettings::loadKdeGlobalsOptions( void ) 0985 { 0986 0987 #if OXYGEN_DEBUG 0988 std::cerr << "Oxygen::QtSettings::loadKdeGlobalsOptions" << std::endl; 0989 #endif 0990 0991 // toolbar style 0992 const std::string toolbarTextPosition( _kdeGlobals.getOption( "[Toolbar style]", "ToolButtonStyle" ).toVariant<std::string>( "TextBelowIcon" ) ); 0993 GtkToolbarStyle toolbarStyle( GTK_TOOLBAR_BOTH ); 0994 if( toolbarTextPosition == "TextOnly" ) toolbarStyle = GTK_TOOLBAR_TEXT; 0995 else if( toolbarTextPosition == "TextBesideIcon" ) toolbarStyle = GTK_TOOLBAR_BOTH_HORIZ; 0996 else if( toolbarTextPosition == "NoText" ) toolbarStyle = GTK_TOOLBAR_ICONS; 0997 0998 GtkSettings* settings( gtk_settings_get_default() ); 0999 gtk_settings_set_long_property( settings, "gtk-toolbar-style", toolbarStyle, "oxygen-gtk" ); 1000 1001 // icons on buttons 1002 if( _kdeGlobals.getValue( "[KDE]", "ShowIconsOnPushButtons", "true" ) == "false" ) 1003 { gtk_settings_set_long_property( settings, "gtk-button-images", 0, "oxygen-gtk" ); } 1004 1005 // active icon effects 1006 _useIconEffect = _kdeGlobals.getOption( "[MainToolbarIcons]", "ActiveEffect" ).toVariant<std::string>( "gamma" ) != "none"; 1007 1008 // start drag time and distance 1009 _startDragDist = _kdeGlobals.getOption( "[KDE]", "StartDragDist" ).toVariant<int>( 4 ); 1010 _startDragTime = _kdeGlobals.getOption( "[KDE]", "StartDragTime" ).toVariant<int>( 500 ); 1011 1012 } 1013 1014 //_________________________________________________________ 1015 void QtSettings::loadOxygenOptions( void ) 1016 { 1017 1018 // background pixmap 1019 _backgroundPixmap = _oxygen.getValue( "[Common]", "BackgroundPixmap", "" ); 1020 1021 // background gradient 1022 _useBackgroundGradient = ( _oxygen.getValue( "[Common]", "UseBackgroundGradient", "true" ) == "true" ); 1023 1024 // checkbox style 1025 _checkBoxStyle = (_oxygen.getValue( "[Style]", "CheckBoxStyle", "CS_CHECK" ) == "CS_CHECK") ? CS_CHECK:CS_X; 1026 1027 // checkbox style 1028 _tabStyle = (_oxygen.getValue( "[Style]", "TabStyle", "TS_SINGLE" ) == "TS_SINGLE") ? TS_SINGLE:TS_PLAIN; 1029 1030 // scrollbar buttons 1031 _scrollBarAddLineButtons = _oxygen.getOption( "[Style]", "ScrollBarAddLineButtons" ).toVariant<int>( 2 ); 1032 _scrollBarSubLineButtons = _oxygen.getOption( "[Style]", "ScrollBarSubLineButtons" ).toVariant<int>( 1 ); 1033 1034 // toolbar separators 1035 _toolBarDrawItemSeparator = _oxygen.getOption( "[Style]", "ToolBarDrawItemSeparator" ).toVariant<std::string>("true") == "true"; 1036 1037 // tooltips 1038 _tooltipTransparent = _oxygen.getOption( "[Style]", "ToolTipTransparent" ).toVariant<std::string>("true") == "true"; 1039 _tooltipDrawStyledFrames = _oxygen.getOption( "[Style]", "ToolTipDrawStyledFrames" ).toVariant<std::string>("true") == "true"; 1040 1041 // focus indicator in views 1042 _viewDrawFocusIndicator = _oxygen.getOption( "[Style]", "ViewDrawFocusIndicator" ).toVariant<std::string>("true") == "true"; 1043 1044 // tree branch lines 1045 _viewDrawTreeBranchLines = _oxygen.getOption( "[Style]", "ViewDrawTreeBranchLines" ).toVariant<std::string>("true") == "true"; 1046 1047 // triangular expanders 1048 _viewDrawTriangularExpander = _oxygen.getOption( "[Style]", "ViewDrawTriangularExpander" ).toVariant<std::string>("true") == "true"; 1049 1050 // triangular expander (arrow) size 1051 std::string expanderSize( _oxygen.getOption( "[Style]", "ViewTriangularExpanderSize" ).toVariant<std::string>("TE_SMALL") ); 1052 if( expanderSize == "TE_NORMAL" ) _viewTriangularExpanderSize = ArrowNormal; 1053 else if( expanderSize == "TE_TINY" ) _viewTriangularExpanderSize = ArrowTiny; 1054 else _viewTriangularExpanderSize = ArrowSmall; 1055 1056 // invert view sort indicators 1057 _viewInvertSortIndicator = _oxygen.getOption( "[Style]", "ViewInvertSortIndicator" ).toVariant<std::string>("false") == "true"; 1058 1059 // menu highlight mode 1060 std::string highlightMode( _oxygen.getOption( "[Style]", "MenuHighlightMode" ).toVariant<std::string>("MM_DARK") ); 1061 if( highlightMode == "MM_SUBTLE" ) _menuHighlightMode = MM_SUBTLE; 1062 else if( highlightMode == "MM_STRONG" ) _menuHighlightMode = MM_STRONG; 1063 else _menuHighlightMode = MM_DARK; 1064 1065 // window drag mode 1066 _windowDragEnabled = _oxygen.getOption( "[Style]", "WindowDragEnabled" ).toVariant<std::string>("true") == "true"; 1067 1068 std::string windowDragMode( _oxygen.getOption( "[Style]", "WindowDragMode" ).toVariant<std::string>("WD_FULL") ); 1069 if( windowDragMode == "WD_MINIMAL" ) _windowDragMode = WD_MINIMAL; 1070 else _windowDragMode = WD_FULL; 1071 1072 // use window manager to handle window drag 1073 _useWMMoveResize = _oxygen.getOption( "[Style]", "UseWMMoveResize" ).toVariant<std::string>("true") == "true"; 1074 1075 // animations 1076 _animationsEnabled = ( _oxygen.getOption( "[Style]", "AnimationsEnabled" ).toVariant<std::string>("true") == "true" ); 1077 _genericAnimationsEnabled = ( _oxygen.getOption( "[Style]", "GenericAnimationsEnabled" ).toVariant<std::string>("true") == "true" ); 1078 1079 // menubar animation type 1080 std::string menuBarAnimationType( _oxygen.getValue( "[Style]", "MenuBarAnimationType", "MB_FADE") ); 1081 if( menuBarAnimationType == "MB_NONE" ) _menuBarAnimationType = NoAnimation; 1082 else if( menuBarAnimationType == "MB_FADE" ) _menuBarAnimationType = Fade; 1083 else if( menuBarAnimationType == "MB_FOLLOW_MOUSE" ) _menuBarAnimationType = FollowMouse; 1084 1085 // menubar animation type 1086 std::string menuAnimationType( _oxygen.getValue( "[Style]", "MenuAnimationType", "ME_FADE") ); 1087 if( menuAnimationType == "ME_NONE" ) _menuAnimationType = NoAnimation; 1088 else if( menuAnimationType == "ME_FADE" ) _menuAnimationType = Fade; 1089 else if( menuAnimationType == "ME_FOLLOW_MOUSE" ) _menuAnimationType = FollowMouse; 1090 1091 // toolbar animation type 1092 std::string toolBarAnimationType( _oxygen.getValue( "[Style]", "ToolBarAnimationType", "TB_FADE") ); 1093 if( toolBarAnimationType == "TB_NONE" ) _toolBarAnimationType = NoAnimation; 1094 else if( toolBarAnimationType == "TB_FADE" ) _toolBarAnimationType = Fade; 1095 else if( toolBarAnimationType == "TB_FOLLOW_MOUSE" ) _toolBarAnimationType = FollowMouse; 1096 1097 // animations duration 1098 _genericAnimationsDuration = _oxygen.getOption( "[Style]", "GenericAnimationsDuration" ).toVariant<int>(150); 1099 _menuBarAnimationsDuration = _oxygen.getOption( "[Style]", "MenuBarAnimationsDuration" ).toVariant<int>(150); 1100 _menuBarFollowMouseAnimationsDuration = _oxygen.getOption( "[Style]", "MenuBarFollowMouseAnimationsDuration" ).toVariant<int>(80); 1101 _menuAnimationsDuration = _oxygen.getOption( "[Style]", "MenuAnimationsDuration" ).toVariant<int>(150); 1102 _menuFollowMouseAnimationsDuration = _oxygen.getOption( "[Style]", "MenuFollowMouseAnimationsDuration" ).toVariant<int>(40); 1103 _toolBarAnimationsDuration = _oxygen.getOption( "[Style]", "ToolBarAnimationsDuration" ).toVariant<int>(50); 1104 1105 // animation steps 1106 TimeLine::setSteps( _oxygen.getOption( "[Style]", "AnimationSteps" ).toVariant<int>( 10 ) ); 1107 1108 // widget explorer 1109 _widgetExplorerEnabled = 1110 _oxygen.getOption( "[Style]", "WidgetExplorerEnabled" ).toVariant<std::string>("false") == "true" || 1111 _oxygen.getOption( "[Style]", "WidgetExplorerGtkEnabled" ).toVariant<std::string>("false") == "true"; 1112 1113 // window decoration button size 1114 std::string buttonSize( _oxygen.getValue( "[Windeco]", "ButtonSize", "Normal") ); 1115 if( buttonSize == "Small" ) _buttonSize = ButtonSmall; 1116 else if( buttonSize == "Large" ) _buttonSize = ButtonLarge; 1117 else if( buttonSize == "Very Large" ) _buttonSize = ButtonVeryLarge; 1118 else if( buttonSize == "Huge" ) _buttonSize = ButtonHuge; 1119 else _buttonSize = ButtonDefault; 1120 1121 // window decoration frame border size 1122 std::string frameBorder( _oxygen.getValue( "[Windeco]", "FrameBorder", "Normal") ); 1123 if( frameBorder == "No Border" ) _frameBorder = BorderNone; 1124 else if( frameBorder == "No Side Border" ) _frameBorder = BorderNoSide; 1125 else if( frameBorder == "Tiny" ) _frameBorder = BorderTiny; 1126 else if( frameBorder == "Large" ) _frameBorder = BorderLarge; 1127 else if( frameBorder == "Very Large" ) _frameBorder = BorderVeryLarge; 1128 else if( frameBorder == "Huge" ) _frameBorder = BorderHuge; 1129 else if( frameBorder == "Very Huge" ) _frameBorder = BorderVeryHuge; 1130 else if( frameBorder == "Oversized" ) _frameBorder = BorderOversized; 1131 else _frameBorder = BorderDefault; 1132 1133 // window decoration title alignment 1134 std::string titleAlign( _oxygen.getValue( "[Windeco]", "TitleAlignment", "Center" ) ); 1135 if( titleAlign == "Left" ) _titleAlignment = PANGO_ALIGN_LEFT; 1136 else if( titleAlign == "Center" ) _titleAlignment = PANGO_ALIGN_CENTER; 1137 else if( titleAlign == "Right" ) _titleAlignment = PANGO_ALIGN_RIGHT; 1138 else _titleAlignment = PANGO_ALIGN_CENTER; 1139 1140 // window decoration radial gradient enable option 1141 std::string wdBlendType( _oxygen.getValue( "[Windeco]", "BlendColor", "Follow Style Hint" ) ); 1142 if( wdBlendType == "Follow Style Hint" ) _windecoBlendType=FollowStyleHint; 1143 else if( wdBlendType == "Radial Gradient" ) _windecoBlendType=RadialGradient; 1144 else if( wdBlendType == "Solid Color" ) _windecoBlendType=SolidColor; 1145 else _windecoBlendType=FollowStyleHint; 1146 1147 // shadow configurations 1148 _activeShadowConfiguration.initialize( _oxygen ); 1149 _inactiveShadowConfiguration.initialize( _oxygen ); 1150 1151 if(_kdeGlobals.getOption( "[General]", "widgetStyle" ).toVariant<std::string>("oxygen") == "oxygen transparent") 1152 { 1153 _backgroundOpacity = _oxygen.getOption( "[Common]", "BackgroundOpacity" ).toVariant<int>(255); 1154 1155 } else { 1156 1157 _backgroundOpacity = 255; 1158 1159 } 1160 1161 #if OXYGEN_DEBUG 1162 std::cerr << _activeShadowConfiguration << std::endl; 1163 std::cerr << _inactiveShadowConfiguration << std::endl; 1164 #endif 1165 1166 // copy relevant options to to gtk 1167 // scrollbar width 1168 _rc.setCurrentSection( Gtk::RC::defaultSection() ); 1169 _rc.addToCurrentSection( Gtk::RCOption<int>( 1170 " GtkScrollbar::slider-width", 1171 _oxygen.getOption( "[Style]", "ScrollBarWidth" ).toVariant<int>(15) + 1 ) ); 1172 1173 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-backward-stepper", _scrollBarSubLineButtons > 0 ) ); 1174 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-forward-stepper", _scrollBarAddLineButtons > 0 ) ); 1175 1176 // note the inversion for add and sub, due to the fact that kde options refer to the button location, and not its direction 1177 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-secondary-backward-stepper", _scrollBarAddLineButtons > 1 ) ); 1178 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-secondary-forward-stepper", _scrollBarSubLineButtons > 1 ) ); 1179 1180 // mnemonics 1181 GtkSettings* settings( gtk_settings_get_default() ); 1182 if( _oxygen.hasOption( "[Style]", "MnemonicsMode" ) ) 1183 { 1184 1185 const std::string mnemonicsMode( _oxygen.getOption( "[Style]", "MnemonicsMode" ).toVariant<std::string>("MN_ALWAYS") ); 1186 if( mnemonicsMode == "MN_NEVER" ) 1187 { 1188 1189 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", false, "oxygen-gtk" ); 1190 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1191 1192 } else if( mnemonicsMode == "MN_AUTO" ) { 1193 1194 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", true, "oxygen-gtk" ); 1195 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", true, "oxygen-gtk" ); 1196 1197 } else { 1198 1199 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", true, "oxygen-gtk" ); 1200 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1201 1202 } 1203 1204 } else { 1205 1206 // for backward compatibility 1207 const bool showMnemonics( _oxygen.getOption( "[Style]", "ShowMnemonics" ).toVariant<std::string>("true") == "true" ); 1208 if( showMnemonics ) 1209 { 1210 1211 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", true, "oxygen-gtk" ); 1212 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1213 1214 } else { 1215 1216 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", false, "oxygen-gtk" ); 1217 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1218 1219 } 1220 1221 } 1222 1223 } 1224 1225 //_________________________________________________________ 1226 void QtSettings::loadExtraOptions( void ) 1227 { 1228 1229 // deal with pathbar button margins 1230 // this needs to be done programatically in order to properly account for RTL locales 1231 _rc.addSection( "oxygen-pathbutton-internal", Gtk::RC::defaultSection() ); 1232 _rc.addToCurrentSection( " GtkButton::inner-border = { 2, 2, 1, 0 }" ); 1233 1234 if( gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL ) 1235 { 1236 1237 _rc.addToCurrentSection( " GtkToggleButton::inner-border={ 10, 0, 1, 0 }" ); 1238 1239 } else { 1240 1241 _rc.addToCurrentSection( " GtkToggleButton::inner-border={ 0, 10, 1, 0 }" ); 1242 1243 } 1244 1245 _rc.matchWidgetClassToSection( "*PathBar.GtkToggleButton", "oxygen-pathbutton-internal" ); 1246 1247 // entry margins 1248 _rc.addSection( "oxygen-entry-margins-internal", Gtk::RC::defaultSection() ); 1249 _rc.addToCurrentSection( Gtk::RCOption<int>( " xthickness", 5 ) ); 1250 _rc.addToCurrentSection( Gtk::RCOption<int>( " ythickness", applicationName().isXul() ? 2:1 ) ); 1251 _rc.matchClassToSection( "GtkEntry", "oxygen-entry-margins-internal" ); 1252 1253 // combobox buttons 1254 _rc.addSection( "oxygen-combobox-button-internal", Gtk::RC::defaultSection() ); 1255 _rc.addToCurrentSection( Gtk::RCOption<int>( " xthickness", 2 ) ); 1256 _rc.addToCurrentSection( Gtk::RCOption<int>( " ythickness", applicationName().isXul() ? 2:0 ) ); 1257 _rc.matchWidgetClassToSection( "*<GtkComboBox>.<GtkButton>", "oxygen-combobox-button-internal" ); 1258 1259 } 1260 1261 //_________________________________________________________ 1262 std::string QtSettings::sanitizePath( const std::string& path ) const 1263 { 1264 1265 std::string out( path ); 1266 size_t position( std::string::npos ); 1267 while( ( position = out.find( "//" ) ) != std::string::npos ) 1268 { out.replace( position, 2, "/" ); } 1269 1270 return out; 1271 } 1272 1273 //_________________________________________________________ 1274 void QtSettings::monitorFile( const std::string& filename ) 1275 { 1276 1277 // check if file was already added 1278 if( _monitoredFiles.find( filename ) != _monitoredFiles.end() ) 1279 { return; } 1280 1281 // check file existence 1282 if( !std::ifstream( filename.c_str() ) ) 1283 { return; } 1284 1285 // create FileMonitor 1286 FileMonitor monitor; 1287 monitor.file = g_file_new_for_path( filename.c_str() ); 1288 if( ( monitor.monitor = g_file_monitor( monitor.file, G_FILE_MONITOR_NONE, 0L, 0L ) ) ) 1289 { 1290 1291 // insert in map 1292 _monitoredFiles.insert( std::make_pair( filename, monitor ) ); 1293 1294 } else { 1295 1296 // clear file and return 1297 g_object_unref( monitor.file ); 1298 return; 1299 1300 } 1301 1302 } 1303 1304 //_________________________________________________________ 1305 void QtSettings::clearMonitoredFiles( void ) 1306 { 1307 for( FileMap::iterator iter = _monitoredFiles.begin(); iter != _monitoredFiles.end(); iter++ ) 1308 { 1309 iter->second.signal.disconnect(); 1310 g_object_unref( iter->second.file ); 1311 g_object_unref( iter->second.monitor ); 1312 } 1313 1314 _monitoredFiles.clear(); 1315 } 1316 1317 }