1 /* 2 * this file is part of the oxygen gtk engine 3 * Copyright (c) 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> 4 * Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or( at your option ) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free 18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 19 * MA 02110-1301, USA. 20 */ 21 22 #include "oxygenqtsettings.h" 23 #include "oxygencoloreffect.h" 24 #include "oxygencolorutils.h" 25 #include "oxygenfontinfo.h" 26 #include "oxygengtkicons.h" 27 #include "oxygengtkrc.h" 28 #include "oxygentimeline.h" 29 #include "config.h" 30 31 #include <glib.h> 32 #include <glib/gstdio.h> 33 #include <gtk/gtk.h> 34 35 #include <algorithm> 36 #include <cstdio> 37 #include <cstdlib> 38 #include <cstring> 39 #include <sys/stat.h> 40 #include <fstream> 41 #include <iostream> 42 #include <sstream> 43 44 namespace Oxygen 45 { 46 47 //_________________________________________________________ 48 const std::string QtSettings::_defaultKdeIconPath = "/usr/share/icons/"; 49 50 //_________________________________________________________ 51 /* 52 Note: the default values set in the constructor are actually ignored. 53 Real default values are set via Oxygen::QtSettings::loadKdeGlobalsOptions, 54 from the oxygenrc file provided with oxygen-gtk 55 */ QtSettings(void)56 QtSettings::QtSettings( void ): 57 _kdeIconTheme( "oxygen" ), 58 _kdeFallbackIconTheme( "gnome" ), 59 _inactiveChangeSelectionColor( false ), 60 _useIconEffect( true ), 61 _useBackgroundGradient( true ), 62 _checkBoxStyle( CS_CHECK ), 63 _tabStyle( TS_SINGLE ), 64 _scrollBarAddLineButtons( 2 ), 65 _scrollBarSubLineButtons( 1 ), 66 _toolBarDrawItemSeparator( true ), 67 _tooltipTransparent( true ), 68 _tooltipDrawStyledFrames( true ), 69 _viewDrawFocusIndicator( true ), 70 _viewDrawTreeBranchLines( true ), 71 _viewDrawTriangularExpander( true ), 72 _viewTriangularExpanderSize( ArrowSmall ), 73 _viewInvertSortIndicator( false ), 74 _menuHighlightMode( MM_DARK ), 75 _windowDragEnabled( true ), 76 _windowDragMode( WD_FULL ), 77 _useWMMoveResize( true ), 78 _startDragDist( 4 ), 79 _startDragTime( 500 ), 80 _animationsEnabled( true ), 81 _genericAnimationsEnabled( true ), 82 _menuBarAnimationType( Fade ), 83 _menuAnimationType( Fade ), 84 _toolBarAnimationType( Fade ), 85 _genericAnimationsDuration( 150 ), 86 _menuBarAnimationsDuration( 150 ), 87 _menuBarFollowMouseAnimationsDuration( 80 ), 88 _menuAnimationsDuration( 150 ), 89 _menuFollowMouseAnimationsDuration( 40 ), 90 _toolBarAnimationsDuration( 50 ), 91 _buttonSize( ButtonDefault ), 92 _frameBorder( BorderDefault ), 93 _windecoBlendType( FollowStyleHint ), 94 _activeShadowConfiguration( Palette::Active ), 95 _inactiveShadowConfiguration( Palette::Inactive ), 96 _backgroundOpacity( 255 ), 97 _argbEnabled( true ), 98 _initialized( false ), 99 _kdeColorsInitialized( false ), 100 _gtkColorsInitialized( false ), 101 _KDESession( false ) 102 {} 103 104 //_________________________________________________________ initialize(unsigned int flags)105 bool QtSettings::initialize( unsigned int flags ) 106 { 107 108 const bool forced( flags&Forced ); 109 110 // no attempt at initializing if gtk settings is not yet set 111 if( !gtk_settings_get_default() ) return false; 112 113 if( _initialized && !forced ) return false; 114 else if( !forced ) _initialized = true; 115 116 if( g_getenv( "KDE_FULL_SESSION" ) ) 117 { _KDESession = true; } 118 119 // init application name 120 if( flags & AppName ) 121 { 122 initUserConfigDir(); 123 initApplicationName(); 124 initArgb(); 125 } 126 127 // keep track of whats changed 128 bool changed( false ); 129 130 // configuration path 131 { 132 const PathList old( _kdeConfigPathList ); 133 _kdeConfigPathList = kdeConfigPathList(); 134 changed |= (old != _kdeConfigPathList ); 135 } 136 137 // icon path 138 { 139 const PathList old( _kdeIconPathList ); 140 _kdeIconPathList = kdeIconPathList(); 141 changed |= (old != _kdeIconPathList ); 142 } 143 144 // load kdeglobals and oxygen option maps 145 const bool kdeGlobalsChanged = loadKdeGlobals(); 146 const bool oxygenChanged = loadOxygen(); 147 148 // do nothing if settings not changed 149 if( forced && !(changed||kdeGlobalsChanged||oxygenChanged) ) return false; 150 151 // dialog button ordering 152 /* TODO: in principle this should be needed only once */ 153 if( flags & Extra ) 154 { 155 GtkSettings* settings( gtk_settings_get_default() ); 156 gtk_settings_set_long_property( settings, "gtk-alternative-button-order", 1, "oxygen-gtk" ); 157 } 158 159 // clear gtkrc 160 _rc.clear(); 161 162 // kde globals options 163 if( flags & KdeGlobals ) 164 { loadKdeGlobalsOptions(); } 165 166 // oxygen options 167 if( flags & Oxygen ) 168 { loadOxygenOptions(); } 169 170 #if !OXYGEN_FORCE_KDE_ICONS_AND_FONTS 171 // TODO: Add support for gtk schemes when not _KDESession 172 if( _KDESession ) 173 #endif 174 { 175 176 // reload fonts 177 if( flags & Fonts ) 178 { loadKdeFonts(); } 179 180 // reload icons 181 #if OXYGEN_ICON_HACK 182 if( flags & Icons ) 183 { loadKdeIcons(); } 184 #endif 185 186 } 187 188 // color palette 189 if( flags & Colors ) 190 { 191 loadKdePalette( forced ); 192 generateGtkColors(); 193 } 194 195 // apply extra programatically set metrics metrics 196 if( flags & Extra ) 197 { loadExtraOptions(); } 198 199 // print generated Gtkrc and commit 200 #if OXYGEN_DEBUG 201 std::cerr << "Oxygen::QtSettings::initialize - Gtkrc: " << std::endl; 202 std::cerr << _rc << std::endl; 203 #endif 204 205 // pass all resources to gtk and clear 206 _rc.commit(); 207 208 #if OXYGEN_DEBUG 209 std::cerr << "Oxygen::QtSettings::initialize - done. " << std::endl; 210 #endif 211 212 return true; 213 214 } 215 216 //_________________________________________________________ runCommand(const std::string & command,char * & result) const217 bool QtSettings::runCommand( const std::string& command, char*& result ) const 218 { return g_spawn_command_line_sync( command.c_str(), &result, 0L, 0L, 0L ) && result; } 219 220 //_________________________________________________________ loadKdeGlobals(void)221 bool QtSettings::loadKdeGlobals( void ) 222 { 223 224 // save backup 225 OptionMap old = _kdeGlobals; 226 227 // clear and reload 228 _kdeGlobals.clear(); 229 for( PathList::const_reverse_iterator iter = _kdeConfigPathList.rbegin(); iter != _kdeConfigPathList.rend(); ++iter ) 230 { 231 const std::string filename( sanitizePath( *iter + "/kdeglobals" ) ); 232 _kdeGlobals.merge( OptionMap( filename ) ); 233 monitorFile( filename ); 234 } 235 236 #if OXYGEN_DEBUG 237 std::cerr << "Oxygen::QtSettings::loadKdeGlobals - kdeglobals: " << std::endl; 238 std::cerr << _kdeGlobals << std::endl; 239 #endif 240 241 // check change 242 return old != _kdeGlobals; 243 244 } 245 246 //_________________________________________________________ loadOxygen(void)247 bool QtSettings::loadOxygen( void ) 248 { 249 250 // save backup 251 OptionMap old = _oxygen; 252 253 // clear and reload 254 _oxygen.clear(); 255 for( PathList::const_reverse_iterator iter = _kdeConfigPathList.rbegin(); iter != _kdeConfigPathList.rend(); ++iter ) 256 { 257 const std::string filename( sanitizePath( *iter + "/oxygenrc" ) ); 258 _oxygen.merge( filename ); 259 monitorFile( filename ); 260 } 261 262 #if OXYGEN_DEBUG 263 std::cerr << "Oxygen::QtSettings::loadOxygen - Oxygenrc: " << std::endl; 264 std::cerr << _oxygen << std::endl; 265 #endif 266 267 // check change 268 return old != _oxygen; 269 270 } 271 272 //_________________________________________________________ kdeConfigPathList(void) const273 PathList QtSettings::kdeConfigPathList( void ) const 274 { 275 276 PathList out; 277 278 // load icon install prefix 279 gchar* path = 0L; 280 if( runCommand( "kde4-config --path config", path ) && path ) 281 { 282 283 out.split( path ); 284 g_free( path ); 285 286 } else { 287 288 out.push_back( userConfigDir() ); 289 290 } 291 292 out.push_back( GTK_THEME_DIR ); 293 294 #if OXYGEN_DEBUG 295 std::cerr << "Oxygen::QtSettings::kdeConfigPathList - loading configuration from path: " << std::endl; 296 std::cerr << out << std::endl; 297 #endif 298 299 return out; 300 301 } 302 303 //_________________________________________________________ kdeIconPathList(void) const304 PathList QtSettings::kdeIconPathList( void ) const 305 { 306 307 // load icon install prefix 308 PathList out; 309 char* path = 0L; 310 if( runCommand( "kde4-config --path icon", path ) && path ) 311 { 312 out.split( path ); 313 g_free( path ); 314 } 315 316 // make sure defaultKdeIconPath is included in the list 317 if( std::find( out.begin(), out.end(), _defaultKdeIconPath ) == out.end() ) 318 { out.push_back( _defaultKdeIconPath ); } 319 320 return out; 321 322 } 323 324 //_________________________________________________________ initUserConfigDir(void)325 void QtSettings::initUserConfigDir( void ) 326 { 327 328 // create directory name 329 _userConfigDir = std::string( g_get_user_config_dir() ) + "/oxygen-gtk"; 330 331 // make sure that corresponding directory does exist 332 struct stat st; 333 if( stat( _userConfigDir.c_str(), &st ) != 0 ) 334 { 335 #ifdef G_OS_WIN32 336 // S_IRWXG and S_IRWXO are undefined on Windows, and g_mkdir() 337 // ignores its second parameter on Windows anyway. 338 g_mkdir( _userConfigDir.c_str(), 0 ); 339 #else 340 g_mkdir( _userConfigDir.c_str(), S_IRWXU|S_IRWXG|S_IRWXO ); 341 #endif 342 } 343 344 // note: in some cases, the target might exist and not be a directory 345 // nothing we can do about it. We won't overwrite the file to prevent dataloss 346 347 } 348 349 //_________________________________________________________ initArgb(void)350 void QtSettings::initArgb( void ) 351 { 352 // get program name 353 const char* appName = g_get_prgname(); 354 if( !appName ) return; 355 356 // user-defined configuration file 357 const std::string userConfig( userConfigDir() + "/argb-apps.conf"); 358 359 // make sure user configuration file exists 360 std::ofstream newConfig( userConfig.c_str(), std::ios::app ); 361 if( newConfig ) 362 { 363 // if the file is empty (newly created), put a hint there 364 if( !newConfig.tellp() ) 365 { newConfig << "# argb-apps.conf\n# Put your user-specific ARGB app settings here\n\n"; } 366 newConfig.close(); 367 368 } 369 370 // check for ARGB hack being disabled 371 if(g_getenv("OXYGEN_DISABLE_ARGB_HACK")) 372 { 373 std::cerr << "Oxygen::QtSettings::initArgb - ARGB hack is disabled; program name: " << appName << std::endl; 374 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; 375 _argbEnabled = false; 376 return; 377 } 378 379 // get debug flag from environement 380 const bool OXYGEN_ARGB_DEBUG = g_getenv("OXYGEN_ARGB_DEBUG"); 381 382 // read blacklist 383 // system-wide configuration file 384 const std::string configFile( std::string( GTK_THEME_DIR ) + "/argb-apps.conf" ); 385 std::ifstream systemIn( configFile.c_str() ); 386 if( !systemIn ) 387 { 388 389 if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) ) 390 { std::cerr << "Oxygen::QtSettings::initArgb - ARGB config file \"" << configFile << "\" not found" << std::endl; } 391 392 } 393 394 // load options into a string 395 std::string contents; 396 std::vector<std::string> lines; 397 while( std::getline( systemIn, contents, '\n' ) ) 398 { 399 if( contents.empty() || contents[0] == '#' ) continue; 400 lines.push_back( contents ); 401 } 402 403 // user specific blacklist 404 std::ifstream userIn( userConfig.c_str() ); 405 if( !userIn ) 406 { 407 408 if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) ) 409 { std::cerr << "Oxygen::QtSettings::initArgb - user-defined ARGB config file \"" << userConfig << "\" not found - only system-wide one will be used" << std::endl; } 410 411 } 412 413 // load options into a string 414 while( std::getline( userIn, contents, '\n' ) ) 415 { 416 if( contents.empty() || contents[0] == '#' ) continue; 417 lines.push_back( contents ); 418 } 419 420 // true if application was found in one of the lines 421 bool found( false ); 422 for( std::vector<std::string>::const_reverse_iterator iter = lines.rbegin(); iter != lines.rend() && !found; ++iter ) 423 { 424 425 // store line locally 426 std::string contents( *iter ); 427 428 // split string using ":" as a delimiter 429 std::vector<std::string> appNames; 430 size_t position( std::string::npos ); 431 while( ( position = contents.find( ':' ) ) != std::string::npos ) 432 { 433 std::string appName( contents.substr(0, position ) ); 434 if( !appName.empty() ) { appNames.push_back( appName ); } 435 contents = contents.substr( position+1 ); 436 } 437 438 if( !contents.empty() ) appNames.push_back( contents ); 439 if( appNames.empty() ) continue; 440 441 // check line type 442 bool enabled( true ); 443 if( appNames[0] == "enable" ) enabled = true; 444 else if( appNames[0] == "disable" ) enabled = false; 445 else continue; 446 447 // compare application names to this application 448 for( unsigned int i = 1; i < appNames.size(); i++ ) 449 { 450 if( appNames[i] == "all" || appNames[i] == appName ) 451 { 452 found = true; 453 _argbEnabled = enabled; 454 break; 455 } 456 } 457 458 } 459 460 } 461 462 //_________________________________________________________ addIconTheme(PathList & pathList,const std::string & theme)463 void QtSettings::addIconTheme( PathList& pathList, const std::string& theme ) 464 { 465 466 // do nothing if theme have already been included in the loop 467 if( _iconThemes.find( theme ) != _iconThemes.end() ) return; 468 _iconThemes.insert( theme ); 469 470 #if OXYGEN_DEBUG 471 std::cerr << "Oxygen::QtSettings::addIconTheme - adding " << theme << std::endl; 472 #endif 473 474 // add all possible path (based on _kdeIconPathList) and look for possible parent 475 std::string parentTheme; 476 for( PathList::const_iterator iter = _kdeIconPathList.begin(); iter != _kdeIconPathList.end(); ++iter ) 477 { 478 479 // create path and check for existence 480 std::string path( sanitizePath( *iter + '/' + theme ) ); 481 struct stat st; 482 if( stat( path.c_str(), &st ) != 0 ) continue; 483 484 // add to path list 485 pathList.push_back( path ); 486 if( parentTheme.empty() ) 487 { 488 const std::string index( sanitizePath( *iter + '/' + theme + "/index.theme" ) ); 489 OptionMap themeOptions( index ); 490 parentTheme = themeOptions.getValue( "[Icon Theme]", "Inherits" ); 491 } 492 493 } 494 495 // add parent if needed 496 if( !parentTheme.empty() ) 497 { 498 // split using "," as a separator 499 PathList parentThemes( parentTheme, "," ); 500 for( PathList::const_iterator iter = parentThemes.begin(); iter != parentThemes.end(); ++iter ) 501 { addIconTheme( pathList, *iter ); } 502 } 503 504 return; 505 506 } 507 508 //_________________________________________________________ loadKdeIcons(void)509 void QtSettings::loadKdeIcons( void ) 510 { 511 512 // update icon search path 513 // put existing default path in a set 514 PathSet searchPath( defaultIconSearchPath() ); 515 516 // add kde's path. Loop is reversed because added path must be prepended. 517 for( PathList::const_reverse_iterator iter = _kdeIconPathList.rbegin(); iter != _kdeIconPathList.rend(); ++iter ) 518 { 519 520 // remove trailing backslash, if any 521 std::string path( *iter ); 522 if( path.empty() ) continue; 523 if( path[path.size()-1] == '/' ) path = path.substr( 0, path.size()-1 ); 524 525 // check if already present and prepend if not 526 if( searchPath.find( path ) == searchPath.end() ) 527 { gtk_icon_theme_prepend_search_path(gtk_icon_theme_get_default(), path.c_str() ); } 528 } 529 530 // load icon theme and path to gtk 531 _iconThemes.clear(); 532 _kdeIconTheme = _kdeGlobals.getValue( "[Icons]", "Theme", "oxygen" ); 533 534 // store to settings 535 GtkSettings* settings( gtk_settings_get_default() ); 536 537 gtk_settings_set_string_property( settings, "gtk-icon-theme-name", _kdeIconTheme.c_str(), "oxygen-gtk" ); 538 gtk_settings_set_string_property( settings, "gtk-fallback-icon-theme-name", _kdeFallbackIconTheme.c_str(), "oxygen-gtk" ); 539 540 // load icon sizes from kde 541 // const int desktopIconSize( _kdeGlobals.getOption( "[DesktopIcons]", "Size" ).toInt( 48 ) ); 542 const int dialogIconSize( _kdeGlobals.getOption( "[DialogIcons]", "Size" ).toInt( 32 ) ); 543 const int panelIconSize( _kdeGlobals.getOption( "[PanelIcons]", "Size" ).toInt( 32 ) ); 544 const int mainToolbarIconSize( _kdeGlobals.getOption( "[MainToolbarIcons]", "Size" ).toInt( 22 ) ); 545 const int smallIconSize( _kdeGlobals.getOption( "[SmallIcons]", "Size" ).toInt( 16 ) ); 546 const int toolbarIconSize( _kdeGlobals.getOption( "[ToolbarIcons]", "Size" ).toInt( 22 ) ); 547 548 // set gtk icon sizes 549 _icons.setIconSize( "panel-menu", smallIconSize ); 550 _icons.setIconSize( "panel", panelIconSize ); 551 _icons.setIconSize( "gtk-small-toolbar", toolbarIconSize ); 552 _icons.setIconSize( "gtk-large-toolbar", mainToolbarIconSize ); 553 _icons.setIconSize( "gtk-dnd", mainToolbarIconSize ); 554 _icons.setIconSize( "gtk-button", smallIconSize ); 555 _icons.setIconSize( "gtk-menu", smallIconSize ); 556 _icons.setIconSize( "gtk-dialog", dialogIconSize ); 557 _icons.setIconSize( "", smallIconSize ); 558 559 // load translation table, generate full translation list, and path to gtk 560 _icons.loadTranslations( sanitizePath( std::string( GTK_THEME_DIR ) + "/icons4" ) ); 561 562 // generate full path list 563 PathList iconThemeList; 564 addIconTheme( iconThemeList, _kdeIconTheme ); 565 addIconTheme( iconThemeList, _kdeFallbackIconTheme ); 566 567 _rc.merge( _icons.generate( iconThemeList ) ); 568 569 } 570 571 //_________________________________________________________ defaultIconSearchPath(void) const572 PathSet QtSettings::defaultIconSearchPath( void ) const 573 { 574 PathSet searchPath; 575 576 // load icon theme 577 GtkIconTheme* theme( gtk_icon_theme_get_default() ); 578 if( !GTK_IS_ICON_THEME( theme ) ) return searchPath; 579 580 // get default 581 gchar** gtkSearchPath; 582 int nElements; 583 584 gtk_icon_theme_get_search_path( theme, >kSearchPath, &nElements ); 585 for( int i=0; i<nElements; i++ ) 586 { searchPath.insert( gtkSearchPath[i] ); } 587 588 // free 589 g_strfreev( gtkSearchPath ); 590 591 return searchPath; 592 } 593 594 //_________________________________________________________ loadKdePalette(bool forced)595 void QtSettings::loadKdePalette( bool forced ) 596 { 597 598 if( _kdeColorsInitialized && !forced ) return; 599 _kdeColorsInitialized = true; 600 601 // contrast 602 ColorUtils::setContrast( _kdeGlobals.getOption( "[KDE]", "contrast" ).toVariant<double>( 7 ) / 10 ); 603 604 // palette 605 _palette.clear(); 606 _palette.setColor( Palette::Active, Palette::Window, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Window]", "BackgroundNormal" ) ) ); 607 _palette.setColor( Palette::Active, Palette::WindowText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Window]", "ForegroundNormal" ) ) ); 608 609 _palette.setColor( Palette::Active, Palette::Button, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Button]", "BackgroundNormal" ) ) ); 610 _palette.setColor( Palette::Active, Palette::ButtonText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Button]", "ForegroundNormal" ) ) ); 611 612 _palette.setColor( Palette::Active, Palette::Selected, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Selection]", "BackgroundNormal" ) ) ); 613 _palette.setColor( Palette::Active, Palette::SelectedText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Selection]", "ForegroundNormal" ) ) ); 614 615 _palette.setColor( Palette::Active, Palette::Tooltip, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Tooltip]", "BackgroundNormal" ) ) ); 616 _palette.setColor( Palette::Active, Palette::TooltipText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:Tooltip]", "ForegroundNormal" ) ) ); 617 618 _palette.setColor( Palette::Active, Palette::Focus, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "DecorationFocus" ) ) ); 619 _palette.setColor( Palette::Active, Palette::Hover, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "DecorationHover" ) ) ); 620 621 _palette.setColor( Palette::Active, Palette::Base, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "BackgroundNormal" ) ) ); 622 _palette.setColor( Palette::Active, Palette::BaseAlternate, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "BackgroundAlternate" ) ) ); 623 _palette.setColor( Palette::Active, Palette::Text, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "ForegroundNormal" ) ) ); 624 _palette.setColor( Palette::Active, Palette::NegativeText, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[Colors:View]", "ForegroundNegative" ) ) ); 625 626 _palette.setColor( Palette::Active, Palette::ActiveWindowBackground, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[WM]", "activeBackground" ) ) ); 627 _palette.setColor( Palette::Active, Palette::InactiveWindowBackground, ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( "[WM]", "inactiveBackground" ) ) ); 628 629 // load effects 630 const ColorUtils::Effect disabledEffect( Palette::Disabled, _kdeGlobals ); 631 const ColorUtils::Effect inactiveEffect( Palette::Inactive, _kdeGlobals ); 632 633 // generate inactive and disabled palette from active, applying effects from kdeglobals 634 _inactiveChangeSelectionColor = ( _kdeGlobals.getOption( "[ColorEffects:Inactive]", "ChangeSelectionColor" ).toVariant<std::string>( "false" ) == "true" ); 635 _palette.generate( Palette::Active, Palette::Inactive, inactiveEffect, _inactiveChangeSelectionColor ); 636 _palette.generate( Palette::Active, Palette::Disabled, disabledEffect ); 637 638 #if OXYGEN_DEBUG 639 std::cerr << "Oxygen::QtSettings::loadKdePalette - disabled effect: " << std::endl; 640 std::cerr << disabledEffect << std::endl; 641 642 std::cerr << "Oxygen::QtSettings::loadKdePalette - inactive effect: " << std::endl; 643 std::cerr << inactiveEffect << std::endl; 644 645 std::cerr << "Oxygen::QtSettings::loadKdePalette - palette: " << std::endl; 646 std::cerr << _palette << std::endl; 647 #endif 648 649 } 650 651 //_________________________________________________________ generateGtkColors(void)652 void QtSettings::generateGtkColors( void ) 653 { 654 655 #if OXYGEN_DEBUG 656 std::cerr << "Oxygen::QtSettings::generateGtkColors" << std::endl; 657 #endif 658 659 // customize gtk palette 660 _palette.setGroup( Palette::Active ); 661 662 // default colors 663 _rc.setCurrentSection( Gtk::RC::defaultSection() ); 664 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Window ) ) ); 665 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[PRELIGHT]", _palette.color( Palette::Window ) ) ); 666 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[ACTIVE]", _palette.color( Palette::Window ) ) ); 667 668 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[SELECTED]", _palette.color( Palette::Selected ) ) ); 669 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[INSENSITIVE]", _palette.color( Palette::Window ) ) ); 670 671 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::WindowText ) ) ); 672 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 673 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 674 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[SELECTED]", _palette.color( Palette::WindowText ) ) ); 675 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::WindowText ) ) ); 676 677 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[NORMAL]", _palette.color( Palette::Base ) ) ); 678 679 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[ACTIVE]", _palette.color( Palette::Inactive, Palette::Selected ) ) ); 680 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[PRELIGHT]", _palette.color( Palette::Base ) ) ); 681 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[SELECTED]", _palette.color( Palette::Selected ) ) ); 682 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Base ) ) ); 683 684 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::Text ) ) ); 685 686 if( _inactiveChangeSelectionColor ) _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::Text ) ) ); 687 else _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::SelectedText ) ) ); 688 689 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::Text ) ) ); 690 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[SELECTED]", _palette.color( Palette::SelectedText ) ) ); 691 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Text ) ) ); 692 addLinkColors( "[Colors:Window]" ); 693 694 // buttons 695 _rc.addSection( "oxygen-buttons-internal", Gtk::RC::defaultSection() ); 696 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Button ) ) ); 697 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[ACTIVE]", _palette.color( Palette::Button ) ) ); 698 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[PRELIGHT]", _palette.color( Palette::Button ) ) ); 699 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Button ) ) ); 700 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::ButtonText ) ) ); 701 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::ButtonText ) ) ); 702 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::ButtonText ) ) ); 703 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::ButtonText ) ) ); 704 addLinkColors( "[Colors:Button]" ); 705 706 _rc.matchClassToSection( "*Button", "oxygen-buttons-internal" ); 707 _rc.matchClassToSection( "GtkOptionMenu", "oxygen-buttons-internal" ); 708 _rc.matchWidgetClassToSection( "*<GtkButton>.<GtkLabel>", "oxygen-buttons-internal" ); 709 _rc.matchWidgetClassToSection( "*<GtkButton>.<GtkAlignment>.<GtkBox>.<GtkLabel>", "oxygen-buttons-internal" ); 710 711 // combobox 712 _rc.addSection( "oxygen-combobox-internal", "oxygen-buttons-internal" ); 713 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::ButtonText ) ) ); 714 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::ButtonText ) ) ); 715 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::ButtonText ) ) ); 716 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::ButtonText ) ) ); 717 _rc.matchWidgetClassToSection( "*<GtkComboBox>.*<GtkCellView>", "oxygen-combobox-internal" ); 718 719 // checkboxes and radio buttons 720 _rc.addSection( "oxygen-checkbox-buttons-internal", "oxygen-buttons-internal" ); 721 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::WindowText ) ) ); 722 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 723 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 724 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::WindowText ) ) ); 725 _rc.matchWidgetClassToSection( "*<GtkCheckButton>.<GtkLabel>", "oxygen-checkbox-buttons-internal" ); 726 727 // progressbar labels 728 _rc.addSection( "oxygen-progressbar-internal", Gtk::RC::defaultSection() ); 729 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::WindowText ) ) ); 730 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 731 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 732 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::WindowText ) ) ); 733 734 _rc.matchClassToSection( "GtkProgressBar", "oxygen-progressbar-internal" ); 735 736 // menu items 737 _rc.addSection( "oxygen-menubar-item-internal", "oxygen-menu-font-internal" ); 738 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[NORMAL]", _palette.color( Palette::Text ) ) ); 739 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::WindowText ) ) ); 740 741 if( _menuHighlightMode == MM_STRONG ) 742 { 743 744 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::Text ) ) ); 745 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[SELECTED]", _palette.color( Palette::SelectedText ) ) ); 746 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::SelectedText ) ) ); 747 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 748 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[SELECTED]", _palette.color( Palette::SelectedText ) ) ); 749 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::SelectedText ) ) ); 750 751 } else { 752 753 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::Text ) ) ); 754 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[SELECTED]", _palette.color( Palette::Text ) ) ); 755 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[ACTIVE]", _palette.color( Palette::Text ) ) ); 756 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::WindowText ) ) ); 757 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[SELECTED]", _palette.color( Palette::WindowText ) ) ); 758 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[ACTIVE]", _palette.color( Palette::WindowText ) ) ); 759 760 } 761 _rc.matchWidgetClassToSection( "*<GtkMenuItem>.<GtkLabel>", "oxygen-menubar-item-internal" ); 762 763 764 if( _menuHighlightMode == MM_STRONG ) 765 { 766 _rc.addSection( "oxygen-menu-item-internal", "oxygen-menubar-item-internal" ); 767 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " text[PRELIGHT]", _palette.color( Palette::SelectedText ) ) ); 768 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[PRELIGHT]", _palette.color( Palette::SelectedText ) ) ); 769 _rc.matchWidgetClassToSection( "*<GtkMenu>.<GtkMenuItem>.<GtkLabel>", "oxygen-menu-item-internal" ); 770 } 771 772 // text entries 773 _rc.addSection( "oxygen-entry-internal", Gtk::RC::defaultSection() ); 774 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Base ) ) ); 775 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Base ) ) ); 776 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " base[INSENSITIVE]", _palette.color( Palette::Disabled, Palette::Base ) ) ); 777 addLinkColors( "[Colors:View]" ); 778 _rc.matchClassToSection( "GtkSpinButton", "oxygen-entry-internal" ); 779 _rc.matchClassToSection( "GtkEntry", "oxygen-entry-internal" ); 780 _rc.matchClassToSection( "GtkTextView", "oxygen-entry-internal" ); 781 _rc.matchWidgetClassToSection( "*<GtkComboBoxEntry>.<GtkButton>", "oxygen-entry-internal" ); 782 _rc.matchWidgetClassToSection( "*<GtkCombo>.<GtkButton>", "oxygen-entry-internal" ); 783 784 // tooltips 785 _rc.addSection( "oxygen-tooltips-internal", Gtk::RC::defaultSection() ); 786 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " bg[NORMAL]", _palette.color( Palette::Tooltip ) ) ); 787 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " fg[NORMAL]", _palette.color( Palette::TooltipText ) ) ); 788 _rc.addToCurrentSection( Gtk::RCOption<int>( " xthickness", 3 ) ); 789 _rc.addToCurrentSection( Gtk::RCOption<int>( " ythickness", 3 ) ); 790 addLinkColors( "[Colors:Tooltip]" ); 791 792 _rc.matchWidgetToSection( "gtk-tooltip*", "oxygen-tooltips-internal" ); 793 794 // special case for google chrome 795 /* based on http://code.google.com/p/chromium/wiki/LinuxGtkThemeIntegration */ 796 _rc.addSection( "oxygen-chrome-gtk-frame-internal", Gtk::RC::defaultSection() ); 797 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " ChromeGtkFrame::frame-color", _palette.color( Palette::Window ) ) ); 798 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " ChromeGtkFrame::inactive-frame-color", _palette.color( Palette::Window ) ) ); 799 _rc.matchClassToSection( "ChromeGtkFrame", "oxygen-chrome-gtk-frame-internal" ); 800 801 } 802 803 804 //_________________________________________________________ addLinkColors(const std::string & section)805 void QtSettings::addLinkColors( const std::string& section ) 806 { 807 808 { 809 // link colors 810 // from http://ubuntuforums.org/showthread.php?p=7009302 811 const ColorUtils::Rgba linkColor( ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( section, "ForegroundLink" ) ) ); 812 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkWidget::link-color", linkColor ) ); 813 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkHTML::alink_color", linkColor ) ); 814 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkHTML::link_color", linkColor ) ); 815 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GnomeHref::link-color", linkColor ) ); 816 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkIMHtml::hyperlink-color", linkColor ) ); 817 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkIMHtml::hyperlink-prelight-color", linkColor ) ); 818 } 819 820 { 821 // visited link colors 822 // from http://ubuntuforums.org/showthread.php?p=7009302 823 const ColorUtils::Rgba visitedLinkColor( ColorUtils::Rgba::fromKdeOption( _kdeGlobals.getValue( section, "ForegroundVisited" ) ) ); 824 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkWidget::visited-link-color", visitedLinkColor ) ); 825 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " GtkHTML::vlink_color", visitedLinkColor ) ); 826 } 827 828 } 829 830 //_________________________________________________________ loadKdeFonts(void)831 void QtSettings::loadKdeFonts( void ) 832 { 833 834 // try load default font 835 FontInfo::Map fonts; 836 FontInfo defaultFont; 837 if( _kdeGlobals.hasOption( "[General]", "font" ) ) 838 { 839 840 defaultFont = FontInfo::fromKdeOption( _kdeGlobals.getValue( "[General]", "font", "" ) ); 841 842 } else { 843 844 #if OXYGEN_DEBUG 845 std::cerr << "Oxygen::QtSettings::loadKdeFonts - cannot load default font" << std::endl; 846 #endif 847 848 } 849 850 fonts[FontInfo::Default] = defaultFont; 851 852 // load extra fonts 853 typedef std::map<FontInfo::FontType, std::string> FontNameMap; 854 FontNameMap optionNames; 855 optionNames.insert( std::make_pair( FontInfo::Desktop, "desktopFont" ) ); 856 optionNames.insert( std::make_pair( FontInfo::Fixed, "fixed" ) ); 857 optionNames.insert( std::make_pair( FontInfo::Menu, "menuFont" ) ); 858 optionNames.insert( std::make_pair( FontInfo::ToolBar, "toolBarFont" ) ); 859 for( FontNameMap::const_iterator iter = optionNames.begin(); iter != optionNames.end(); ++iter ) 860 { 861 FontInfo local; 862 if( _kdeGlobals.hasOption( "[General]", iter->second ) ) 863 { 864 865 local = FontInfo::fromKdeOption( _kdeGlobals.getValue( "[General]", iter->second, "" ) ); 866 867 } else { 868 869 #if OXYGEN_DEBUG 870 std::cerr << "Oxygen::QtSettings::loadKdeFonts - cannot load font named " << iter->second << std::endl; 871 #endif 872 local = defaultFont; 873 874 } 875 876 // store in map 877 fonts[iter->first] = local; 878 879 } 880 881 // pass fonts to RC 882 if( fonts[FontInfo::Default].isValid() ) 883 { 884 // pass to settings 885 GtkSettings* settings( gtk_settings_get_default() ); 886 gtk_settings_set_string_property( settings, "gtk-font-name", fonts[FontInfo::Default].toString( false ).c_str(), "oxygen-gtk" ); 887 888 _rc.setCurrentSection( Gtk::RC::defaultSection() ); 889 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " font_name", fonts[FontInfo::Default].toString() ) ); 890 } 891 892 if( fonts[FontInfo::Menu].isValid() ) 893 { 894 _rc.addSection( "oxygen-menu-font-internal", Gtk::RC::defaultSection() ); 895 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " font_name", fonts[FontInfo::Menu].toString() ) ); 896 _rc.matchWidgetClassToSection( "*<GtkMenuItem>.<GtkLabel>", "oxygen-menu-font-internal" ); 897 } 898 899 if( fonts[FontInfo::ToolBar].isValid() ) 900 { 901 _rc.addSection( "oxygen-toolbar-font-internal", Gtk::RC::defaultSection() ); 902 _rc.addToCurrentSection( Gtk::RCOption<std::string>( " font_name", fonts[FontInfo::ToolBar].toString() ) ); 903 _rc.matchWidgetClassToSection( "*<GtkToolbar>.*", "oxygen-toolbar-font-internal" ); 904 } 905 906 // don't check for section and tag presence - use default font if not present 907 _WMFont=FontInfo::fromKdeOption( _kdeGlobals.getValue( "[WM]", "activeFont", "Sans Serif,8,-1,5,50,0,0,0,0,0" ) ); 908 909 } 910 911 //_________________________________________________________ loadKdeGlobalsOptions(void)912 void QtSettings::loadKdeGlobalsOptions( void ) 913 { 914 915 #if OXYGEN_DEBUG 916 std::cerr << "Oxygen::QtSettings::loadKdeGlobalsOptions" << std::endl; 917 #endif 918 919 // toolbar style 920 const std::string toolbarTextPosition( _kdeGlobals.getOption( "[Toolbar style]", "ToolButtonStyle" ).toVariant<std::string>( "TextBelowIcon" ) ); 921 GtkToolbarStyle toolbarStyle( GTK_TOOLBAR_BOTH ); 922 if( toolbarTextPosition == "TextOnly" ) toolbarStyle = GTK_TOOLBAR_TEXT; 923 else if( toolbarTextPosition == "TextBesideIcon" ) toolbarStyle = GTK_TOOLBAR_BOTH_HORIZ; 924 else if( toolbarTextPosition == "NoText" ) toolbarStyle = GTK_TOOLBAR_ICONS; 925 926 GtkSettings* settings( gtk_settings_get_default() ); 927 gtk_settings_set_long_property( settings, "gtk-toolbar-style", toolbarStyle, "oxygen-gtk" ); 928 929 // icons on buttons 930 if( _kdeGlobals.getValue( "[KDE]", "ShowIconsOnPushButtons", "true" ) == "false" ) 931 { gtk_settings_set_long_property( settings, "gtk-button-images", 0, "oxygen-gtk" ); } 932 933 // active icon effects 934 _useIconEffect = _kdeGlobals.getOption( "[MainToolbarIcons]", "ActiveEffect" ).toVariant<std::string>( "gamma" ) != "none"; 935 936 // start drag time and distance 937 _startDragDist = _kdeGlobals.getOption( "[KDE]", "StartDragDist" ).toVariant<int>( 4 ); 938 _startDragTime = _kdeGlobals.getOption( "[KDE]", "StartDragTime" ).toVariant<int>( 500 ); 939 940 } 941 942 //_________________________________________________________ loadOxygenOptions(void)943 void QtSettings::loadOxygenOptions( void ) 944 { 945 946 // background pixmap 947 _backgroundPixmap = _oxygen.getValue( "[Common]", "BackgroundPixmap", "" ); 948 949 // background gradient 950 _useBackgroundGradient = ( _oxygen.getValue( "[Common]", "UseBackgroundGradient", "true" ) == "true" ); 951 952 // checkbox style 953 _checkBoxStyle = (_oxygen.getValue( "[Style]", "CheckBoxStyle", "CS_CHECK" ) == "CS_CHECK") ? CS_CHECK:CS_X; 954 955 // checkbox style 956 _tabStyle = (_oxygen.getValue( "[Style]", "TabStyle", "TS_SINGLE" ) == "TS_SINGLE") ? TS_SINGLE:TS_PLAIN; 957 958 // scrollbar buttons 959 _scrollBarAddLineButtons = _oxygen.getOption( "[Style]", "ScrollBarAddLineButtons" ).toVariant<int>( 2 ); 960 _scrollBarSubLineButtons = _oxygen.getOption( "[Style]", "ScrollBarSubLineButtons" ).toVariant<int>( 1 ); 961 962 // toolbar separators 963 _toolBarDrawItemSeparator = _oxygen.getOption( "[Style]", "ToolBarDrawItemSeparator" ).toVariant<std::string>("true") == "true"; 964 965 // tooltips 966 _tooltipTransparent = _oxygen.getOption( "[Style]", "ToolTipTransparent" ).toVariant<std::string>("true") == "true"; 967 _tooltipDrawStyledFrames = _oxygen.getOption( "[Style]", "ToolTipDrawStyledFrames" ).toVariant<std::string>("true") == "true"; 968 969 // focus indicator in views 970 _viewDrawFocusIndicator = _oxygen.getOption( "[Style]", "ViewDrawFocusIndicator" ).toVariant<std::string>("true") == "true"; 971 972 // tree branch lines 973 _viewDrawTreeBranchLines = _oxygen.getOption( "[Style]", "ViewDrawTreeBranchLines" ).toVariant<std::string>("true") == "true"; 974 975 // triangular expanders 976 _viewDrawTriangularExpander = _oxygen.getOption( "[Style]", "ViewDrawTriangularExpander" ).toVariant<std::string>("true") == "true"; 977 978 // triangular expander (arrow) size 979 std::string expanderSize( _oxygen.getOption( "[Style]", "ViewTriangularExpanderSize" ).toVariant<std::string>("TE_SMALL") ); 980 if( expanderSize == "TE_NORMAL" ) _viewTriangularExpanderSize = ArrowNormal; 981 else if( expanderSize == "TE_TINY" ) _viewTriangularExpanderSize = ArrowTiny; 982 else _viewTriangularExpanderSize = ArrowSmall; 983 984 // invert view sort indicators 985 _viewInvertSortIndicator = _oxygen.getOption( "[Style]", "ViewInvertSortIndicator" ).toVariant<std::string>("false") == "true"; 986 987 // menu highlight mode 988 std::string highlightMode( _oxygen.getOption( "[Style]", "MenuHighlightMode" ).toVariant<std::string>("MM_DARK") ); 989 if( highlightMode == "MM_SUBTLE" ) _menuHighlightMode = MM_SUBTLE; 990 else if( highlightMode == "MM_STRONG" ) _menuHighlightMode = MM_STRONG; 991 else _menuHighlightMode = MM_DARK; 992 993 // window drag mode 994 _windowDragEnabled = _oxygen.getOption( "[Style]", "WindowDragEnabled" ).toVariant<std::string>("true") == "true"; 995 996 std::string windowDragMode( _oxygen.getOption( "[Style]", "WindowDragMode" ).toVariant<std::string>("WD_FULL") ); 997 if( windowDragMode == "WD_MINIMAL" ) _windowDragMode = WD_MINIMAL; 998 else _windowDragMode = WD_FULL; 999 1000 // use window manager to handle window drag 1001 _useWMMoveResize = _oxygen.getOption( "[Style]", "UseWMMoveResize" ).toVariant<std::string>("true") == "true"; 1002 1003 // animations 1004 _animationsEnabled = ( _oxygen.getOption( "[Style]", "AnimationsEnabled" ).toVariant<std::string>("true") == "true" ); 1005 _genericAnimationsEnabled = ( _oxygen.getOption( "[Style]", "GenericAnimationsEnabled" ).toVariant<std::string>("true") == "true" ); 1006 1007 // menubar animation type 1008 std::string menuBarAnimationType( _oxygen.getValue( "[Style]", "MenuBarAnimationType", "MB_FADE") ); 1009 if( menuBarAnimationType == "MB_NONE" ) _menuBarAnimationType = NoAnimation; 1010 else if( menuBarAnimationType == "MB_FADE" ) _menuBarAnimationType = Fade; 1011 else if( menuBarAnimationType == "MB_FOLLOW_MOUSE" ) _menuBarAnimationType = FollowMouse; 1012 1013 // menubar animation type 1014 std::string menuAnimationType( _oxygen.getValue( "[Style]", "MenuAnimationType", "ME_FADE") ); 1015 if( menuAnimationType == "ME_NONE" ) _menuAnimationType = NoAnimation; 1016 else if( menuAnimationType == "ME_FADE" ) _menuAnimationType = Fade; 1017 else if( menuAnimationType == "ME_FOLLOW_MOUSE" ) _menuAnimationType = FollowMouse; 1018 1019 // toolbar animation type 1020 std::string toolBarAnimationType( _oxygen.getValue( "[Style]", "ToolBarAnimationType", "TB_FADE") ); 1021 if( toolBarAnimationType == "TB_NONE" ) _toolBarAnimationType = NoAnimation; 1022 else if( toolBarAnimationType == "TB_FADE" ) _toolBarAnimationType = Fade; 1023 else if( toolBarAnimationType == "TB_FOLLOW_MOUSE" ) _toolBarAnimationType = FollowMouse; 1024 1025 // animations duration 1026 _genericAnimationsDuration = _oxygen.getOption( "[Style]", "GenericAnimationsDuration" ).toVariant<int>(150); 1027 _menuBarAnimationsDuration = _oxygen.getOption( "[Style]", "MenuBarAnimationsDuration" ).toVariant<int>(150); 1028 _menuBarFollowMouseAnimationsDuration = _oxygen.getOption( "[Style]", "MenuBarFollowMouseAnimationsDuration" ).toVariant<int>(80); 1029 _menuAnimationsDuration = _oxygen.getOption( "[Style]", "MenuAnimationsDuration" ).toVariant<int>(150); 1030 _menuFollowMouseAnimationsDuration = _oxygen.getOption( "[Style]", "MenuFollowMouseAnimationsDuration" ).toVariant<int>(40); 1031 _toolBarAnimationsDuration = _oxygen.getOption( "[Style]", "ToolBarAnimationsDuration" ).toVariant<int>(50); 1032 1033 // animation steps 1034 TimeLine::setSteps( _oxygen.getOption( "[Style]", "AnimationSteps" ).toVariant<int>( 10 ) ); 1035 1036 // window decoration button size 1037 std::string buttonSize( _oxygen.getValue( "[Windeco]", "ButtonSize", "Normal") ); 1038 if( buttonSize == "Small" ) _buttonSize = ButtonSmall; 1039 else if( buttonSize == "Large" ) _buttonSize = ButtonLarge; 1040 else if( buttonSize == "Very Large" ) _buttonSize = ButtonVeryLarge; 1041 else if( buttonSize == "Huge" ) _buttonSize = ButtonHuge; 1042 else _buttonSize = ButtonDefault; 1043 1044 // window decoration frame border size 1045 std::string frameBorder( _oxygen.getValue( "[Windeco]", "FrameBorder", "Normal") ); 1046 if( frameBorder == "No Border" ) _frameBorder = BorderNone; 1047 else if( frameBorder == "No Side Border" ) _frameBorder = BorderNoSide; 1048 else if( frameBorder == "Tiny" ) _frameBorder = BorderTiny; 1049 else if( frameBorder == "Large" ) _frameBorder = BorderLarge; 1050 else if( frameBorder == "Very Large" ) _frameBorder = BorderVeryLarge; 1051 else if( frameBorder == "Huge" ) _frameBorder = BorderHuge; 1052 else if( frameBorder == "Very Huge" ) _frameBorder = BorderVeryHuge; 1053 else if( frameBorder == "Oversized" ) _frameBorder = BorderOversized; 1054 else _frameBorder = BorderDefault; 1055 1056 // window decoration title alignment 1057 std::string titleAlign( _oxygen.getValue( "[Windeco]", "TitleAlignment", "Center" ) ); 1058 if( titleAlign == "Left" ) _titleAlignment = PANGO_ALIGN_LEFT; 1059 else if( titleAlign == "Center" ) _titleAlignment = PANGO_ALIGN_CENTER; 1060 else if( titleAlign == "Right" ) _titleAlignment = PANGO_ALIGN_RIGHT; 1061 else _titleAlignment = PANGO_ALIGN_CENTER; 1062 1063 // Windeco radial gradient enable option 1064 std::string wdBlendType( _oxygen.getValue( "[Windeco]", "BlendColor", "Follow Style Hint" ) ); 1065 if( wdBlendType == "Follow Style Hint" ) _windecoBlendType=FollowStyleHint; 1066 else if( wdBlendType == "Radial Gradient" ) _windecoBlendType=RadialGradient; 1067 else if( wdBlendType == "Solid Color" ) _windecoBlendType=SolidColor; 1068 else _windecoBlendType=FollowStyleHint; 1069 1070 // shadow configurations 1071 _activeShadowConfiguration.initialize( _oxygen ); 1072 _inactiveShadowConfiguration.initialize( _oxygen ); 1073 1074 if(_kdeGlobals.getOption( "[General]", "widgetStyle" ).toVariant<std::string>("oxygen") == "oxygen transparent") 1075 _backgroundOpacity = _oxygen.getOption( "[Common]", "BackgroundOpacity" ).toVariant<int>(255); 1076 else 1077 _backgroundOpacity = 255; 1078 1079 #if OXYGEN_DEBUG 1080 std::cerr << _activeShadowConfiguration << std::endl; 1081 std::cerr << _inactiveShadowConfiguration << std::endl; 1082 #endif 1083 1084 // copy relevant options to to gtk 1085 // scrollbar width 1086 _rc.setCurrentSection( Gtk::RC::defaultSection() ); 1087 _rc.addToCurrentSection( Gtk::RCOption<int>( 1088 " GtkScrollbar::slider-width", 1089 _oxygen.getOption( "[Style]", "ScrollBarWidth" ).toVariant<int>(15) + 1 ) ); 1090 1091 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-backward-stepper", _scrollBarSubLineButtons > 0 ) ); 1092 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-forward-stepper", _scrollBarAddLineButtons > 0 ) ); 1093 1094 // note the inversion for add and sub, due to the fact that kde options refer to the button location, and not its direction 1095 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-secondary-backward-stepper", _scrollBarAddLineButtons > 1 ) ); 1096 _rc.addToCurrentSection( Gtk::RCOption<bool>(" GtkScrollbar::has-secondary-forward-stepper", _scrollBarSubLineButtons > 1 ) ); 1097 1098 // mnemonics 1099 GtkSettings* settings( gtk_settings_get_default() ); 1100 if( _oxygen.hasOption( "[Style]", "MnemonicsMode" ) ) 1101 { 1102 1103 const std::string mnemonicsMode( _oxygen.getOption( "[Style]", "MnemonicsMode" ).toVariant<std::string>("MN_ALWAYS") ); 1104 if( mnemonicsMode == "MN_NEVER" ) 1105 { 1106 1107 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", false, "oxygen-gtk" ); 1108 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1109 1110 } else if( mnemonicsMode == "MN_AUTO" ) { 1111 1112 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", true, "oxygen-gtk" ); 1113 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", true, "oxygen-gtk" ); 1114 1115 } else { 1116 1117 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", true, "oxygen-gtk" ); 1118 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1119 1120 } 1121 1122 } else { 1123 1124 // for backward compatibility 1125 const bool showMnemonics( _oxygen.getOption( "[Style]", "ShowMnemonics" ).toVariant<std::string>("true") == "true" ); 1126 if( showMnemonics ) 1127 { 1128 1129 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", true, "oxygen-gtk" ); 1130 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1131 1132 } else { 1133 1134 gtk_settings_set_long_property( settings, "gtk-enable-mnemonics", false, "oxygen-gtk" ); 1135 gtk_settings_set_long_property( settings, "gtk-auto-mnemonics", false, "oxygen-gtk" ); 1136 1137 } 1138 1139 } 1140 1141 } 1142 1143 //_________________________________________________________ loadExtraOptions(void)1144 void QtSettings::loadExtraOptions( void ) 1145 { 1146 1147 // deal with pathbar button margins 1148 // this needs to be done programatically in order to properly account for RTL locales 1149 _rc.addSection( "oxygen-pathbutton-internal", Gtk::RC::defaultSection() ); 1150 _rc.addToCurrentSection( " GtkButton::inner-border = { 2, 2, 1, 0 }" ); 1151 1152 if( gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL ) 1153 { 1154 1155 _rc.addToCurrentSection( " GtkToggleButton::inner-border={ 10, 0, 1, 0 }" ); 1156 1157 } else { 1158 1159 _rc.addToCurrentSection( " GtkToggleButton::inner-border={ 0, 10, 1, 0 }" ); 1160 1161 } 1162 1163 _rc.matchWidgetClassToSection( "*PathBar.GtkToggleButton", "oxygen-pathbutton-internal" ); 1164 1165 // entry margins 1166 _rc.addSection( "oxygen-entry-margins-internal", Gtk::RC::defaultSection() ); 1167 _rc.addToCurrentSection( Gtk::RCOption<int>( " xthickness", 5 ) ); 1168 _rc.addToCurrentSection( Gtk::RCOption<int>( " ythickness", applicationName().isXul() ? 2:1 ) ); 1169 _rc.matchClassToSection( "GtkEntry", "oxygen-entry-margins-internal" ); 1170 1171 // combobox buttons 1172 _rc.addSection( "oxygen-combobox-button-internal", Gtk::RC::defaultSection() ); 1173 _rc.addToCurrentSection( Gtk::RCOption<int>( " xthickness", 2 ) ); 1174 _rc.addToCurrentSection( Gtk::RCOption<int>( " ythickness", applicationName().isXul() ? 2:0 ) ); 1175 _rc.matchWidgetClassToSection( "*<GtkComboBox>.<GtkButton>", "oxygen-combobox-button-internal" ); 1176 1177 } 1178 1179 //_________________________________________________________ sanitizePath(const std::string & path) const1180 std::string QtSettings::sanitizePath( const std::string& path ) const 1181 { 1182 1183 std::string out( path ); 1184 size_t position( std::string::npos ); 1185 while( ( position = out.find( "//" ) ) != std::string::npos ) 1186 { out.replace( position, 2, "/" ); } 1187 1188 return out; 1189 } 1190 1191 //_________________________________________________________ monitorFile(const std::string & filename)1192 void QtSettings::monitorFile( const std::string& filename ) 1193 { 1194 1195 // check if file was already added 1196 if( _monitoredFiles.find( filename ) != _monitoredFiles.end() ) 1197 { return; } 1198 1199 // check file existence 1200 if( !std::ifstream( filename.c_str() ) ) 1201 { return; } 1202 1203 // create FileMonitor 1204 FileMonitor monitor; 1205 monitor.file = g_file_new_for_path( filename.c_str() ); 1206 if( ( monitor.monitor = g_file_monitor( monitor.file, G_FILE_MONITOR_NONE, 0L, 0L ) ) ) 1207 { 1208 1209 // insert in map 1210 _monitoredFiles.insert( std::make_pair( filename, monitor ) ); 1211 1212 } else { 1213 1214 // clear file and return 1215 g_object_unref( monitor.file ); 1216 return; 1217 1218 } 1219 1220 } 1221 1222 //_________________________________________________________ clearMonitoredFiles(void)1223 void QtSettings::clearMonitoredFiles( void ) 1224 { 1225 for( FileMap::iterator iter = _monitoredFiles.begin(); iter != _monitoredFiles.end(); iter++ ) 1226 { 1227 iter->second.signal.disconnect(); 1228 g_object_unref( iter->second.file ); 1229 g_object_unref( iter->second.monitor ); 1230 } 1231 1232 _monitoredFiles.clear(); 1233 } 1234 1235 } 1236