diff --git a/CMakeLists.txt b/CMakeLists.txt index de88c1bb..236a273b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,103 +1,64 @@ project(oxygen) set(PROJECT_VERSION "5.18.80") set(PROJECT_VERSION_MAJOR 5) cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) include(GenerateExportHeader) include(WriteBasicConfigVersionFile) include(FeatureSummary) -set(OXYGEN_USE_KDE4 ${USE_KDE4}) -if(OXYGEN_USE_KDE4) - - ############ Language and toolchain features - ############ copied from ECM - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" AND NOT WIN32) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - endif() - -endif() - ################# Qt/KDE ################# -if(OXYGEN_USE_KDE4) - - find_package(KDE4 REQUIRED) - include(KDE4Defaults) - include(MacroLibrary) - - add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) - include_directories(${KDE4_INCLUDES}) - - ### XCB - find_package(PkgConfig) - pkg_check_modules(XCB xcb x11-xcb) - add_feature_info("x11-xcb" XCB_FOUND "Required to pass style properties to native Windows on X11 Platform") - set_feature_info("x11-xcb" "Required to pass style properties to native Windows on X11 Platform" "http://xcb.freedesktop.org") - set(OXYGEN_HAVE_X11 ${XCB_FOUND}) - set(OXYGEN_HAVE_KWAYLAND FALSE) - - add_subdirectory(liboxygen) - add_subdirectory(kstyle) - -else() - - find_package(ECM 0.0.9 REQUIRED NO_MODULE) - set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) - - find_package(Qt5 REQUIRED CONFIG COMPONENTS Widgets DBus Quick) - find_package(KF5 REQUIRED COMPONENTS - I18n - Config - GuiAddons - WidgetsAddons - Service - Completion - FrameworkIntegration - WindowSystem) - - find_package(XCB COMPONENTS XCB) - set_package_properties(XCB PROPERTIES - DESCRIPTION "X protocol C-language Binding" - URL "http://xcb.freedesktop.org" - TYPE OPTIONAL - PURPOSE "Required to pass style properties to native Windows on X11 Platform" - ) - - find_package(KF5Wayland CONFIG) - set(OXYGEN_HAVE_KWAYLAND ${KF5Wayland_FOUND}) - - if(NOT APPLE) - +find_package(ECM 0.0.9 REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) + +find_package(Qt5 REQUIRED CONFIG COMPONENTS Widgets DBus Quick) +find_package(KF5 REQUIRED COMPONENTS + I18n + Config + GuiAddons + WidgetsAddons + Service + Completion + FrameworkIntegration + WindowSystem) + +find_package(XCB COMPONENTS XCB) +set_package_properties(XCB PROPERTIES + DESCRIPTION "X protocol C-language Binding" + URL "http://xcb.freedesktop.org" + TYPE OPTIONAL + PURPOSE "Required to pass style properties to native Windows on X11 Platform" +) + +find_package(KF5Wayland CONFIG) +set(OXYGEN_HAVE_KWAYLAND ${KF5Wayland_FOUND}) + +if(NOT APPLE) set(OXYGEN_HAVE_X11 ${XCB_XCB_FOUND}) if (XCB_XCB_FOUND) - find_package(Qt5 REQUIRED CONFIG COMPONENTS X11Extras) + find_package(Qt5 REQUIRED CONFIG COMPONENTS X11Extras) endif() +endif() - endif() - - include(ECMInstallIcons) - include(KDEInstallDirs) - include(KDECMakeSettings) - include(KDECompilerSettings NO_POLICY_SCOPE) +include(ECMInstallIcons) +include(KDEInstallDirs) +include(KDECMakeSettings) +include(KDECompilerSettings NO_POLICY_SCOPE) - add_subdirectory(liboxygen) - add_subdirectory(kstyle) - add_subdirectory(color-schemes) - add_subdirectory(cursors) - add_subdirectory(sounds) - add_subdirectory(kdecoration) +add_subdirectory(liboxygen) +add_subdirectory(kstyle) +add_subdirectory(color-schemes) +add_subdirectory(cursors) +add_subdirectory(sounds) +add_subdirectory(kdecoration) - install(DIRECTORY lookandfeel/ DESTINATION ${KDE_INSTALL_DATADIR}/plasma/look-and-feel/org.kde.oxygen - PATTERN "Messages.sh" EXCLUDE PATTERN "CMakeLists.txt" EXCLUDE) +install(DIRECTORY lookandfeel/ DESTINATION ${KDE_INSTALL_DATADIR}/plasma/look-and-feel/org.kde.oxygen + PATTERN "Messages.sh" EXCLUDE PATTERN "CMakeLists.txt" EXCLUDE) - # po/ dir added by packaging scripts - if(EXISTS ${CMAKE_SOURCE_DIR}/po AND IS_DIRECTORY ${CMAKE_SOURCE_DIR}/po) +# po/ dir added by packaging scripts +if(EXISTS ${CMAKE_SOURCE_DIR}/po AND IS_DIRECTORY ${CMAKE_SOURCE_DIR}/po) find_package(KF5I18n CONFIG REQUIRED) ki18n_install(po) - endif() - endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/kstyle/CMakeLists.txt b/kstyle/CMakeLists.txt index 12db9707..96861d2a 100644 --- a/kstyle/CMakeLists.txt +++ b/kstyle/CMakeLists.txt @@ -1,116 +1,98 @@ ################# includes ################# include_directories( animations debug transitions ) include_directories(${CMAKE_SOURCE_DIR}/liboxygen) include_directories(${CMAKE_BINARY_DIR}/liboxygen) ########### next target ############### set(oxygen_PART_SRCS animations/oxygenanimations.cpp animations/oxygenanimationdata.cpp animations/oxygenbaseengine.cpp animations/oxygenbusyindicatordata.cpp animations/oxygenbusyindicatorengine.cpp animations/oxygendockseparatordata.cpp animations/oxygendockseparatorengine.cpp animations/oxygenenabledata.cpp animations/oxygengenericdata.cpp animations/oxygenheaderviewdata.cpp animations/oxygenheaderviewengine.cpp animations/oxygenmdiwindowdata.cpp animations/oxygenmdiwindowengine.cpp animations/oxygenmenubardata.cpp animations/oxygenmenubarengine.cpp animations/oxygenmenudata.cpp animations/oxygenmenuengine.cpp animations/oxygenprogressbardata.cpp animations/oxygenprogressbarengine.cpp animations/oxygenscrollbardata.cpp animations/oxygenscrollbarengine.cpp animations/oxygenspinboxdata.cpp animations/oxygenspinboxengine.cpp animations/oxygensplitterengine.cpp animations/oxygentabbardata.cpp animations/oxygentabbarengine.cpp animations/oxygentoolbardata.cpp animations/oxygentoolbarengine.cpp animations/oxygentoolboxengine.cpp animations/oxygenwidgetstatedata.cpp animations/oxygenwidgetstateengine.cpp debug/oxygenwidgetexplorer.cpp transitions/oxygencomboboxdata.cpp transitions/oxygencomboboxengine.cpp transitions/oxygenlabeldata.cpp transitions/oxygenlabelengine.cpp transitions/oxygenlineeditdata.cpp transitions/oxygenlineeditengine.cpp transitions/oxygenstackedwidgetdata.cpp transitions/oxygenstackedwidgetengine.cpp transitions/oxygentransitiondata.cpp transitions/oxygentransitions.cpp transitions/oxygentransitionwidget.cpp oxygenblurhelper.cpp oxygenframeshadow.cpp oxygenmdiwindowshadow.cpp oxygenmnemonics.cpp oxygenpropertynames.cpp oxygenshadowhelper.cpp oxygensplitterproxy.cpp oxygenstyle.cpp oxygenstylehelper.cpp oxygenstyleplugin.cpp oxygenwindowmanager.cpp ) -if(OXYGEN_USE_KDE4) +kconfig_add_kcfg_files(oxygen_PART_SRCS oxygenstyleconfigdata.kcfgc) +add_library(oxygen MODULE ${oxygen_PART_SRCS}) - kde4_add_kcfg_files(oxygen_PART_SRCS oxygenstyleconfigdata.kcfgc) - kde4_add_plugin(oxygen ${oxygen_PART_SRCS} kstylekde4compat.cpp) - target_link_libraries(oxygen ${KDE4_KDEUI_LIBS}) - target_link_libraries(oxygen oxygenstyle) +target_link_libraries(oxygen Qt5::Core Qt5::Gui Qt5::Widgets Qt5::DBus Qt5::Quick) +target_link_libraries(oxygen KF5::GuiAddons KF5::Style KF5::WindowSystem) +target_link_libraries(oxygen oxygenstyle5) - if(OXYGEN_HAVE_X11) - target_link_libraries(oxygen ${X11_XCB_LIBRARIES}) - target_link_libraries(oxygen ${XCB_LIBRARIES}) - endif() - - install(TARGETS oxygen DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/styles/) - -else() - - kconfig_add_kcfg_files(oxygen_PART_SRCS oxygenstyleconfigdata.kcfgc) - add_library(oxygen MODULE ${oxygen_PART_SRCS}) - - target_link_libraries(oxygen Qt5::Core Qt5::Gui Qt5::Widgets Qt5::DBus Qt5::Quick) - target_link_libraries(oxygen KF5::GuiAddons KF5::Style KF5::WindowSystem) - target_link_libraries(oxygen oxygenstyle5) - - if(OXYGEN_HAVE_X11) +if(OXYGEN_HAVE_X11) target_link_libraries(oxygen XCB::XCB) target_link_libraries(oxygen Qt5::X11Extras) - endif() +endif() - if(OXYGEN_HAVE_KWAYLAND) +if(OXYGEN_HAVE_KWAYLAND) target_link_libraries(oxygen KF5::WaylandClient) - endif() - - install(TARGETS oxygen DESTINATION ${QT_PLUGIN_INSTALL_DIR}/styles/) - endif() +install(TARGETS oxygen DESTINATION ${QT_PLUGIN_INSTALL_DIR}/styles/) + if(WIN32) # As stated in http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx M_PI only gets defined # when using MSVC if _USE_MATH_DEFINES is defined (this is needed for angle.cpp) target_compile_definitions(oxygen PRIVATE _USE_MATH_DEFINES _GNU_SOURCE) endif() ########### install files ############### install(FILES oxygen.themerc DESTINATION ${DATA_INSTALL_DIR}/kstyle/themes) ########### subdirectories ############### add_subdirectory(config) add_subdirectory(demo) diff --git a/kstyle/config/CMakeLists.txt b/kstyle/config/CMakeLists.txt index 3d5387e4..a619e9f5 100644 --- a/kstyle/config/CMakeLists.txt +++ b/kstyle/config/CMakeLists.txt @@ -1,80 +1,57 @@ ### configuration plugin add_definitions(-DTRANSLATION_DOMAIN=\"oxygen_style_config\") set(kstyle_oxygen_config_PART_SRCS oxygenanimationconfigwidget.cpp oxygenfollowmouseanimationconfigitem.cpp oxygenstyleconfig.cpp ) set(kstyle_oxygen_config_PART_FORMS ui/oxygenfollowmouseanimationconfigbox.ui ui/oxygenstyleconfig.ui ) -if(OXYGEN_USE_KDE4) +set(kstyle_oxygen_config_PART_SRCS ${kstyle_oxygen_config_PART_SRCS} oxygenstyleconfigmodule.cpp) - kde4_add_kcfg_files(kstyle_oxygen_config_PART_SRCS ../oxygenstyleconfigdata.kcfgc) +kconfig_add_kcfg_files(kstyle_oxygen_config_PART_SRCS ../oxygenstyleconfigdata.kcfgc) - kde4_add_ui_files(kstyle_oxygen_config_PART_FORMS_HEADERS ${kstyle_oxygen_config_PART_FORMS}) - - kde4_add_plugin(kstyle_oxygen_config - ${kstyle_oxygen_config_PART_SRCS} - ${kstyle_oxygen_config_PART_FORMS_HEADERS} - ) - - target_link_libraries(kstyle_oxygen_config ${KDE4_KDEUI_LIBS}) - target_link_libraries(kstyle_oxygen_config oxygenstyleconfig) - install(TARGETS kstyle_oxygen_config DESTINATION ${PLUGIN_INSTALL_DIR}/) - -else() - - set(kstyle_oxygen_config_PART_SRCS ${kstyle_oxygen_config_PART_SRCS} oxygenstyleconfigmodule.cpp) - - kconfig_add_kcfg_files(kstyle_oxygen_config_PART_SRCS ../oxygenstyleconfigdata.kcfgc) - - set(kstyle_oxygen_config_PART_FORMS +set(kstyle_oxygen_config_PART_FORMS ui/oxygenfollowmouseanimationconfigbox.ui ui/oxygenstyleconfig.ui - ) - - ki18n_wrap_ui(kstyle_oxygen_config_PART_FORMS_HEADERS ${kstyle_oxygen_config_PART_FORMS}) +) - add_library(kstyle_oxygen_config MODULE - ${kstyle_oxygen_config_PART_SRCS} - ${kstyle_oxygen_config_PART_FORMS_HEADERS} - ) +ki18n_wrap_ui(kstyle_oxygen_config_PART_FORMS_HEADERS ${kstyle_oxygen_config_PART_FORMS}) - target_link_libraries(kstyle_oxygen_config Qt5::Core Qt5::Gui Qt5::Widgets Qt5::DBus) - target_link_libraries(kstyle_oxygen_config KF5::Completion KF5::I18n) - target_link_libraries(kstyle_oxygen_config oxygenstyleconfig5) +add_library(kstyle_oxygen_config MODULE + ${kstyle_oxygen_config_PART_SRCS} + ${kstyle_oxygen_config_PART_FORMS_HEADERS} +) - install(TARGETS kstyle_oxygen_config DESTINATION ${QT_PLUGIN_INSTALL_DIR}) - install(FILES oxygenstyleconfig.desktop DESTINATION ${SERVICES_INSTALL_DIR}) +target_link_libraries(kstyle_oxygen_config Qt5::Core Qt5::Gui Qt5::Widgets Qt5::DBus) +target_link_libraries(kstyle_oxygen_config KF5::Completion KF5::I18n) +target_link_libraries(kstyle_oxygen_config oxygenstyleconfig5) -endif() +install(TARGETS kstyle_oxygen_config DESTINATION ${QT_PLUGIN_INSTALL_DIR}) +install(FILES oxygenstyleconfig.desktop DESTINATION ${SERVICES_INSTALL_DIR}) ########### next target ############### -if(NOT OXYGEN_USE_KDE4) - - find_package(KF5KCMUtils CONFIG) - set_package_properties(KF5KCMUtils PROPERTIES - DESCRIPTION "KF5 KCM utils Framework" - URL "https://projects.kde.org/projects/frameworks/kcmutils" - TYPE OPTIONAL - PURPOSE "Required for oxygen-settings5 application to build") - - if( KF5KCMUtils_FOUND ) - - set(oxygen_settings_SOURCES main.cpp) - add_executable(oxygen-settings5 ${oxygen_settings_SOURCES} ) - target_link_libraries(oxygen-settings5 Qt5::Core Qt5::Gui Qt5::Widgets ) - target_link_libraries(oxygen-settings5 KF5::I18n KF5::KCMUtils) - - install(TARGETS oxygen-settings5 ${INSTALL_TARGETS_DEFAULT_ARGS}) - - # icon - ecm_install_icons(ICONS 256-apps-oxygen-settings.png - DESTINATION ${ICON_INSTALL_DIR} - THEME hicolor ) - endif() +find_package(KF5KCMUtils CONFIG) +set_package_properties(KF5KCMUtils PROPERTIES + DESCRIPTION "KF5 KCM utils Framework" + URL "https://projects.kde.org/projects/frameworks/kcmutils" + TYPE OPTIONAL + PURPOSE "Required for oxygen-settings5 application to build") + +if( KF5KCMUtils_FOUND ) + set(oxygen_settings_SOURCES main.cpp) + add_executable(oxygen-settings5 ${oxygen_settings_SOURCES} ) + target_link_libraries(oxygen-settings5 Qt5::Core Qt5::Gui Qt5::Widgets ) + target_link_libraries(oxygen-settings5 KF5::I18n KF5::KCMUtils) + + install(TARGETS oxygen-settings5 ${INSTALL_TARGETS_DEFAULT_ARGS}) + + # icon + ecm_install_icons(ICONS 256-apps-oxygen-settings.png + DESTINATION ${ICON_INSTALL_DIR} + THEME hicolor ) endif() diff --git a/kstyle/config/oxygenstyleconfig.cpp b/kstyle/config/oxygenstyleconfig.cpp index 4578adc0..dca4fc25 100644 --- a/kstyle/config/oxygenstyleconfig.cpp +++ b/kstyle/config/oxygenstyleconfig.cpp @@ -1,259 +1,239 @@ /* Copyright 2010 Hugo Pereira Da Costa Copyright 2009 Matthew Woehlke Copyright 2009 Long Huynh Huu Copyright 2003 Sandro Giessl originally based on the Keramik configuration dialog: Copyright 2003 Maksim Orlovich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "oxygenstyleconfig.h" #include "oxygenanimationconfigwidget.h" #include "oxygenstyleconfigdata.h" #include "../oxygen.h" #include "config-liboxygen.h" #include #include #include #include #include #include -#if !OXYGEN_USE_KDE4 -#include -#endif #define SCROLLBAR_DEFAULT_WIDTH 15 #define SCROLLBAR_MINIMUM_WIDTH 10 #define SCROLLBAR_MAXIMUM_WIDTH 30 extern "C" { Q_DECL_EXPORT QWidget* allocate_kstyle_config(QWidget* parent) { return new Oxygen::StyleConfig(parent); } } namespace Oxygen { //__________________________________________________________________ StyleConfig::StyleConfig(QWidget* parent): QWidget(parent) { setupUi(this); // load setup from configData load(); connect( _useBackgroundGradient, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _toolBarDrawItemSeparator, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _splitterProxyEnabled, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _mnemonicsMode, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) ); connect( _viewDrawFocusIndicator, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _viewTriangularExpanderSize, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) ); connect( _viewDrawTreeBranchLines, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _scrollBarWidth, SIGNAL(valueChanged(int)), SLOT(updateChanged()) ); connect( _scrollBarAddLineButtons, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) ); connect( _scrollBarSubLineButtons, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) ); connect( _menuHighlightDark, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _menuHighlightStrong, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _menuHighlightSubtle, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( _windowDragMode, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) ); connect( _animationConfigWidget, SIGNAL(changed(bool)), SLOT(updateChanged()) ); connect( _animationConfigWidget, SIGNAL(layoutChanged()), SLOT(updateLayout()) ); } //__________________________________________________________________ void StyleConfig::save( void ) { StyleConfigData::setUseBackgroundGradient( _useBackgroundGradient->isChecked() ); StyleConfigData::setToolBarDrawItemSeparator( _toolBarDrawItemSeparator->isChecked() ); StyleConfigData::setSplitterProxyEnabled( _splitterProxyEnabled->isChecked() ); StyleConfigData::setMnemonicsMode( _mnemonicsMode->currentIndex() ); StyleConfigData::setViewDrawFocusIndicator( _viewDrawFocusIndicator->isChecked() ); StyleConfigData::setViewTriangularExpanderSize( triangularExpanderSize() ); StyleConfigData::setViewDrawTreeBranchLines( _viewDrawTreeBranchLines->isChecked() ); StyleConfigData::setScrollBarWidth( _scrollBarWidth->value() ); StyleConfigData::setScrollBarAddLineButtons( _scrollBarAddLineButtons->currentIndex() ); StyleConfigData::setScrollBarSubLineButtons( _scrollBarSubLineButtons->currentIndex() ); StyleConfigData::setMenuHighlightMode( menuMode() ); StyleConfigData::setWindowDragMode( _windowDragMode->currentIndex() ); StyleConfigData::setWindowDragEnabled( _windowDragMode->currentIndex() != StyleConfigData::WD_NONE ); _animationConfigWidget->save(); - #if OXYGEN_USE_KDE4 - StyleConfigData::self()->writeConfig(); - #else StyleConfigData::self()->save(); - //update the KDE4 config to match - Kdelibs4Migration migration; - const QString kde4ConfigDirPath = migration.saveLocation("config"); - - QScopedPointer kde4Config(new KConfig); - StyleConfigData::self()->config()->copyTo(kde4ConfigDirPath+"/oxygenrc", kde4Config.data()); - kde4Config->sync(); - - #endif - // emit dbus signal QDBusMessage message( QDBusMessage::createSignal( QStringLiteral( "/OxygenStyle" ), QStringLiteral( "org.kde.Oxygen.Style" ), QStringLiteral( "reparseConfiguration" ) ) ); QDBusConnection::sessionBus().send(message); } //__________________________________________________________________ void StyleConfig::defaults( void ) { StyleConfigData::self()->setDefaults(); load(); } //__________________________________________________________________ void StyleConfig::reset( void ) { // reparse configuration - #if OXYGEN_USE_KDE4 - StyleConfigData::self()->readConfig(); - #else StyleConfigData::self()->load(); - #endif load(); } //__________________________________________________________________ bool StyleConfig::event( QEvent* event ) { const bool result( QWidget::event( event ) ); switch( event->type() ) { case QEvent::Show: case QEvent::ShowToParent: // explicitly update minimum size from hint // this is needed to automatically resize the window to fit animations tab setMinimumSize( minimumSizeHint() ); break; default: break; } return result; } //__________________________________________________________________ void StyleConfig::updateLayout( void ) { const int delta = _animationConfigWidget->minimumSizeHint().height() - _animationConfigWidget->size().height(); window()->setMinimumSize( QSize( window()->minimumSizeHint().width(), window()->size().height() + delta ) ); } //__________________________________________________________________ void StyleConfig::updateChanged() { bool modified( false ); // check if any value was modified if ( _useBackgroundGradient->isChecked() != StyleConfigData::useBackgroundGradient() ) modified = true; if ( _toolBarDrawItemSeparator->isChecked() != StyleConfigData::toolBarDrawItemSeparator() ) modified = true; else if( _mnemonicsMode->currentIndex() != StyleConfigData::mnemonicsMode() ) modified = true; else if( _viewDrawTreeBranchLines->isChecked() != StyleConfigData::viewDrawTreeBranchLines() ) modified = true; else if( _scrollBarWidth->value() != StyleConfigData::scrollBarWidth() ) modified = true; else if( _scrollBarAddLineButtons->currentIndex() != StyleConfigData::scrollBarAddLineButtons() ) modified = true; else if( _scrollBarSubLineButtons->currentIndex() != StyleConfigData::scrollBarSubLineButtons() ) modified = true; else if( _splitterProxyEnabled->isChecked() != StyleConfigData::splitterProxyEnabled() ) modified = true; else if( menuMode() != StyleConfigData::menuHighlightMode() ) modified = true; else if( _viewDrawFocusIndicator->isChecked() != StyleConfigData::viewDrawFocusIndicator() ) modified = true; else if( triangularExpanderSize() != StyleConfigData::viewTriangularExpanderSize() ) modified = true; else if( _animationConfigWidget && _animationConfigWidget->isChanged() ) modified = true; else if( _windowDragMode->currentIndex() != StyleConfigData::windowDragMode() ) modified = true; emit changed(modified); } //__________________________________________________________________ void StyleConfig::load( void ) { _useBackgroundGradient->setChecked( StyleConfigData::useBackgroundGradient() ); _toolBarDrawItemSeparator->setChecked( StyleConfigData::toolBarDrawItemSeparator() ); _mnemonicsMode->setCurrentIndex( StyleConfigData::mnemonicsMode() ); _splitterProxyEnabled->setChecked( StyleConfigData::splitterProxyEnabled() ); _viewDrawTreeBranchLines->setChecked(StyleConfigData::viewDrawTreeBranchLines() ); _scrollBarWidth->setValue( qMin(SCROLLBAR_MAXIMUM_WIDTH, qMax(SCROLLBAR_MINIMUM_WIDTH, StyleConfigData::scrollBarWidth())) ); _scrollBarAddLineButtons->setCurrentIndex( StyleConfigData::scrollBarAddLineButtons() ); _scrollBarSubLineButtons->setCurrentIndex( StyleConfigData::scrollBarSubLineButtons() ); // menu highlight _menuHighlightDark->setChecked( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_DARK ); _menuHighlightStrong->setChecked( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG ); _menuHighlightSubtle->setChecked( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_SUBTLE ); _windowDragMode->setCurrentIndex( StyleConfigData::windowDragMode() ); _viewDrawFocusIndicator->setChecked( StyleConfigData::viewDrawFocusIndicator() ); switch( StyleConfigData::viewTriangularExpanderSize() ) { case StyleConfigData::TE_TINY: _viewTriangularExpanderSize->setCurrentIndex(0); break; case StyleConfigData::TE_SMALL: default: _viewTriangularExpanderSize->setCurrentIndex(1); break; case StyleConfigData::TE_NORMAL: _viewTriangularExpanderSize->setCurrentIndex(2); break; } // animation config widget if( _animationConfigWidget ) _animationConfigWidget->load(); } //____________________________________________________________ int StyleConfig::menuMode( void ) const { if (_menuHighlightDark->isChecked()) return StyleConfigData::MM_DARK; else if (_menuHighlightSubtle->isChecked()) return StyleConfigData::MM_SUBTLE; else return StyleConfigData::MM_STRONG; } //____________________________________________________________ int StyleConfig::triangularExpanderSize( void ) const { switch( _viewTriangularExpanderSize->currentIndex() ) { case 0: return StyleConfigData::TE_TINY; case 1: default: return StyleConfigData::TE_SMALL; case 2: return StyleConfigData::TE_NORMAL; } } } diff --git a/kstyle/demo/CMakeLists.txt b/kstyle/demo/CMakeLists.txt index 18d23b3c..e18064bf 100644 --- a/kstyle/demo/CMakeLists.txt +++ b/kstyle/demo/CMakeLists.txt @@ -1,70 +1,52 @@ add_definitions(-DTRANSLATION_DOMAIN=\"oxygen_style_demo\") include_directories(${CMAKE_BINARY_DIR}/liboxygen) ########### next target ############### set(oxygen_demo_SOURCES oxygenbenchmarkwidget.cpp oxygenbuttondemowidget.cpp oxygendemodialog.cpp oxygendemowidget.cpp oxygenframedemowidget.cpp oxygeninputdemowidget.cpp oxygenlistdemowidget.cpp oxygenmdidemowidget.cpp oxygensimulator.cpp oxygensliderdemowidget.cpp oxygentabdemowidget.cpp oxygentabwidget.cpp main.cpp) set(oxygen_demo_FORMS ui/oxygenbenchmarkwidget.ui ui/oxygenbuttondemowidget.ui ui/oxygenframedemowidget.ui ui/oxygeninputdemowidget.ui ui/oxygenlistdemowidget.ui ui/oxygenmdidemowidget.ui ui/oxygensliderdemowidget.ui ui/oxygentabdemowidget.ui ) -if(OXYGEN_USE_KDE4) - - kde4_add_ui_files(oxygen_demo_FORMS_HEADERS ${oxygen_demo_FORMS}) - - kde4_add_executable(oxygen-demo - ${oxygen_demo_SOURCES} - ${oxygen_demo_FORMS_HEADERS} - ) - - target_link_libraries(oxygen-demo ${KDE4_KDEUI_LIBS}) - - ########### install files ############### - install(TARGETS oxygen-demo ${INSTALL_TARGETS_DEFAULT_ARGS}) - -else() - - find_package(KF5ConfigWidgets CONFIG) - if(KF5ConfigWidgets_FOUND) +find_package(KF5ConfigWidgets CONFIG) +if(KF5ConfigWidgets_FOUND) set(oxygen_demo_SOURCES ${oxygen_demo_SOURCES} oxygenschemechooser.cpp oxygenstylechooser.cpp) add_definitions(-DHAVE_SCHEME_CHOOSER) - endif() +endif() - ki18n_wrap_ui(oxygen_demo_FORMS_HEADERS ${oxygen_demo_FORMS}) +ki18n_wrap_ui(oxygen_demo_FORMS_HEADERS ${oxygen_demo_FORMS}) - add_executable(oxygen-demo5 - ${oxygen_demo_SOURCES} - ${oxygen_demo_FORMS_HEADERS} - ) +add_executable(oxygen-demo5 + ${oxygen_demo_SOURCES} + ${oxygen_demo_FORMS_HEADERS} +) - target_link_libraries(oxygen-demo5 Qt5::Core Qt5::Gui Qt5::Widgets) - target_link_libraries(oxygen-demo5 KF5::Completion KF5::ConfigGui KF5::WidgetsAddons KF5::I18n) - if(KF5ConfigWidgets_FOUND) +target_link_libraries(oxygen-demo5 Qt5::Core Qt5::Gui Qt5::Widgets) +target_link_libraries(oxygen-demo5 KF5::Completion KF5::ConfigGui KF5::WidgetsAddons KF5::I18n) +if(KF5ConfigWidgets_FOUND) target_link_libraries(oxygen-demo5 KF5::ConfigWidgets) - endif() - - ########### install files ############### - install(TARGETS oxygen-demo5 ${INSTALL_TARGETS_DEFAULT_ARGS}) - endif() + +########### install files ############### +install(TARGETS oxygen-demo5 ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/kstyle/demo/main.cpp b/kstyle/demo/main.cpp index b75731fa..0210b3ec 100644 --- a/kstyle/demo/main.cpp +++ b/kstyle/demo/main.cpp @@ -1,77 +1,69 @@ ////////////////////////////////////////////////////////////////////////////// // main.cpp // oxygen-demo main // ------------------- // // Copyright (c) 2010 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygendemodialog.h" #include "../oxygen.h" #include "config-liboxygen.h" #include - -#if QT_VERSION >= 0x050200 #include #include -#endif - #include #include namespace Oxygen { int run(int argc, char *argv[]) { QApplication app( argc, argv ); - #if QT_VERSION >= 0x050200 QCommandLineParser commandLine; QCommandLineOption enableHighDpi( "highdpi", "Enable High DPI pixmaps" ); commandLine.addOption( enableHighDpi ); commandLine.process( app ); app.setAttribute( Qt::AA_UseHighDpiPixmaps, commandLine.isSet( enableHighDpi ) ); - #endif app.setApplicationName( i18n( "Oxygen Demo" ) ); app.setWindowIcon( QIcon::fromTheme( QStringLiteral( "oxygen" ) ) ); DemoDialog dialog; dialog.show(); bool result = app.exec(); return result; } } //__________________________________________ int main(int argc, char *argv[]) { - #if !OXYGEN_USE_KDE4 KLocalizedString::setApplicationDomain("oxygen_style_demo"); - #endif return Oxygen::run( argc, argv ); } diff --git a/kstyle/demo/oxygendemodialog.cpp b/kstyle/demo/oxygendemodialog.cpp index 528173b1..74b23440 100644 --- a/kstyle/demo/oxygendemodialog.cpp +++ b/kstyle/demo/oxygendemodialog.cpp @@ -1,258 +1,243 @@ ////////////////////////////////////////////////////////////////////////////// // oxygendemodialog.cpp // oxygen configuration dialog // ------------------- // // Copyright (c) 2010 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygendemodialog.h" #include "oxygenbenchmarkwidget.h" #include "oxygenbuttondemowidget.h" #include "oxygeninputdemowidget.h" #include "oxygenframedemowidget.h" #include "oxygenlistdemowidget.h" #include "oxygenmdidemowidget.h" #include "oxygensliderdemowidget.h" #include "oxygentabdemowidget.h" #include "config-liboxygen.h" #ifdef HAVE_SCHEME_CHOOSER #include "oxygenschemechooser.h" #include "oxygenstylechooser.h" #endif #include #include #include #include #include namespace Oxygen { //_______________________________________________________________ DemoDialog::DemoDialog( QWidget* parent ): KPageDialog( parent ) { setWindowTitle( i18n( "Oxygen Demo" ) ); - #if OXYGEN_USE_KDE4 - // install Quit shortcut - connect( new QShortcut( KStandardShortcut::quit().primary(), this ), SIGNAL(activated()), SLOT(close()) ); - connect( new QShortcut( KStandardShortcut::quit().alternate(), this ), SIGNAL(activated()), SLOT(close()) ); - #else // install Quit shortcut foreach( const QKeySequence& sequence, KStandardShortcut::quit() ) { connect( new QShortcut( sequence, this ), SIGNAL(activated()), SLOT(close()) ); } - #endif - #if OXYGEN_USE_KDE4 - setButtons( KDialog::Ok ); - auto buttonBox = findChild(); - #else // button box auto buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok, Qt::Horizontal ); setButtonBox( buttonBox ); // connection connect( buttonBox->button( QDialogButtonBox::Ok ), SIGNAL(clicked()), SLOT(close()) ); - #endif // customize button box _enableCheckBox = new QCheckBox( i18n( "Enabled" ) ); _enableCheckBox->setChecked( true ); connect( _enableCheckBox, SIGNAL(toggled(bool)), SLOT(toggleEnable(bool)) ); buttonBox->addButton( _enableCheckBox, QDialogButtonBox::ResetRole ); _rightToLeftCheckBox = new QCheckBox( i18n( "Right to left layout" ) ); connect( _rightToLeftCheckBox, SIGNAL(toggled(bool)), SLOT(toggleRightToLeft(bool)) ); buttonBox->addButton( _rightToLeftCheckBox, QDialogButtonBox::ResetRole ); #ifdef HAVE_SCHEME_CHOOSER auto styleChooser = new WidgetStyleChooser(this); styleChooser->createStyleSelectionMenu( i18n( "Style" ) ); buttonBox->addButton( styleChooser, QDialogButtonBox::ResetRole ); auto colChooser = new ColorSchemeChooser( this ); buttonBox->addButton( colChooser, QDialogButtonBox::ResetRole ); #endif // connections connect( this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), SLOT(updateWindowTitle(KPageWidgetItem*)) ); connect( this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), SLOT(updateEnableState(KPageWidgetItem*)) ); auto setPageIcon = []( KPageWidgetItem* page, const QString& iconName ) { - #if OXYGEN_USE_KDE4 - page->setIcon( KIcon( iconName ) ); - #else page->setIcon( QIcon::fromTheme( iconName ) ); - #endif }; KPageWidgetItem* page = nullptr; QVector items; // inputs { page = new KPageWidgetItem( new InputDemoWidget() ); page->setName( i18n("Input Widgets") ); setPageIcon( page, QStringLiteral( "edit-rename" ) ); page->setHeader( i18n("Shows the appearance of text input widgets") ); addPage( page ); items.append( page ); } // tab { page = new KPageWidgetItem( new TabDemoWidget() ); page->setName( i18n("Tab Widgets") ); setPageIcon( page, QStringLiteral( "tab-detach" ) ); page->setHeader( i18n("Shows the appearance of tab widgets") ); addPage( page ); items.append( page ); } // buttons { page = new KPageWidgetItem( new ButtonDemoWidget() ); page->setName( i18n("Buttons") ); setPageIcon( page, QStringLiteral( "go-jump-locationbar" ) ); page->setHeader( i18n("Shows the appearance of buttons") ); addPage( page ); items.append( page ); } // lists { page = new KPageWidgetItem( new ListDemoWidget() ); page->setName( i18n("Lists") ); setPageIcon( page, QStringLiteral( "view-list-tree" ) ); page->setHeader( i18n("Shows the appearance of lists, trees and tables") ); addPage( page ); items.append( page ); } // frames { page = new KPageWidgetItem( new FrameDemoWidget() ); page->setName( i18n("Frames") ); setPageIcon( page, QStringLiteral( "draw-rectangle" ) ); page->setHeader( i18n("Shows the appearance of various framed widgets") ); addPage( page ); items.append( page ); } // mdi { page = new KPageWidgetItem( new MdiDemoWidget() ); page->setName( i18n( "MDI Windows" ) ); setPageIcon( page, QStringLiteral( "preferences-system-windows" ) ); page->setHeader( i18n( "Shows the appearance of MDI windows" ) ); addPage( page ); items.append( page ); } // sliders { page = new KPageWidgetItem( new SliderDemoWidget() ); page->setName( i18n("Sliders") ); setPageIcon( page, QStringLiteral( "measure" ) ); page->setHeader( i18n("Shows the appearance of sliders, progress bars and scrollbars") ); addPage( page ); items.append( page ); } // benchmark { auto benchmarkWidget( new BenchmarkWidget() ); page = new KPageWidgetItem( benchmarkWidget ); page->setName( i18n("Benchmark") ); setPageIcon( page, QStringLiteral( "system-run" ) ); page->setHeader( i18n("Emulates user interaction with widgets for benchmarking") ); benchmarkWidget->init( this, items ); addPage( page ); items.append( page ); } // connections QShortcut* shortcut( new QShortcut( Qt::CTRL + Qt::Key_X, this ) ); for( auto item:items ) { if( item->widget()->metaObject()->indexOfSlot( "benchmark()" ) >= 0 ) { connect( shortcut, SIGNAL(activated()), item->widget(), SLOT(benchmark()) ); } connect( this, SIGNAL(abortSimulations()), &static_cast(item->widget())->simulator(), SLOT(abort()) ); } } //_______________________________________________________________ void DemoDialog::updateWindowTitle( KPageWidgetItem* item ) { QString title; QTextStream what( &title ); if( item ) { what << item->name(); what << " - "; } what << i18n( "Oxygen Demo" ); setWindowTitle( title ); } //_______________________________________________________________ void DemoDialog::updateEnableState( KPageWidgetItem* item ) { if( !( item && item->widget() && _enableCheckBox ) ) return; item->widget()->setEnabled( _enableCheckBox->isChecked() ); } //_______________________________________________________________ void DemoDialog::toggleEnable( bool value ) { if( !( currentPage() && currentPage()->widget() ) ) return; currentPage()->widget()->setEnabled( value ); } //_______________________________________________________________ void DemoDialog::toggleRightToLeft( bool value ) { qApp->setLayoutDirection( value ? Qt::RightToLeft:Qt::LeftToRight ); } //_______________________________________________________________ void DemoDialog::closeEvent( QCloseEvent* event ) { emit abortSimulations(); KPageDialog::closeEvent( event ); } //_______________________________________________________________ void DemoDialog::hideEvent( QHideEvent* event ) { emit abortSimulations(); KPageDialog::hideEvent( event ); } } diff --git a/kstyle/demo/oxygenframedemowidget.cpp b/kstyle/demo/oxygenframedemowidget.cpp index 488446b3..03ba3e57 100644 --- a/kstyle/demo/oxygenframedemowidget.cpp +++ b/kstyle/demo/oxygenframedemowidget.cpp @@ -1,169 +1,167 @@ ////////////////////////////////////////////////////////////////////////////// // oxygenframedemowidget.cpp // oxygen frames demo widget // ------------------- // // Copyright (c) 2010 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygenframedemowidget.h" #include "config-liboxygen.h" #include #include #include -#if !OXYGEN_USE_KDE4 #include -#endif namespace Oxygen { //_____________________________________________________________ FrameDemoWidget::FrameDemoWidget( QWidget* parent ): DemoWidget( parent ), posMsg(nullptr), infoMsg(nullptr), warnMsg(nullptr), errMsg(nullptr) { ui.setupUi( this ); QButtonGroup* group = new QButtonGroup( this ); group->addButton( ui.raisedFrameRadioButton ); group->addButton( ui.plainFrameRadioButton ); group->addButton( ui.sunkenFrameRadioButton ); connect( ui.raisedFrameRadioButton, SIGNAL(toggled(bool)), SLOT(toggleRaisedFrame(bool)) ); connect( ui.plainFrameRadioButton, SIGNAL(toggled(bool)), SLOT(togglePlainFrame(bool)) ); connect( ui.sunkenFrameRadioButton, SIGNAL(toggled(bool)), SLOT(toggleSunkenFrame(bool)) ); connect( ui.directionComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateLayoutDirection(int)) ); connect( ui.flatGroupBoxCheckBox, SIGNAL(toggled(bool)), SLOT(toggleFlatGroupBox(bool)) ); addMessages(); -#if !OXYGEN_USE_KDE4 && KWIDGETSADDONS_VERSION < QT_VERSION_CHECK(5, 48, 0) +#if KWIDGETSADDONS_VERSION < QT_VERSION_CHECK(5, 48, 0) qApp->installEventFilter(this); #endif } void FrameDemoWidget::addMessages() { delete posMsg; delete infoMsg; delete warnMsg; delete errMsg; posMsg = new KMessageWidget(QStringLiteral("A positive message"), ui.msgFrame); posMsg->setMessageType(KMessageWidget::Positive); posMsg->setWordWrap(true); posMsg->setIcon(QIcon::fromTheme("dialog-positive")); ui.verticalLayout_5->addWidget(posMsg); infoMsg = new KMessageWidget(QStringLiteral("An information message"), ui.msgFrame); infoMsg->setMessageType(KMessageWidget::Information); infoMsg->setWordWrap(true); infoMsg->setIcon(QIcon::fromTheme("dialog-information")); ui.verticalLayout_5->addWidget(infoMsg); warnMsg = new KMessageWidget(QStringLiteral("A warning message"), ui.msgFrame); warnMsg->setMessageType(KMessageWidget::Warning); warnMsg->setWordWrap(true); warnMsg->setIcon(QIcon::fromTheme("dialog-warning")); ui.verticalLayout_5->addWidget(warnMsg); errMsg = new KMessageWidget(QStringLiteral("An error message"), ui.msgFrame); errMsg->setMessageType(KMessageWidget::Error); errMsg->setWordWrap(true); errMsg->setIcon(QIcon::fromTheme("dialog-error")); ui.verticalLayout_5->addWidget(errMsg); ui.verticalLayout_5->addStretch(); } bool FrameDemoWidget::eventFilter( QObject *obj, QEvent *event ) { -#if !OXYGEN_USE_KDE4 && KWIDGETSADDONS_VERSION < QT_VERSION_CHECK(5, 48, 0) +#if KWIDGETSADDONS_VERSION < QT_VERSION_CHECK(5, 48, 0) if (event->type() == QEvent::DynamicPropertyChange && obj == qApp) { QDynamicPropertyChangeEvent *e = dynamic_cast(event); if (e->propertyName() == QByteArrayLiteral("KDE_COLOR_SCHEME_PATH")) { addMessages(); } } #else Q_UNUSED(obj); Q_UNUSED(event); #endif return false; } //_____________________________________________________________ void FrameDemoWidget::updateLayoutDirection( int value ) { QBoxLayout::Direction direction; switch( value ) { default: case 0: direction = QBoxLayout::LeftToRight; break; case 1: direction = QBoxLayout::RightToLeft; break; case 2: direction = QBoxLayout::TopToBottom; break; case 3: direction = QBoxLayout::BottomToTop; break; } if( direction != ui.frameLayout->direction() ) { ui.frameLayout->setDirection( direction ); ui.frameLayout->update(); } } //_____________________________________________________________ void FrameDemoWidget::benchmark( void ) { if( !isVisible() ) return; if( true ) { simulator().selectComboBoxItem( ui.directionComboBox, 1 ); simulator().selectComboBoxItem( ui.directionComboBox, 2 ); simulator().selectComboBoxItem( ui.directionComboBox, 3 ); simulator().selectComboBoxItem( ui.directionComboBox, 0 ); } if( true ) { simulator().click( ui.flatGroupBoxCheckBox ); simulator().click( ui.flatGroupBoxCheckBox ); } if( true ) { simulator().click( ui.plainFrameRadioButton ); simulator().click( ui.sunkenFrameRadioButton ); simulator().click( ui.raisedFrameRadioButton ); } simulator().run(); } } diff --git a/kstyle/kstylekde4compat.cpp b/kstyle/kstylekde4compat.cpp deleted file mode 100644 index 9b8db594..00000000 --- a/kstyle/kstylekde4compat.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/************************************************************************* - * Copyright (C) 2015 by David Edmundson * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * - *************************************************************************/ - -#include "kstylekde4compat.h" - -#include -#include -#include - -static const QStyle::StyleHint SH_KCustomStyleElement = (QStyle::StyleHint)0xff000001; -static const int X_KdeBase = 0xff000000; - -//_____________________________________________________________________ -KStyleKDE4Compat::KStyleKDE4Compat() -{ - controlCounter = subElementCounter = X_KdeBase; - hintCounter = X_KdeBase + 1; //sic! X_KdeBase is covered by SH_KCustomStyleElement -} - -//_____________________________________________________________________ -static inline int newStyleElement(const QString &element, const char *check, int &counter, QHash *elements) -{ - if (!element.contains(check)) return 0; - - int id = elements->value(element, 0); - if (!id) - { - ++counter; - id = counter; - elements->insert(element, id); - } - return id; -} - -//_____________________________________________________________________ -QStyle::StyleHint KStyleKDE4Compat::newStyleHint(const QString &element) -{ return (StyleHint)newStyleElement(element, "SH_", hintCounter, &styleElements); } - -//_____________________________________________________________________ -QStyle::ControlElement KStyleKDE4Compat::newControlElement(const QString &element) -{ return (ControlElement)newStyleElement(element, "CE_", controlCounter, &styleElements); } - -//_____________________________________________________________________ -QStyle::SubElement KStyleKDE4Compat::newSubElement(const QString &element) -{ return (SubElement)newStyleElement(element, "SE_", subElementCounter, &styleElements); } - -//_____________________________________________________________________ -int KStyleKDE4Compat::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const -{ - - if( hint == SH_KCustomStyleElement && widget ) - { return styleElements.value(widget->objectName(), 0); } - - switch (hint) { - case SH_ItemView_ActivateItemOnSingleClick: { - KConfigGroup g(KSharedConfig::openConfig(), "KDE"); - return g.readEntry("SingleClick", true); - } - - case SH_DialogButtonBox_ButtonsHaveIcons: { - // was KGlobalSettings::showIconsOnPushButtons() : - KConfigGroup g(KSharedConfig::openConfig(), "KDE"); - return g.readEntry("ShowIconsOnPushButtons", true); - } - - case SH_ItemView_ArrowKeysNavigateIntoChildren: - return true; - - case SH_ToolButtonStyle: { - KConfigGroup g(KSharedConfig::openConfig(), "Toolbar style"); - - bool useOthertoolbars = false; - const QWidget *parent = widget ? widget->parentWidget() : nullptr; - - //If the widget parent is a QToolBar and the magic property is set - if (parent && qobject_cast< const QToolBar * >(parent)) { - if (parent->property("otherToolbar").isValid()) { - useOthertoolbars = true; - } - } - - QString buttonStyle; - if (useOthertoolbars) { - buttonStyle = g.readEntry("ToolButtonStyleOtherToolbars", "NoText").toLower(); - } else { - buttonStyle = g.readEntry("ToolButtonStyle", "TextBesideIcon").toLower(); - } - - return buttonStyle == QLatin1String("textbesideicon") ? Qt::ToolButtonTextBesideIcon - : buttonStyle == QLatin1String("icontextright") ? Qt::ToolButtonTextBesideIcon - : buttonStyle == QLatin1String("textundericon") ? Qt::ToolButtonTextUnderIcon - : buttonStyle == QLatin1String("icontextbottom") ? Qt::ToolButtonTextUnderIcon - : buttonStyle == QLatin1String("textonly") ? Qt::ToolButtonTextOnly - : Qt::ToolButtonIconOnly; - } - - default: - break; - }; - - return QCommonStyle::styleHint(hint, option, widget, returnData); -} diff --git a/kstyle/kstylekde4compat.h b/kstyle/kstylekde4compat.h deleted file mode 100644 index 3116b9e7..00000000 --- a/kstyle/kstylekde4compat.h +++ /dev/null @@ -1,60 +0,0 @@ -/************************************************************************* - * Copyright (C) 2015 by David Edmundson * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * - *************************************************************************/ - -/** - * This class copies the features of KF5's KStyle for use in KDE4 only - * - * kdelibs4 also has a KStyle class but this isn't a 1-1 mapping and - * provides a lot of features we do not want - */ - -#ifndef KSTYLE_KDE4_COMPAT_H -#define KSTYLE_KDE4_COMPAT_H - -#include -#include - -class KStyleKDE4Compat : public QCommonStyle -{ - Q_OBJECT - - public: - - //* constructor - KStyleKDE4Compat(); - - //* style hint - int styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *w, QStyleHintReturn *returnData) const override; - - protected: - - StyleHint newStyleHint(const QString &element); - ControlElement newControlElement(const QString &element); - SubElement newSubElement(const QString &element); - - private: - - QHash styleElements; - int hintCounter = 0; - int controlCounter = 0; - int subElementCounter = 0; - -}; - -#endif diff --git a/kstyle/oxygen.h b/kstyle/oxygen.h index b3f76efd..72952a56 100644 --- a/kstyle/oxygen.h +++ b/kstyle/oxygen.h @@ -1,221 +1,211 @@ #ifndef oxygen_h #define oxygen_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include #include #include #include namespace Oxygen { //*@name convenience typedef //@{ - #if QT_VERSION >= 0x050000 //* scoped pointer convenience typedef template using WeakPointer = QPointer; - #else - //* scoped pointer convenience typedef - template using WeakPointer = QWeakPointer; - #endif //* scoped pointer convenience typedef template using ScopedPointer = QScopedPointer; - //* disable QStringLiteral for older Qt version - #if QT_VERSION < 0x050000 - using QStringLiteral = QString; - #endif - //@} //* metrics /*! these are copied from the old KStyle WidgetProperties */ enum Metrics { // frames Frame_FrameWidth = 2, Frame_FrameRadius = 3, // layout Layout_TopLevelMarginWidth = 10, Layout_ChildMarginWidth = 6, Layout_DefaultSpacing = 6, // line editors LineEdit_FrameWidth = 6, // menu items MenuItem_MarginWidth = 3, MenuItem_ItemSpacing = 4, MenuItem_AcceleratorSpace = 16, MenuButton_IndicatorWidth = 20, // combobox ComboBox_FrameWidth = 6, // spinbox SpinBox_FrameWidth = LineEdit_FrameWidth, SpinBox_ArrowButtonWidth = 20, // groupbox title margin GroupBox_TitleMarginWidth = 4, // buttons Button_MinWidth = 80, Button_MarginWidth = 6, Button_ItemSpacing = 4, // tool buttons ToolButton_MarginWidth = 6, ToolButton_ItemSpacing = 4, ToolButton_InlineIndicatorWidth = 12, // checkboxes and radio buttons CheckBox_Size = 23, CheckBox_FocusMarginWidth = 2, CheckBox_ItemSpacing = 6, // menubar items MenuBarItem_MarginWidth = 10, MenuBarItem_MarginHeight = 6, // scrollbars ScrollBar_MinSliderHeight = 21, // toolbars ToolBar_FrameWidth = 2, ToolBar_HandleExtent = 10, ToolBar_HandleWidth = 6, ToolBar_SeparatorWidth = 8, ToolBar_ExtensionWidth = 20, ToolBar_ItemSpacing = 0, // progressbars ProgressBar_BusyIndicatorSize = 14, ProgressBar_Thickness = 6, ProgressBar_ItemSpacing = 4, // mdi title bar TitleBar_MarginWidth = 4, // sliders Slider_TickLength = 8, Slider_TickMarginWidth = 2, Slider_GrooveThickness = 7, Slider_ControlThickness = 21, // tabbar TabBar_TabMarginHeight = 6, TabBar_TabMarginWidth = 12, TabBar_TabMinWidth = 80, TabBar_TabMinHeight = 28, TabBar_TabItemSpacing = 8, TabBar_TabOverlap = 1, TabBar_TabOffset = 4, TabBar_BaseOverlap = 7, // tab widget TabWidget_MarginWidth = 4, // toolbox ToolBox_TabMinWidth = 80, ToolBox_TabItemSpacing = 4, // tooltips ToolTip_FrameWidth = 3, // list headers Header_MarginWidth = 6, Header_ItemSpacing = 4, Header_ArrowSize = 10, // tree view ItemView_ArrowSize = 10, ItemView_ItemMarginWidth = 3, // splitter Splitter_SplitterWidth = 3, }; //* animation mode enum AnimationMode { AnimationNone = 0, AnimationHover = 0x1, AnimationFocus = 0x2, AnimationEnable = 0x4, AnimationPressed = 0x8 }; Q_DECLARE_FLAGS(AnimationModes, AnimationMode) //* arrow orientation enum ArrowOrientation { ArrowNone, ArrowUp, ArrowDown, ArrowLeft, ArrowRight }; //* get polygon corresponding to generic arrow enum ArrowSize { ArrowNormal, ArrowSmall, ArrowTiny }; //* internal option flags to pass arguments around enum StyleOption { Sunken = 0x1, Focus = 0x2, Hover = 0x4, Disabled = 0x8, NoFill = 0x10, HoleOutline = 0x20, HoleContrast = 0x80 }; Q_DECLARE_FLAGS(StyleOptions, StyleOption) //* shadow area enum ShadowArea { ShadowAreaTop, ShadowAreaBottom, ShadowAreaLeft, ShadowAreaRight }; } Q_DECLARE_OPERATORS_FOR_FLAGS( Oxygen::AnimationModes ); Q_DECLARE_OPERATORS_FOR_FLAGS( Oxygen::StyleOptions ); #endif diff --git a/kstyle/oxygenmnemonics.cpp b/kstyle/oxygenmnemonics.cpp index c938e65b..84f55280 100644 --- a/kstyle/oxygenmnemonics.cpp +++ b/kstyle/oxygenmnemonics.cpp @@ -1,104 +1,102 @@ ////////////////////////////////////////////////////////////////////////////// // oxygenmnemonics.cpp // enable/disable mnemonics display // ------------------- // // Copyright (C) 2011 Hugo Pereira Da Costa // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License version 2 as published by the Free Software Foundation. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with this library; see the file COPYING.LIB. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. ////////////////////////////////////////////////////////////////////////////// #include "oxygenmnemonics.h" #include #include namespace Oxygen { //____________________________________________________ void Mnemonics::setMode( int mode ) { switch( mode ) { case StyleConfigData::MN_NEVER: qApp->removeEventFilter( this ); setEnabled( false ); break; default: case StyleConfigData::MN_ALWAYS: qApp->removeEventFilter( this ); setEnabled( true ); break; case StyleConfigData::MN_AUTO: qApp->removeEventFilter( this ); qApp->installEventFilter( this ); setEnabled( false ); break; } return; } //____________________________________________________ bool Mnemonics::eventFilter( QObject*, QEvent* event ) { switch( event->type() ) { case QEvent::KeyPress: if( static_cast(event)->key() == Qt::Key_Alt ) { setEnabled( true ); } break; case QEvent::KeyRelease: if( static_cast(event)->key() == Qt::Key_Alt ) { setEnabled( false ); } break; - #if QT_VERSION >= 0x050000 case QEvent::ApplicationStateChange: { setEnabled( false ); } break; - #endif default: break; } return false; } //____________________________________________________ void Mnemonics::setEnabled( bool value ) { if( _enabled == value ) return; _enabled = value; // update all top level widgets foreach( QWidget* widget, qApp->topLevelWidgets() ) { widget->update(); } } } diff --git a/kstyle/oxygenshadowhelper.cpp b/kstyle/oxygenshadowhelper.cpp index 77bd8e4d..de8faf9d 100644 --- a/kstyle/oxygenshadowhelper.cpp +++ b/kstyle/oxygenshadowhelper.cpp @@ -1,581 +1,577 @@ ////////////////////////////////////////////////////////////////////////////// // oxygenshadowhelper.h // handle shadow pixmaps passed to window manager via X property // ------------------- // // Copyright (c) 2010 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygenshadowhelper.h" #include "oxygenpropertynames.h" #include "oxygenshadowcache.h" #include "oxygenstylehelper.h" #include #include #include #include #include #include #include #if OXYGEN_HAVE_X11 #include #endif #if OXYGEN_HAVE_KWAYLAND #include #include #include #include #include #include #endif namespace Oxygen { const char ShadowHelper::netWMShadowAtomName[] = "_KDE_NET_WM_SHADOW"; //_____________________________________________________ ShadowHelper::ShadowHelper( QObject* parent, StyleHelper& helper ): QObject( parent ), _helper( helper ), _shadowCache( new ShadowCache( helper ) ), _size( 0 ) #if OXYGEN_HAVE_X11 ,_gc( 0 ), _atom( 0 ) #endif #if OXYGEN_HAVE_KWAYLAND , _shadowManager( Q_NULLPTR ) , _shmPool( Q_NULLPTR ) #endif { initializeWayland(); } //_______________________________________________________ ShadowHelper::~ShadowHelper( void ) { #if OXYGEN_HAVE_X11 if( _helper.isX11() ) { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( _helper.connection(), value ); foreach( const quint32& value, _dockPixmaps ) xcb_free_pixmap( _helper.connection(), value ); } #endif delete _shadowCache; } //_______________________________________________________ void ShadowHelper::initializeWayland() { #if OXYGEN_HAVE_KWAYLAND if( !Helper::isWayland() ) return; using namespace KWayland::Client; auto connection = ConnectionThread::fromApplication( this ); if( !connection ) { return; } Registry *registry = new Registry( this ); registry->create( connection ); connect(registry, &Registry::interfacesAnnounced, this, [registry, this] { const auto interface = registry->interface( Registry::Interface::Shadow ); if( interface.name != 0 ) { _shadowManager = registry->createShadowManager( interface.name, interface.version, this ); } const auto shmInterface = registry->interface( Registry::Interface::Shm ); if( shmInterface.name != 0 ) { _shmPool = registry->createShmPool( shmInterface.name, shmInterface.version, this ); } } ); registry->setup(); connection->roundtrip(); #endif } //______________________________________________ void ShadowHelper::reset( void ) { #if OXYGEN_HAVE_X11 if( _helper.isX11() ) { // round pixmaps foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( _helper.connection(), value ); foreach( const quint32& value, _dockPixmaps ) xcb_free_pixmap( _helper.connection(), value ); } #endif _pixmaps.clear(); _dockPixmaps.clear(); _tiles = TileSet(); _dockTiles = TileSet(); // reset size _size = 0; } //_______________________________________________________ bool ShadowHelper::registerWidget( QWidget* widget, bool force ) { // make sure widget is not already registered if( _widgets.contains( widget ) ) return false; // check if widget qualifies if( !( force || acceptWidget( widget ) ) ) { return false; } // try create shadow directly if( installShadows( widget ) ) _widgets.insert( widget, widget->winId() ); else _widgets.insert( widget, 0 ); // install event filter widget->removeEventFilter( this ); widget->installEventFilter( this ); // connect destroy signal connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) ); return true; } //_______________________________________________________ void ShadowHelper::unregisterWidget( QWidget* widget ) { if( _widgets.remove( widget ) ) { uninstallShadows( widget ); } } //_______________________________________________________ void ShadowHelper::reparseCacheConfig( void ) { // shadow cache _shadowCache->readConfig(); } //_______________________________________________________ void ShadowHelper::loadConfig( void ) { // reset reset(); // retrieve shadow pixmap _size = _shadowCache->shadowSize(); QPixmap pixmap( _shadowCache->pixmap( ShadowCache::Key() ) ); const QSize pixmapSize( pixmap.size()/_helper.devicePixelRatio( pixmap ) ); if( !pixmap.isNull() ) { QPainter painter( &pixmap ); // add transparency painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); painter.fillRect( pixmap.rect(), QColor( 0, 0, 0, 150 ) ); } // recreate tileset _tiles = TileSet( pixmap, pixmapSize.width()/2, pixmapSize.height()/2, 1, 1 ); if( !pixmap.isNull() ) { QPainter painter( &pixmap ); // add round corners const QRect cornerRect( (pixmap.width()-10)/2, (pixmap.height()-10)/2, 10, 10 ); _helper.roundCorner( QPalette().color( QPalette::Window ) ).render( cornerRect, &painter ); } // recreate tileset _dockTiles = TileSet( pixmap, pixmapSize.width()/2, pixmapSize.height()/2, 1, 1 ); // update property for registered widgets for( QMap::const_iterator iter = _widgets.constBegin(); iter != _widgets.constEnd(); ++iter ) { installShadows( iter.key() ); } } //_______________________________________________________ bool ShadowHelper::eventFilter( QObject* object, QEvent* event ) { // check event type if( event->type() != QEvent::WinIdChange ) return false; // cast widget QWidget* widget( static_cast( object ) ); // install shadows and update winId if( installShadows( widget ) ) { _widgets.insert( widget, widget->winId() ); } return false; } //_______________________________________________________ void ShadowHelper::objectDeleted( QObject* object ) { _widgets.remove( static_cast( object ) ); } //_______________________________________________________ bool ShadowHelper::isMenu( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::isToolTip( QWidget* widget ) const { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } //_______________________________________________________ bool ShadowHelper::isDockWidget( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::isToolBar( QWidget* widget ) const { return qobject_cast( widget ) || widget->inherits( "Q3ToolBar" ); } //_______________________________________________________ bool ShadowHelper::acceptWidget( QWidget* widget ) const { // flags if( widget->property( PropertyNames::netWMSkipShadow ).toBool() ) return false; if( widget->property( PropertyNames::netWMForceShadow ).toBool() ) return true; // menus if( isMenu( widget ) ) return true; // combobox dropdown lists if( widget->inherits( "QComboBoxPrivateContainer" ) ) return true; // tooltips if( isToolTip( widget ) && !widget->inherits( "Plasma::ToolTip" ) ) { return true; } // detached widgets if( isDockWidget( widget ) || isToolBar( widget ) ) { return true; } // reject return false; } //______________________________________________ const QVector& ShadowHelper::createPixmapHandles( bool isDockWidget ) { /*! shadow atom and property specification available at http://community.kde.org/KWin/Shadow */ // create atom #if OXYGEN_HAVE_X11 if( !_atom && _helper.isX11() ) _atom = _helper.createAtom( QLatin1String( netWMShadowAtomName ) ); #endif // make sure size is valid if( _size <= 0 ) return _pixmaps; // make sure pixmaps are not already initialized if( isDockWidget ) { // make sure pixmaps are not already initialized if( _dockPixmaps.empty() && _dockTiles.isValid() ) { _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 1 ) ) ); _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 2 ) ) ); _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 5 ) ) ); _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 8 ) ) ); _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 7 ) ) ); _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 6 ) ) ); _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 3 ) ) ); _dockPixmaps.append( createPixmap( _dockTiles.pixmap( 0 ) ) ); } } else if( _pixmaps.empty() && _tiles.isValid() ) { _pixmaps.append( createPixmap( _tiles.pixmap( 1 ) ) ); _pixmaps.append( createPixmap( _tiles.pixmap( 2 ) ) ); _pixmaps.append( createPixmap( _tiles.pixmap( 5 ) ) ); _pixmaps.append( createPixmap( _tiles.pixmap( 8 ) ) ); _pixmaps.append( createPixmap( _tiles.pixmap( 7 ) ) ); _pixmaps.append( createPixmap( _tiles.pixmap( 6 ) ) ); _pixmaps.append( createPixmap( _tiles.pixmap( 3 ) ) ); _pixmaps.append( createPixmap( _tiles.pixmap( 0 ) ) ); } // return relevant list of pixmap handles return isDockWidget ? _dockPixmaps:_pixmaps; } //______________________________________________ quint32 ShadowHelper::createPixmap( const QPixmap& source ) { // do nothing for invalid pixmaps if( source.isNull() ) return 0; if( !_helper.isX11() ) return 0; /* in some cases, pixmap handle is invalid. This is the case notably when Qt uses to RasterEngine. In this case, we create an X11 Pixmap explicitly and draw the source pixmap on it. */ #if OXYGEN_HAVE_X11 const int width( source.width() ); const int height( source.height() ); // create X11 pixmap xcb_pixmap_t pixmap = xcb_generate_id( _helper.connection() ); xcb_create_pixmap( _helper.connection(), 32, pixmap, QX11Info::appRootWindow(), width, height ); // create gc if( !_gc ) { _gc = xcb_generate_id( _helper.connection() ); xcb_create_gc( _helper.connection(), _gc, pixmap, 0, 0x0 ); } // create image from QPixmap and assign to pixmap QImage image( source.toImage() ); xcb_put_image( _helper.connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.byteCount(), image.constBits()); return pixmap; #else return 0; #endif } //_______________________________________________________ bool ShadowHelper::installShadows( QWidget* widget ) { if( !widget ) return false; /* From bespin code. Supposibly prevent playing with some 'pseudo-widgets' that have winId matching some other -random- window */ if( !(widget->testAttribute(Qt::WA_WState_Created) && widget->internalWinId() )) { return false; } if( Helper::isX11() ) return installX11Shadows( widget ); if( Helper::isWayland() ) return installWaylandShadows( widget ); return false; } //_______________________________________________________ bool ShadowHelper::installX11Shadows( QWidget* widget ) { #if OXYGEN_HAVE_X11 #ifndef QT_NO_XRENDER // create pixmap handles if needed const bool isDockWidget( this->isDockWidget( widget ) || this->isToolBar( widget ) ); const QVector& pixmaps( createPixmapHandles( isDockWidget ) ); if( pixmaps.size() != numPixmaps ) return false; // create data // add pixmap handles QVector data; foreach( const quint32& value, pixmaps ) { data.append( value ); } const QMargins margins = shadowMargins( widget ); data << int(margins.top()) << int(margins.right()) << int(margins.bottom()) << int(margins.left()); xcb_change_property( _helper.connection(), XCB_PROP_MODE_REPLACE, widget->winId(), _atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData() ); xcb_flush( _helper.connection() ); return true; #endif #endif return false; } //_______________________________________________________ void ShadowHelper::uninstallX11Shadows( QWidget* widget ) const { #if OXYGEN_HAVE_X11 xcb_delete_property( _helper.connection(), widget->winId(), _atom); #else Q_UNUSED( widget ) #endif } //_______________________________________________________ bool ShadowHelper::installWaylandShadows( QWidget* widget ) { #if OXYGEN_HAVE_KWAYLAND if( widget->windowHandle()->parent() ) return false; if( !_shadowManager || !_shmPool ) return false; const bool isDockWidget( this->isDockWidget( widget ) || this->isToolBar( widget ) ); const TileSet &tiles = isDockWidget ? _dockTiles : _tiles; if( !tiles.isValid() ) return false; // create shadow using namespace KWayland::Client; auto s = Surface::fromWindow( widget->windowHandle() ); if( !s ) return false; auto shadow = _shadowManager->createShadow( s, widget ); if( !shadow->isValid() ) return false; // add the shadow elements shadow->attachTop( _shmPool->createBuffer( tiles.pixmap( 1 ).toImage() ) ); shadow->attachTopRight( _shmPool->createBuffer( tiles.pixmap( 2 ).toImage() ) ); shadow->attachRight( _shmPool->createBuffer( tiles.pixmap( 5 ).toImage() ) ); shadow->attachBottomRight( _shmPool->createBuffer( tiles.pixmap( 8 ).toImage() ) ); shadow->attachBottom( _shmPool->createBuffer( tiles.pixmap( 7 ).toImage() ) ); shadow->attachBottomLeft( _shmPool->createBuffer( tiles.pixmap( 6 ).toImage() ) ); shadow->attachLeft( _shmPool->createBuffer( tiles.pixmap( 3 ).toImage() ) ); shadow->attachTopLeft( _shmPool->createBuffer( tiles.pixmap( 0 ).toImage() ) ); shadow->setOffsets( shadowMargins( widget ) ); shadow->commit(); s->commit( Surface::CommitFlag::None ); return true; #else Q_UNUSED( widget ); #endif return false; } //_______________________________________________________ QMargins ShadowHelper::shadowMargins( QWidget* widget ) const { // const qreal devicePixelRatio( _helper.devicePixelRatio( isDockWidget ? // _dockTiles.pixmap( 0 ):_tiles.pixmap( 0 ) ) ); - #if QT_VERSION >= 0x050300 const qreal devicePixelRatio( qApp->devicePixelRatio() ); - #else - const qreal devicePixelRatio( 1.0 ); - #endif // add padding /* in most cases all 4 paddings are identical, since offsets are handled when generating the pixmaps. There is one extra pixel needed with respect to actual shadow size, to deal with how menu backgrounds are rendered. Some special care is needed for QBalloonTip, since the later have an arrow */ int topSize = 0; int rightSize = 0; int bottomSize = 0; int leftSize = 0; if( isToolTip( widget ) && widget->inherits( "QBalloonTip" ) ) { // balloon tip needs special margins to deal with the arrow int top = 0; int bottom = 0; widget->getContentsMargins(nullptr, &top, nullptr, &bottom ); // also need to decrement default size further due to extra hard coded round corner const int size = (_size - 2)*devicePixelRatio; // it seems arrow can be either to the top or the bottom. Adjust margins accordingly if( top > bottom ) { topSize = size - (top - bottom); rightSize = size; bottomSize = size; leftSize = size; } else { topSize = size; rightSize = size; bottomSize = size - (bottom - top); leftSize = size; } } else { const int size = _size*devicePixelRatio; topSize = size; rightSize = size; bottomSize = size; leftSize = size; } return QMargins( leftSize, topSize, rightSize, bottomSize ); } //_______________________________________________________ void ShadowHelper::uninstallShadows( QWidget* widget ) const { if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; if( Helper::isX11() ) uninstallX11Shadows( widget ); if( Helper::isWayland() ) uninstallWaylandShadows( widget ); } //_______________________________________________________ void ShadowHelper::uninstallWaylandShadows( QWidget* widget ) const { #if OXYGEN_HAVE_KWAYLAND if( widget->windowHandle() && widget->windowHandle()->parent() ) return; if( !_shadowManager ) return; using namespace KWayland::Client; auto s = Surface::fromWindow( widget->windowHandle() ); if( !s ) return; _shadowManager->removeShadow( s ); s->commit( Surface::CommitFlag::None ); #else Q_UNUSED( widget ) #endif } } diff --git a/kstyle/oxygenstyle.cpp b/kstyle/oxygenstyle.cpp index 9b407239..57ad8d5e 100644 --- a/kstyle/oxygenstyle.cpp +++ b/kstyle/oxygenstyle.cpp @@ -1,8896 +1,8767 @@ // krazy:excludeall=qclasses ////////////////////////////////////////////////////////////////////////////// // oxygenstyle.cpp // Oxygen widget style for KDE 4 // ------------------- // // Copyright ( C ) 2009-2010 Hugo Pereira Da Costa // Copyright ( C ) 2008 Long Huynh Huu // Copyright ( C ) 2007-2008 Casper Boemann // Copyright ( C ) 2007 Matthew Woehlke // Copyright ( C ) 2003-2005 Sandro Giessl // // based on the KDE style "dotNET": // Copyright ( C ) 2001-2002, Chris Lee // Carsten Pfeiffer // Karol Szwed // Drawing routines completely reimplemented from KDE3 +HighColor, which was // originally based on some stuff from the KDE2 HighColor. // // based on drawing routines of the style "Keramik": // Copyright ( c ) 2002 Malte Starostik // ( c ) 2002,2003 Maksim Orlovich // based on the KDE3 HighColor Style // Copyright ( C ) 2001-2002 Karol Szwed // ( C ) 2001-2002 Fredrik H?glund // Drawing routines adapted from the KDE2 HCStyle, // Copyright ( C ) 2000 Daniel M. Duley // ( C ) 2000 Dirk Mueller // ( C ) 2001 Martijn Klingens // Progressbar code based on KStyle, // Copyright ( C ) 2001-2002 Karol Szwed // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License version 2 as published by the Free Software Foundation. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with this library; see the file COPYING.LIB. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. ////////////////////////////////////////////////////////////////////////////// #include "oxygenstyle.h" #include "oxygen.h" #include "oxygenanimations.h" #include "oxygenblurhelper.h" #include "oxygenframeshadow.h" #include "oxygenmdiwindowshadow.h" #include "oxygenmnemonics.h" #include "oxygenpropertynames.h" #include "oxygenshadowhelper.h" #include "oxygensplitterproxy.h" #include "oxygenstyleconfigdata.h" #include "oxygentransitions.h" #include "oxygenwidgetexplorer.h" #include "oxygenwindowmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace OxygenPrivate { /*! tabBar data class needed for the rendering of tabbars when one tab is being drawn */ class TabBarData: public QObject { public: //* constructor explicit TabBarData( Oxygen::Style* parent ): QObject( parent ), _style( parent ) {} //* assign target tabBar void lock( const QWidget* widget ) { _tabBar = widget; } //* true if tabbar is locked bool locks( const QWidget* widget ) const { return _tabBar && _tabBar.data() == widget; } //* set dirty void setDirty( const bool& value = true ) { _dirty = value; } //* release void release( void ) { _tabBar.clear(); } //* draw tabBarBase virtual void drawTabBarBaseControl( const QStyleOptionTab*, QPainter*, const QWidget* ); private: //* pointer to parent style object Oxygen::WeakPointer _style; //* pointer to target tabBar Oxygen::WeakPointer _tabBar; //* if true, will paint on next TabBarTabShapeControl call bool _dirty = false; }; //* needed to have spacing added to items in combobox class ComboBoxItemDelegate: public QItemDelegate { public: //* constructor ComboBoxItemDelegate( QAbstractItemView* parent ): QItemDelegate( parent ), _proxy( parent->itemDelegate() ), _itemMargin( Oxygen::Metrics::ItemView_ItemMarginWidth ) {} //* paint void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { // call either proxy or parent class if( _proxy ) _proxy.data()->paint( painter, option, index ); else QItemDelegate::paint( painter, option, index ); } //* size hint for index QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override { // get size from either proxy or parent class QSize size( _proxy ? _proxy.data()->sizeHint( option, index ): QItemDelegate::sizeHint( option, index ) ); // adjust and return if( size.isValid() ) { size.rheight() += _itemMargin*2; } return size; } private: //* proxy Oxygen::WeakPointer _proxy; //* margin int _itemMargin; }; } namespace Oxygen { //* toplevel manager class TopLevelManager: public QObject { public: //* constructor TopLevelManager( QObject* parent, const StyleHelper& helper ): QObject( parent ), _helper( helper ) {} //* event filter bool eventFilter(QObject* object, QEvent* event ) override { // cast to QWidget QWidget *widget = static_cast( object ); if( event->type() == QEvent::Show && _helper.hasDecoration( widget ) ) { _helper.setHasBackgroundGradient( widget->winId(), true ); } return false; } private: //* helper const StyleHelper& _helper; }; //______________________________________________________________ Style::Style( void ): - #if OXYGEN_USE_KDE4 - _helper( new StyleHelper( "oxygen" ) ) - #else _helper( new StyleHelper( StyleConfigData::self()->sharedConfig() ) ) - #endif ,_shadowHelper( new ShadowHelper( this, *_helper ) ) ,_animations( new Animations( this ) ) ,_transitions( new Transitions( this ) ) ,_windowManager( new WindowManager( this ) ) ,_topLevelManager( new TopLevelManager( this, *_helper ) ) ,_frameShadowFactory( new FrameShadowFactory( this ) ) ,_mdiWindowShadowFactory( new MdiWindowShadowFactory( this, *_helper ) ) ,_mnemonics( new Mnemonics( this ) ) ,_blurHelper( new BlurHelper( this, *_helper ) ) ,_widgetExplorer( new WidgetExplorer( this ) ) ,_tabBarData( new OxygenPrivate::TabBarData( this ) ) ,_splitterFactory( new SplitterFactory( this ) ) ,SH_ArgbDndWindow( newStyleHint( QStringLiteral( "SH_ArgbDndWindow" ) ) ) ,CE_CapacityBar( newControlElement( QStringLiteral( "CE_CapacityBar" ) ) ) { // use DBus connection to update on oxygen configuration change QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.connect( QString(), QStringLiteral( "/OxygenStyle" ), QStringLiteral( "org.kde.Oxygen.Style" ), QStringLiteral( "reparseConfiguration" ), this, SLOT(configurationChanged()) ); // call the slot directly; this initial call will set up things that also // need to be reset when the system palette changes loadConfiguration(); } //______________________________________________________________ Style::~Style( void ) { // _shadowHelper is a child of us, but its destructor uses _helper so we // delete it manually to ensure it is deleted *before* _helper is // deleted delete _shadowHelper; delete _helper; } //______________________________________________________________ void Style::polish( QWidget* widget ) { if( !widget ) return; // register widget to animations _animations->registerWidget( widget ); _transitions->registerWidget( widget ); _windowManager->registerWidget( widget ); _frameShadowFactory->registerWidget( widget, *_helper ); _mdiWindowShadowFactory->registerWidget( widget ); _shadowHelper->registerWidget( widget ); _splitterFactory->registerWidget( widget ); // scroll areas if( QAbstractScrollArea* scrollArea = qobject_cast( widget ) ) { polishScrollArea( scrollArea ); } // several widgets set autofill background to false, which effectively breaks the background // gradient rendering. Instead of patching all concerned applications, // we change the background here if( widget->inherits( "MessageList::Core::Widget" ) ) { widget->setAutoFillBackground( false ); } // adjust layout for K3B themed headers // FIXME: to be removed when fixed upstream if( widget->inherits( "K3b::ThemedHeader" ) && widget->layout() ) { widget->layout()->setMargin( 0 ); _frameShadowFactory->setHasContrast( widget, true ); } // adjust flags for windows and dialogs switch( widget->windowFlags() & Qt::WindowType_Mask ) { case Qt::Window: case Qt::Dialog: // set background as styled widget->setAttribute( Qt::WA_StyledBackground ); widget->installEventFilter( _topLevelManager ); break; default: break; } // enforce translucency for drag and drop window if( widget->testAttribute( Qt::WA_X11NetWmWindowTypeDND ) && _helper->compositingActive() ) { widget->setAttribute( Qt::WA_TranslucentBackground ); widget->clearMask(); } if( qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || widget->inherits( "KTextEditor::View" ) ) { widget->setAttribute( Qt::WA_Hover ); } // transparent tooltips if( widget->inherits( "QTipLabel" ) ) { widget->setAttribute( Qt::WA_TranslucentBackground ); #ifdef Q_WS_WIN //FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly widget->setWindowFlags( widget->windowFlags() | Qt::FramelessWindowHint ); #endif } if( QAbstractItemView *itemView = qobject_cast( widget ) ) { // enable hover effects in itemviews' viewport itemView->viewport()->setAttribute( Qt::WA_Hover ); } else if( QAbstractScrollArea* scrollArea = qobject_cast( widget ) ) { // enable hover effect in sunken scrollareas that support focus if( scrollArea->frameShadow() == QFrame::Sunken && widget->focusPolicy()&Qt::StrongFocus ) { widget->setAttribute( Qt::WA_Hover ); } } else if( QGroupBox* groupBox = qobject_cast( widget ) ) { // checkable group boxes if( groupBox->isCheckable() ) { groupBox->setAttribute( Qt::WA_Hover ); } } else if( qobject_cast( widget ) && qobject_cast( widget->parent() ) ) { widget->setAttribute( Qt::WA_Hover ); } else if( qobject_cast( widget ) && qobject_cast( widget->parent() ) ) { widget->setAttribute( Qt::WA_Hover ); } if( qobject_cast( widget ) ) { if( qobject_cast( widget->parent() ) ) { // this hack is needed to have correct text color // rendered in toolbars. This does not really update nicely when changing styles // but is the best I can do for now since setting the palette color at painting // time is not doable QPalette palette( widget->palette() ); palette.setColor( QPalette::Disabled, QPalette::ButtonText, palette.color( QPalette::Disabled, QPalette::WindowText ) ); palette.setColor( QPalette::Active, QPalette::ButtonText, palette.color( QPalette::Active, QPalette::WindowText ) ); palette.setColor( QPalette::Inactive, QPalette::ButtonText, palette.color( QPalette::Inactive, QPalette::WindowText ) ); widget->setPalette( palette ); } widget->setBackgroundRole( QPalette::NoRole ); if( widget->parentWidget() && widget->parentWidget()->parentWidget() && widget->parentWidget()->parentWidget()->inherits( "Gwenview::SideBarGroup" ) ) { widget->setProperty( PropertyNames::toolButtonAlignment, Qt::AlignLeft ); } } else if( qobject_cast( widget ) ) { widget->setBackgroundRole( QPalette::NoRole ); } else if( widget->inherits( "KMultiTabBar" ) ) { // kMultiTabBar margins are set to unity for alignment // with ( usually sunken ) neighbor frames widget->setContentsMargins( 1, 1, 1, 1 ); } else if( qobject_cast( widget ) ) { widget->setBackgroundRole( QPalette::NoRole ); addEventFilter( widget ); } else if( qobject_cast( widget ) ) { addEventFilter( widget ); } else if( widget->inherits( "QTipLabel" ) ) { widget->setBackgroundRole( QPalette::NoRole ); widget->setAttribute( Qt::WA_TranslucentBackground ); #ifdef Q_WS_WIN //FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly widget->setWindowFlags( widget->windowFlags() | Qt::FramelessWindowHint ); #endif } else if( qobject_cast( widget ) ) { widget->setAttribute( Qt::WA_OpaquePaintEvent, false ); // when painted in konsole, one needs to paint the window background below // the scrollarea, otherwise an ugly flat background is used if( widget->parent() && widget->parent()->inherits( "Konsole::TerminalDisplay" ) ) { addEventFilter( widget ); } } else if( qobject_cast( widget ) ) { widget->setBackgroundRole( QPalette::NoRole ); widget->setContentsMargins( 3,3,3,3 ); addEventFilter( widget ); } else if( qobject_cast( widget ) ) { widget->setAutoFillBackground( false ); addEventFilter( widget ); } else if( qobject_cast( widget ) ) { widget->setBackgroundRole( QPalette::NoRole ); widget->setAutoFillBackground( false ); widget->setContentsMargins( 5,5,5,5 ); addEventFilter( widget ); } else if( widget->parentWidget() && widget->parentWidget()->parentWidget() && qobject_cast( widget->parentWidget()->parentWidget()->parentWidget() ) ) { widget->setBackgroundRole( QPalette::NoRole ); widget->setAutoFillBackground( false ); widget->parentWidget()->setAutoFillBackground( false ); } else if( qobject_cast( widget ) ) { widget->setAttribute( Qt::WA_TranslucentBackground ); #ifdef Q_WS_WIN //FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly widget->setWindowFlags( widget->windowFlags() | Qt::FramelessWindowHint ); #endif - #if QT_VERSION >= 0x050000 } else if( qobject_cast( widget ) ) { addEventFilter( widget ); - #endif + } else if( QComboBox *comboBox = qobject_cast( widget ) ) { if( !hasParent( widget, "QWebView" ) ) { QAbstractItemView *itemView( comboBox->view() ); if( itemView && itemView->itemDelegate() && itemView->itemDelegate()->inherits( "QComboBoxDelegate" ) ) { itemView->setItemDelegate( new OxygenPrivate::ComboBoxItemDelegate( itemView ) ); } } } else if( widget->inherits( "QComboBoxPrivateContainer" ) ) { addEventFilter( widget ); widget->setAttribute( Qt::WA_TranslucentBackground ); #ifdef Q_WS_WIN //FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly widget->setWindowFlags( widget->windowFlags() | Qt::FramelessWindowHint ); #endif } else if( qobject_cast( widget ) && widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ) { widget->setAutoFillBackground( false ); widget->setBackgroundRole( QPalette::Window ); } // base class polishing - ParentStyleClass::polish( widget ); + KStyle::polish( widget ); } //_______________________________________________________________ void Style::unpolish( QWidget* widget ) { // register widget to animations _animations->unregisterWidget( widget ); _transitions->unregisterWidget( widget ); _windowManager->unregisterWidget( widget ); _frameShadowFactory->unregisterWidget( widget ); _mdiWindowShadowFactory->unregisterWidget( widget ); _shadowHelper->unregisterWidget( widget ); _splitterFactory->unregisterWidget( widget ); _blurHelper->unregisterWidget( widget ); // event filters switch( widget->windowFlags() & Qt::WindowType_Mask ) { case Qt::Window: case Qt::Dialog: widget->removeEventFilter( this ); widget->setAttribute( Qt::WA_StyledBackground, false ); break; default: break; } // checkable group boxes if( QGroupBox* groupBox = qobject_cast( widget ) ) { if( groupBox->isCheckable() ) { groupBox->setAttribute( Qt::WA_Hover, false ); } } // hover flags if( qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) ) { widget->setAttribute( Qt::WA_Hover, false ); } // checkable group boxes if( QGroupBox* groupBox = qobject_cast( widget ) ) { if( groupBox->isCheckable() ) { groupBox->setAttribute( Qt::WA_Hover, false ); } } if( qobject_cast( widget ) || qobject_cast( widget ) || ( widget && qobject_cast( widget->parent() ) ) || qobject_cast( widget ) ) { widget->setBackgroundRole( QPalette::Button ); widget->removeEventFilter( this ); widget->clearMask(); } if( qobject_cast( widget ) ) { widget->removeEventFilter( this ); } else if( widget->inherits( "QTipLabel" ) ) { widget->setAttribute( Qt::WA_PaintOnScreen, false ); widget->setAttribute( Qt::WA_NoSystemBackground, false ); widget->clearMask(); } else if( qobject_cast( widget ) ) { widget->setAttribute( Qt::WA_OpaquePaintEvent ); } else if( qobject_cast( widget ) ) { widget->setContentsMargins( 0,0,0,0 ); widget->clearMask(); } else if( qobject_cast( widget ) ) { widget->setBackgroundRole( QPalette::Button ); widget->setContentsMargins( 0,0,0,0 ); widget->removeEventFilter( this ); } else if( qobject_cast( widget ) ) { widget->setAttribute( Qt::WA_PaintOnScreen, false ); widget->setAttribute( Qt::WA_NoSystemBackground, false ); widget->clearMask(); } else if( widget->inherits( "QComboBoxPrivateContainer" ) ) widget->removeEventFilter( this ); - ParentStyleClass::unpolish( widget ); + KStyle::unpolish( widget ); } //______________________________________________________________ int Style::pixelMetric( PixelMetric metric, const QStyleOption* option, const QWidget* widget ) const { // handle special cases switch( metric ) { case PM_DefaultFrameWidth: if( qobject_cast( widget ) ) return Metrics::LineEdit_FrameWidth; - #if QT_VERSION >= 0x050000 else if( isQtQuickControl( option, widget ) ) { const QString &elementType = option->styleObject->property( "elementType" ).toString(); if( elementType == QLatin1String( "edit" ) || elementType == QLatin1String( "spinbox" ) ) { return Metrics::LineEdit_FrameWidth; } else if( elementType == QLatin1String( "combobox" ) ) { return Metrics::ComboBox_FrameWidth; } } - #endif // fallback return Metrics::Frame_FrameWidth; case PM_ComboBoxFrameWidth: { const QStyleOptionComboBox* comboBoxOption( qstyleoption_cast< const QStyleOptionComboBox*>( option ) ); return comboBoxOption && comboBoxOption->editable ? Metrics::LineEdit_FrameWidth : Metrics::ComboBox_FrameWidth; } case PM_SpinBoxFrameWidth: return Metrics::SpinBox_FrameWidth; case PM_ToolBarFrameWidth: return Metrics::ToolBar_FrameWidth; case PM_ToolTipLabelFrameWidth: return Metrics::ToolTip_FrameWidth; // layout case PM_LayoutLeftMargin: case PM_LayoutTopMargin: case PM_LayoutRightMargin: case PM_LayoutBottomMargin: { /* use either Child margin or TopLevel margin, depending on widget type */ if( ( option && ( option->state & QStyle::State_Window ) ) || ( widget && widget->isWindow() ) ) { return Metrics::Layout_TopLevelMarginWidth; } else { return Metrics::Layout_ChildMarginWidth; } } case PM_LayoutHorizontalSpacing: return Metrics::Layout_DefaultSpacing; case PM_LayoutVerticalSpacing: return Metrics::Layout_DefaultSpacing; // buttons case PM_ButtonMargin: { /* HACK: needs special case for kcalc buttons, to prevent the application to set too small margins */ if( widget && widget->inherits( "KCalcButton" ) ) return Metrics::Button_MarginWidth + 4; else return Metrics::Button_MarginWidth; } // buttons case PM_ButtonDefaultIndicator: return 0; case PM_ButtonShiftHorizontal: return 0; case PM_ButtonShiftVertical: return 0; // menubars case PM_MenuBarPanelWidth: return 0; case PM_MenuBarHMargin: return 0; case PM_MenuBarVMargin: return 0; case PM_MenuBarItemSpacing: return 0; case PM_MenuDesktopFrameWidth: return 0; // menu buttons case PM_MenuButtonIndicator: return Metrics::MenuButton_IndicatorWidth; // toolbars case PM_ToolBarHandleExtent: return Metrics::ToolBar_HandleExtent; case PM_ToolBarSeparatorExtent: return Metrics::ToolBar_SeparatorWidth; case PM_ToolBarExtensionExtent: return pixelMetric( PM_SmallIconSize, option, widget ) + 2*Metrics::ToolButton_MarginWidth; case PM_ToolBarItemMargin: return 0; case PM_ToolBarItemSpacing: return Metrics::ToolBar_ItemSpacing; // tabbars case PM_TabBarTabShiftVertical: return 0; case PM_TabBarTabShiftHorizontal: return 0; case PM_TabBarTabOverlap: return Metrics::TabBar_TabOverlap; case PM_TabBarBaseOverlap: return Metrics::TabBar_BaseOverlap; case PM_TabBarTabHSpace: return 2*Metrics::TabBar_TabMarginWidth; case PM_TabBarTabVSpace: return 2*Metrics::TabBar_TabMarginHeight; case PM_TabCloseIndicatorWidth: case PM_TabCloseIndicatorHeight: return pixelMetric( PM_SmallIconSize, option, widget ); // scrollbars case PM_ScrollBarExtent: return StyleConfigData::scrollBarWidth() + 2; case PM_ScrollBarSliderMin: return Metrics::ScrollBar_MinSliderHeight; // title bar case PM_TitleBarHeight: return 2*Metrics::TitleBar_MarginWidth + pixelMetric( PM_SmallIconSize, option, widget ); // sliders case PM_SliderThickness: return Metrics::Slider_ControlThickness; case PM_SliderControlThickness: return Metrics::Slider_ControlThickness; case PM_SliderLength: return Metrics::Slider_ControlThickness; // checkboxes and radio buttons case PM_IndicatorWidth: return Metrics::CheckBox_Size; case PM_IndicatorHeight: return Metrics::CheckBox_Size; case PM_ExclusiveIndicatorWidth: return Metrics::CheckBox_Size; case PM_ExclusiveIndicatorHeight: return Metrics::CheckBox_Size; // list heaaders case PM_HeaderMarkSize: return Metrics::Header_ArrowSize; case PM_HeaderMargin: return Metrics::Header_MarginWidth; // dock widget // return 0 here, since frame is handled directly in polish case PM_DockWidgetFrameWidth: return 0; case PM_DockWidgetTitleMargin: return Metrics::Frame_FrameWidth; case PM_DockWidgetTitleBarButtonMargin: return Metrics::ToolButton_MarginWidth; case PM_SplitterWidth: return Metrics::Splitter_SplitterWidth; case PM_DockWidgetSeparatorExtent: return Metrics::Splitter_SplitterWidth; // spacing between widget and scrollbars case PM_ScrollView_ScrollBarSpacing: if( const QFrame* frame = qobject_cast( widget ) ) { const bool framed( frame->frameShape() != QFrame::NoFrame ); return framed ? -1:0; } else return -1; // fallback - default: return ParentStyleClass::pixelMetric( metric, option, widget ); + default: return KStyle::pixelMetric( metric, option, widget ); } } //______________________________________________________________ int Style::styleHint( StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData ) const { /* special cases, that cannot be registered in styleHint map, because of conditional statements */ switch( hint ) { case SH_RubberBand_Mask: { if( QStyleHintReturnMask *mask = qstyleoption_cast( returnData ) ) { mask->region = option->rect; // need to check on widget before removing inner region // in order to still preserve rubberband in MainWindow and QGraphicsView // in QMainWindow because it looks better // in QGraphicsView because the painting fails completely otherwise if( widget && ( qobject_cast( widget->parent() ) || qobject_cast( widget->parent() ) || qobject_cast( widget->parent() ) ) ) { return true; } // also check if widget's parent is some itemView viewport if( widget && widget->parent() && qobject_cast( widget->parent()->parent() ) && static_cast( widget->parent()->parent() )->viewport() == widget->parent() ) { return true; } // mask out center mask->region -= insideMargin( option->rect, 1 ); return true; } return false; } case SH_ToolTip_Mask: case SH_Menu_Mask: { if( !_helper->hasAlphaChannel( widget ) && ( !widget || widget->isWindow() ) ) { // mask should be set only if compositing is disabled if( QStyleHintReturnMask *mask = qstyleoption_cast( returnData ) ) { mask->region = _helper->roundedMask( option->rect ); } } return true; } // mouse tracking case SH_ComboBox_ListMouseTracking: return true; case SH_MenuBar_MouseTracking: return true; case SH_Menu_MouseTracking: return true; case SH_Menu_SubMenuPopupDelay: return 150; case SH_Menu_SloppySubMenus: return true; case SH_ToolBox_SelectedPageTitleBold: return false; - #if QT_VERSION >= 0x050000 case SH_Widget_Animate: return StyleConfigData::animationsEnabled(); case SH_Menu_SupportsSections: return true; - #endif case SH_TitleBar_NoBorder: return false; case SH_GroupBox_TextLabelVerticalAlignment: return Qt::AlignVCenter; case SH_ScrollBar_MiddleClickAbsolutePosition: return true; case SH_ScrollView_FrameOnlyAroundContents: return true; case SH_FormLayoutFormAlignment: return Qt::AlignLeft | Qt::AlignTop; case SH_FormLayoutLabelAlignment: return Qt::AlignRight; case SH_FormLayoutFieldGrowthPolicy: return QFormLayout::ExpandingFieldsGrow; case SH_FormLayoutWrapPolicy: return QFormLayout::DontWrapRows; case SH_MessageBox_TextInteractionFlags: return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; case SH_RequestSoftwareInputPanel: return RSIP_OnMouseClick; case SH_ProgressDialog_CenterCancelButton: case SH_MessageBox_CenterButtons: return false; - default: return ParentStyleClass::styleHint( hint, option, widget, returnData ); + default: return KStyle::styleHint( hint, option, widget, returnData ); } } //______________________________________________________________ QRect Style::subElementRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const { switch( element ) { case SE_PushButtonContents: return pushButtonContentsRect( option, widget ); case SE_CheckBoxContents: return checkBoxContentsRect( option, widget ); case SE_RadioButtonContents: return checkBoxContentsRect( option, widget ); case SE_LineEditContents: return lineEditContentsRect( option, widget ); case SE_ProgressBarGroove: return progressBarGrooveRect( option, widget ); case SE_ProgressBarContents: return progressBarContentsRect( option, widget ); case SE_ProgressBarLabel: return defaultSubElementRect( option, widget ); case SE_HeaderArrow: return headerArrowRect( option, widget ); case SE_HeaderLabel: return headerLabelRect( option, widget ); case SE_TabBarTabLeftButton: return tabBarTabLeftButtonRect( option, widget ); case SE_TabBarTabRightButton: return tabBarTabRightButtonRect( option, widget ); case SE_TabWidgetTabBar: return tabWidgetTabBarRect( option, widget ); case SE_TabWidgetTabContents: return tabWidgetTabContentsRect( option, widget ); case SE_TabWidgetTabPane: return tabWidgetTabPaneRect( option, widget ); case SE_TabWidgetLeftCorner: return tabWidgetCornerRect( SE_TabWidgetLeftCorner, option, widget ); case SE_TabWidgetRightCorner: return tabWidgetCornerRect( SE_TabWidgetRightCorner, option, widget ); case SE_ToolBoxTabContents: return toolBoxTabContentsRect( option, widget ); - default: return ParentStyleClass::subElementRect( element, option, widget ); + default: return KStyle::subElementRect( element, option, widget ); } } //______________________________________________________________ QRect Style::subControlRect( ComplexControl element, const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { switch( element ) { case CC_GroupBox: return groupBoxSubControlRect( option, subControl, widget ); case CC_ToolButton: return toolButtonSubControlRect( option, subControl, widget ); case CC_ComboBox: return comboBoxSubControlRect( option, subControl, widget ); case CC_SpinBox: return spinBoxSubControlRect( option, subControl, widget ); case CC_ScrollBar: return scrollBarSubControlRect( option, subControl, widget ); case CC_Slider: return sliderSubControlRect( option, subControl, widget ); // fallback - default: return ParentStyleClass::subControlRect( element, option, subControl, widget ); + default: return KStyle::subControlRect( element, option, subControl, widget ); } } //______________________________________________________________ QSize Style::sizeFromContents( ContentsType element, const QStyleOption* option, const QSize& size, const QWidget* widget ) const { switch( element ) { case CT_CheckBox: return checkBoxSizeFromContents( option, size, widget ); case CT_RadioButton: return checkBoxSizeFromContents( option, size, widget ); case CT_LineEdit: return lineEditSizeFromContents( option, size, widget ); case CT_ComboBox: return comboBoxSizeFromContents( option, size, widget ); case CT_SpinBox: return spinBoxSizeFromContents( option, size, widget ); case CT_Slider: return sliderSizeFromContents( option, size, widget ); case CT_PushButton: return pushButtonSizeFromContents( option, size, widget ); case CT_ToolButton: return toolButtonSizeFromContents( option, size, widget ); case CT_MenuBar: return defaultSizeFromContents( option, size, widget ); case CT_MenuBarItem: return menuBarItemSizeFromContents( option, size, widget ); case CT_MenuItem: return menuItemSizeFromContents( option, size, widget ); case CT_TabWidget: return tabWidgetSizeFromContents( option, size, widget ); case CT_TabBarTab: return tabBarTabSizeFromContents( option, size, widget ); case CT_HeaderSection: return headerSectionSizeFromContents( option, size, widget ); case CT_ItemViewItem: return itemViewItemSizeFromContents( option, size, widget ); - default: return ParentStyleClass::sizeFromContents( element, option, size, widget ); + default: return KStyle::sizeFromContents( element, option, size, widget ); } } //______________________________________________________________ QStyle::SubControl Style::hitTestComplexControl( ComplexControl control, const QStyleOptionComplex* option, const QPoint& point, const QWidget* widget ) const { switch( control ) { case CC_ScrollBar: { QRect grooveRect = subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ); if( grooveRect.contains( point ) ) { //Must be either page up/page down, or just click on the slider. //Grab the slider to compare QRect sliderRect = subControlRect( CC_ScrollBar, option, SC_ScrollBarSlider, widget ); if( sliderRect.contains( point ) ) return SC_ScrollBarSlider; else if( preceeds( point, sliderRect, option ) ) return SC_ScrollBarSubPage; else return SC_ScrollBarAddPage; } //This is one of the up/down buttons. First, decide which one it is. if( preceeds( point, grooveRect, option ) ) { if( _subLineButtons == DoubleButton ) { QRect buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarSubLine ); return scrollBarHitTest( buttonRect, point, option ); } else return SC_ScrollBarSubLine; } if( _addLineButtons == DoubleButton ) { QRect buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarAddLine ); return scrollBarHitTest( buttonRect, point, option ); } else return SC_ScrollBarAddLine; } // fallback - default: return ParentStyleClass::hitTestComplexControl( control, option, point, widget ); + default: return KStyle::hitTestComplexControl( control, option, point, widget ); } } //______________________________________________________________ void Style::drawPrimitive( PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { StylePrimitive fcn( nullptr ); switch( element ) { case PE_PanelButtonCommand: fcn = &Style::drawPanelButtonCommandPrimitive; break; case PE_PanelButtonTool: fcn = &Style::drawPanelButtonToolPrimitive; break; case PE_PanelScrollAreaCorner: fcn = &Style::drawPanelScrollAreaCornerPrimitive; break; case PE_PanelMenu: fcn = &Style::drawPanelMenuPrimitive; break; case PE_PanelTipLabel: fcn = &Style::drawPanelTipLabelPrimitive; break; case PE_PanelItemViewItem: fcn = &Style::drawPanelItemViewItemPrimitive; break; case PE_IndicatorCheckBox: fcn = &Style::drawIndicatorCheckBoxPrimitive; break; case PE_IndicatorRadioButton: fcn = &Style::drawIndicatorRadioButtonPrimitive; break; case PE_IndicatorButtonDropDown: fcn = &Style::drawIndicatorButtonDropDownPrimitive; break; case PE_IndicatorTabClose: fcn = &Style::drawIndicatorTabClosePrimitive; break; case PE_IndicatorTabTear: fcn = &Style::drawIndicatorTabTearPrimitive; break; case PE_IndicatorArrowUp: fcn = &Style::drawIndicatorArrowUpPrimitive; break; case PE_IndicatorArrowDown: fcn = &Style::drawIndicatorArrowDownPrimitive; break; case PE_IndicatorArrowLeft: fcn = &Style::drawIndicatorArrowLeftPrimitive; break; case PE_IndicatorArrowRight: fcn = &Style::drawIndicatorArrowRightPrimitive; break; case PE_IndicatorMenuCheckMark: fcn = &Style::drawIndicatorMenuCheckMarkPrimitive; break; case PE_IndicatorHeaderArrow: fcn = &Style::drawIndicatorHeaderArrowPrimitive; break; case PE_IndicatorToolBarHandle: fcn = &Style::drawIndicatorToolBarHandlePrimitive; break; case PE_IndicatorToolBarSeparator: fcn = &Style::drawIndicatorToolBarSeparatorPrimitive; break; case PE_IndicatorBranch: fcn = &Style::drawIndicatorBranchPrimitive; break; case PE_IndicatorDockWidgetResizeHandle: fcn = &Style::drawIndicatorDockWidgetResizeHandlePrimitive; break; case PE_FrameStatusBar: fcn = &Style::emptyPrimitive; break; case PE_Frame: fcn = &Style::drawFramePrimitive; break; case PE_FrameLineEdit: fcn = &Style::drawFrameLineEditPrimitive; break; case PE_FrameMenu: fcn = &Style::drawFrameMenuPrimitive; break; case PE_FrameGroupBox: fcn = &Style::drawFrameGroupBoxPrimitive; break; case PE_FrameTabWidget: fcn = &Style::drawFrameTabWidgetPrimitive; break; case PE_FrameTabBarBase: fcn = &Style::drawFrameTabBarBasePrimitive; break; case PE_FrameWindow: fcn = &Style::drawFrameWindowPrimitive; break; case PE_FrameFocusRect: fcn = _frameFocusPrimitive; break; case PE_Widget: fcn = &Style::drawWidgetPrimitive; break; // fallback default: break; } painter->save(); // call function if implemented if( !( fcn && ( this->*fcn )( option, painter, widget ) ) ) - { ParentStyleClass::drawPrimitive( element, option, painter, widget ); } + { KStyle::drawPrimitive( element, option, painter, widget ); } painter->restore(); } //______________________________________________________________ void Style::drawControl( ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { StyleControl fcn( nullptr ); if( element == CE_CapacityBar ) { fcn = &Style::drawProgressBarControl; } else switch( element ) { case CE_ComboBoxLabel: break; case CE_DockWidgetTitle: fcn = &Style::drawDockWidgetTitleControl; break; case CE_HeaderEmptyArea: fcn = &Style::drawHeaderEmptyAreaControl; break; case CE_HeaderLabel: break; case CE_HeaderSection: fcn = &Style::drawHeaderSectionControl; break; case CE_MenuBarEmptyArea: fcn = &Style::emptyControl; break; case CE_MenuBarItem: fcn = &Style::drawMenuBarItemControl; break; case CE_MenuItem: fcn = &Style::drawMenuItemControl; break; case CE_ProgressBar: fcn = &Style::drawProgressBarControl; break; case CE_ProgressBarContents: fcn = &Style::drawProgressBarContentsControl; break; case CE_ProgressBarGroove: fcn = &Style::drawProgressBarGrooveControl; break; case CE_ProgressBarLabel: fcn = &Style::drawProgressBarLabelControl; break; case CE_PushButtonBevel: fcn = &Style::drawPanelButtonCommandPrimitive; break; case CE_PushButtonLabel: fcn = &Style::drawPushButtonLabelControl; break; case CE_RubberBand: fcn = &Style::drawRubberBandControl; break; case CE_ScrollBarSlider: fcn = &Style::drawScrollBarSliderControl; break; case CE_ScrollBarAddLine: fcn = &Style::drawScrollBarAddLineControl; break; case CE_ScrollBarSubLine: fcn = &Style::drawScrollBarSubLineControl; break; case CE_ScrollBarAddPage: fcn = &Style::emptyControl; break; case CE_ScrollBarSubPage: fcn = &Style::emptyControl; break; case CE_ShapedFrame: fcn = &Style::drawShapedFrameControl; break; case CE_SizeGrip: fcn = &Style::emptyControl; break; case CE_Splitter: fcn = &Style::drawSplitterControl; break; case CE_TabBarTabLabel: fcn = &Style::drawTabBarTabLabelControl; break; case CE_TabBarTabShape: fcn = &Style::drawTabBarTabShapeControl; break; case CE_ToolBar: fcn = &Style::drawToolBarControl; break; case CE_ToolBoxTabLabel: fcn = &Style::drawToolBoxTabLabelControl; break; case CE_ToolBoxTabShape: fcn = &Style::drawToolBoxTabShapeControl; break; case CE_ToolButtonLabel: fcn = &Style::drawToolButtonLabelControl; break; default: break; } painter->save(); // call function if implemented if( !( fcn && ( this->*fcn )( option, painter, widget ) ) ) - { ParentStyleClass::drawControl( element, option, painter, widget ); } + { KStyle::drawControl( element, option, painter, widget ); } painter->restore(); } //______________________________________________________________ void Style::drawComplexControl( ComplexControl element, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { StyleComplexControl fcn( nullptr ); switch( element ) { case CC_GroupBox: break; case CC_ToolButton: fcn = &Style::drawToolButtonComplexControl; break; case CC_ComboBox: fcn = &Style::drawComboBoxComplexControl; break; case CC_SpinBox: fcn = &Style::drawSpinBoxComplexControl; break; case CC_Slider: fcn = &Style::drawSliderComplexControl; break; case CC_Dial: fcn = &Style::drawDialComplexControl; break; case CC_ScrollBar: fcn = &Style::drawScrollBarComplexControl; break; case CC_TitleBar: fcn = &Style::drawTitleBarComplexControl; break; // fallback default: break; } painter->save(); // call function if implemented if( !( fcn && ( this->*fcn )( option, painter, widget ) ) ) - { ParentStyleClass::drawComplexControl( element, option, painter, widget ); } + { KStyle::drawComplexControl( element, option, painter, widget ); } painter->restore(); } //___________________________________________________________________________________ void Style::drawItemText( QPainter* painter, const QRect& rect, int flags, const QPalette& palette, bool enabled, const QString &text, QPalette::ColorRole textRole ) const { // hide mnemonics if requested if( !_mnemonics->enabled() && ( flags&Qt::TextShowMnemonic ) && !( flags&Qt::TextHideMnemonic ) ) { flags &= ~Qt::TextShowMnemonic; flags |= Qt::TextHideMnemonic; } // make sure vertical alignment is defined // fallback on Align::VCenter if not if( !(flags&Qt::AlignVertical_Mask) ) flags |= Qt::AlignVCenter; if( _animations->widgetEnableStateEngine().enabled() ) { /* check if painter engine is registered to widgetEnableStateEngine, and animated if yes, merge the palettes. Note: a static_cast is safe here, since only the address of the pointer is used, not the actual content. */ const QWidget* widget( static_cast( painter->device() ) ); if( _animations->widgetEnableStateEngine().isAnimated( widget, AnimationEnable ) ) { const QPalette copy( _helper->disabledPalette( palette, _animations->widgetEnableStateEngine().opacity( widget, AnimationEnable ) ) ); - return ParentStyleClass::drawItemText( painter, rect, flags, copy, enabled, text, textRole ); + return KStyle::drawItemText( painter, rect, flags, copy, enabled, text, textRole ); } } // fallback - return ParentStyleClass::drawItemText( painter, rect, flags, palette, enabled, text, textRole ); + return KStyle::drawItemText( painter, rect, flags, palette, enabled, text, textRole ); } //_____________________________________________________________________ bool Style::eventFilter( QObject *object, QEvent *event ) { if( QTabBar* tabBar = qobject_cast( object ) ) { return eventFilterTabBar( tabBar, event ); } else if( QToolBar* toolBar = qobject_cast( object ) ) { return eventFilterToolBar( toolBar, event ); } else if( QDockWidget* dockWidget = qobject_cast( object ) ) { return eventFilterDockWidget( dockWidget, event ); } else if( QToolBox* toolBox = qobject_cast( object ) ) { return eventFilterToolBox( toolBox, event ); } else if( QMdiSubWindow* subWindow = qobject_cast( object ) ) { return eventFilterMdiSubWindow( subWindow, event ); } else if( QScrollBar* scrollBar = qobject_cast( object ) ) { return eventFilterScrollBar( scrollBar, event ); } - #if QT_VERSION >= 0x050000 else if( QCommandLinkButton* commandLinkButton = qobject_cast( object ) ) { return eventFilterCommandLinkButton( commandLinkButton, event ); } - #endif // cast to QWidget QWidget *widget = static_cast( object ); if( widget->inherits( "QComboBoxPrivateContainer" ) ) { return eventFilterComboBoxContainer( widget, event ); } // fallback - return ParentStyleClass::eventFilter( object, event ); + return KStyle::eventFilter( object, event ); } //_________________________________________________________ bool Style::eventFilterComboBoxContainer( QWidget* widget, QEvent* event ) { switch( event->type() ) { case QEvent::Show: case QEvent::Resize: { if( !_helper->hasAlphaChannel( widget ) ) widget->setMask( _helper->roundedMask( widget->size() ) ); else widget->clearMask(); return false; } case QEvent::Paint: { QPainter painter( widget ); QPaintEvent *paintEvent = static_cast( event ); painter.setClipRegion( paintEvent->region() ); const QRect rect( widget->rect() ); const QColor color( widget->palette().color( widget->window()->backgroundRole() ) ); const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); if( hasAlpha ) { _helper->roundCorner( color ).render( rect, &painter ); painter.setCompositionMode( QPainter::CompositionMode_SourceOver ); painter.setClipPath( _helper->roundedPath( insideMargin( rect, 1 ) ), Qt::IntersectClip ); } // background _helper->renderMenuBackground( &painter, paintEvent->rect(), widget, widget->palette() ); // frame if( hasAlpha ) painter.setClipping( false ); _helper->drawFloatFrame( &painter, rect, color, !hasAlpha ); return false; } default: return false; } } //____________________________________________________________________________ bool Style::eventFilterDockWidget( QDockWidget* dockWidget, QEvent* event ) { switch( event->type() ) { case QEvent::Show: case QEvent::Resize: { // make sure mask is appropriate if( dockWidget->isFloating() ) dockWidget->setMask( _helper->roundedMask( dockWidget->size() ) ); else dockWidget->clearMask(); return false; } case QEvent::Paint: { QPainter painter( dockWidget ); QPaintEvent *paintEvent = static_cast( event ); painter.setClipRegion( paintEvent->region() ); const QColor color( dockWidget->palette().color( QPalette::Window ) ); const QRect rect( dockWidget->rect() ); if( dockWidget->isWindow() ) { _helper->renderWindowBackground( &painter, rect, dockWidget, color, 0 ); #ifndef Q_WS_WIN _helper->drawFloatFrame( &painter, rect, color, !_helper->compositingActive() ); #endif } else { // need to draw window background for autoFilled dockWidgets for better rendering if( dockWidget->autoFillBackground() ) { _helper->renderWindowBackground( &painter, rect, dockWidget, color ); } // adjust color QColor top( _helper->backgroundColor( color, dockWidget, rect.topLeft() ) ); QColor bottom( _helper->backgroundColor( color, dockWidget, rect.bottomLeft() ) ); _helper->dockFrame( top, bottom ).render( rect, &painter ); } return false; } default: return false; } } //____________________________________________________________________________ bool Style::eventFilterMdiSubWindow( QMdiSubWindow* subWindow, QEvent* event ) { if( event->type() == QEvent::Paint ) { QPainter painter( subWindow ); QRect clip( static_cast( event )->rect() ); if( subWindow->isMaximized() ) _helper->renderWindowBackground( &painter, clip, subWindow, subWindow->palette() ); else { painter.setClipRect( clip ); const QRect rect( subWindow->rect() ); _helper->roundCorner( subWindow->palette().color( subWindow->backgroundRole() ) ).render( rect, &painter ); painter.setClipPath( _helper->roundedPath( insideMargin( rect, 1 ) ), Qt::IntersectClip ); _helper->renderWindowBackground( &painter, clip, subWindow, subWindow, subWindow->palette(), 0 ); } } // continue with normal painting return false; } //____________________________________________________________________________ - #if QT_VERSION >= 0x050000 bool Style::eventFilterCommandLinkButton( QCommandLinkButton* button, QEvent* event ) { if( event->type() == QEvent::Paint ) { // painter QPainter painter( button ); painter.setClipRegion( static_cast( event )->region() ); const bool isFlat = false; // option QStyleOptionButton option; option.initFrom( button ); option.features |= QStyleOptionButton::CommandLinkButton; if( isFlat ) option.features |= QStyleOptionButton::Flat; option.text = QString(); option.icon = QIcon(); if( button->isChecked() ) option.state|=State_On; if( button->isDown() ) option.state|=State_Sunken; // frame drawControl(QStyle::CE_PushButton, &option, &painter, button ); // offset const int margin( Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth ); QPoint offset( margin, margin ); // state const State& state( option.state ); const bool enabled( state & State_Enabled ); // icon if( !button->icon().isNull() ) { const QSize pixmapSize( button->icon().actualSize( button->iconSize() ) ); const QRect pixmapRect( QPoint( offset.x(), button->description().isEmpty() ? (button->height() - pixmapSize.height())/2:offset.y() ), pixmapSize ); const QPixmap pixmap( button->icon().pixmap(pixmapSize, enabled ? QIcon::Normal : QIcon::Disabled, button->isChecked() ? QIcon::On : QIcon::Off) ); drawItemPixmap( &painter, pixmapRect, Qt::AlignCenter, pixmap ); offset.rx() += pixmapSize.width() + 4; } // text rect QRect textRect( offset, QSize( button->size().width() - offset.x() - margin, button->size().height() - 2*margin ) ); const QPalette::ColorRole textRole = QPalette::ButtonText; if( !button->text().isEmpty() ) { QFont font( button->font() ); font.setBold( true ); painter.setFont( font ); if( button->description().isEmpty() ) { drawItemText( &painter, textRect, Qt::AlignLeft|Qt::AlignVCenter|Qt::TextHideMnemonic, button->palette(), enabled, button->text(), textRole ); } else { drawItemText( &painter, textRect, Qt::AlignLeft|Qt::AlignTop|Qt::TextHideMnemonic, button->palette(), enabled, button->text(), textRole ); textRect.setTop( textRect.top() + QFontMetrics( font ).height() ); } painter.setFont( button->font() ); } if( !button->description().isEmpty() ) { drawItemText( &painter, textRect, Qt::AlignLeft|Qt::AlignVCenter|Qt::TextWordWrap, button->palette(), enabled, button->description(), textRole ); } return true; } // continue with normal painting return false; } - #endif //_________________________________________________________ bool Style::eventFilterScrollBar( QWidget* widget, QEvent* event ) { if( event->type() == QEvent::Paint ) { QPainter painter( widget ); painter.setClipRegion( static_cast( event )->region() ); _helper->renderWindowBackground( &painter, widget->rect(), widget,widget->palette() ); } return false; } //_____________________________________________________________________ bool Style::eventFilterTabBar( QWidget* widget, QEvent* event ) { if( event->type() == QEvent::Paint && _tabBarData->locks( widget ) ) { /* this makes sure that tabBar base is drawn ( and drawn only once ) every time a replaint is triggered by dragging a tab around */ _tabBarData->setDirty(); } return false; } //_____________________________________________________________________ bool Style::eventFilterToolBar( QToolBar* toolBar, QEvent* event ) { switch( event->type() ) { case QEvent::Show: case QEvent::Resize: { // make sure mask is appropriate if( toolBar->isFloating() ) { // TODO: should not be needed toolBar->setMask( _helper->roundedMask( toolBar->size() ) ); } else toolBar->clearMask(); return false; } case QEvent::Paint: { QPainter painter( toolBar ); QPaintEvent *paintEvent = static_cast( event ); painter.setClipRegion( paintEvent->region() ); const QRect rect( toolBar->rect() ); const QColor color( toolBar->palette().window().color() ); // default painting when not qrealing if( !toolBar->isFloating() ) { // background has to be rendered explicitly // when one of the parent has autofillBackground set to true if( _helper->checkAutoFillBackground( toolBar ) ) { _helper->renderWindowBackground( &painter, rect, toolBar, color, 0 ); } return false; } else { // background _helper->renderWindowBackground( &painter, rect, toolBar, color ); if( toolBar->isMovable() ) { // remaining painting: need to add handle // this is copied from QToolBar::paintEvent QStyleOptionToolBar opt; opt.initFrom( toolBar ); if( toolBar->orientation() == Qt::Horizontal ) { opt.rect = visualRect( &opt, QRect( rect.topLeft(), QSize( 8, rect.height() ) ) ); opt.state |= QStyle::State_Horizontal; } else { opt.rect = visualRect( &opt, QRect( rect.topLeft(), QSize( rect.width(), 8 ) ) ); } drawPrimitive( PE_IndicatorToolBarHandle, &opt, &painter, toolBar ); } #ifndef Q_WS_WIN if( _helper->compositingActive() ) _helper->drawFloatFrame( &painter, insideMargin( rect, -1 ), color, false ); else _helper->drawFloatFrame( &painter, rect, color, true ); #endif // do not propagate return true; } } default: return false; } } //____________________________________________________________________________ bool Style::eventFilterToolBox( QToolBox* toolBox, QEvent* event ) { if( event->type() == QEvent::Paint ) { if( toolBox->frameShape() != QFrame::NoFrame ) { const QRect rect( toolBox->rect() ); const StyleOptions styleOptions( NoFill ); QPainter painter( toolBox ); painter.setClipRegion( static_cast( event )->region() ); renderSlab( &painter, rect, toolBox->palette().color( QPalette::Button ), styleOptions ); } } return false; } //_____________________________________________________________________ void Style::configurationChanged() { // reload - #if OXYGEN_USE_KDE4 - StyleConfigData::self()->readConfig(); - #else StyleConfigData::self()->load(); - #endif _shadowHelper->reparseCacheConfig(); _helper->invalidateCaches(); loadConfiguration(); } //____________________________________________________________________ QIcon Style::standardIconImplementation( StandardPixmap standardPixmap, const QStyleOption *option, const QWidget *widget ) const { // MDI windows buttons // get button color ( unfortunately option and widget might not be set ) QColor buttonColor; QColor iconColor; if( option ) { buttonColor = option->palette.window().color(); iconColor = option->palette.windowText().color(); } else if( widget ) { buttonColor = widget->palette().window().color(); iconColor = widget->palette().windowText().color(); } else if( qApp ) { // might not have a QApplication buttonColor = QPalette().window().color(); iconColor = QPalette().windowText().color(); } else { // KCS is always safe buttonColor = KColorScheme( QPalette::Active, KColorScheme::Window, _helper->config() ).background().color(); iconColor = KColorScheme( QPalette::Active, KColorScheme::Window, _helper->config() ).foreground().color(); } // contrast const QColor contrast( _helper->calcLightColor( buttonColor ) ); const int iconSize( pixelMetric( QStyle::PM_SmallIconSize ) ); const QRect rect( 0, 0, iconSize, iconSize ); switch( standardPixmap ) { case SP_TitleBarNormalButton: { QPixmap pixmap( _helper->highDpiPixmap( rect.size() ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, rect, buttonColor, iconColor, SC_TitleBarNormalButton ); return QIcon( pixmap ); } case SP_TitleBarShadeButton: { QPixmap pixmap( _helper->highDpiPixmap( rect.size() ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, rect, buttonColor, iconColor, SC_TitleBarShadeButton ); return QIcon( pixmap ); } case SP_TitleBarUnshadeButton: { QPixmap pixmap( _helper->highDpiPixmap( rect.size() ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, rect, buttonColor, iconColor, SC_TitleBarUnshadeButton ); return QIcon( pixmap ); } case SP_TitleBarCloseButton: case SP_DockWidgetCloseButton: { QPixmap pixmap( _helper->highDpiPixmap( rect.size() ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, rect, buttonColor, iconColor, SC_TitleBarCloseButton ); return QIcon( pixmap ); } case SP_ToolBarHorizontalExtensionButton: { QIcon icon; // default icon sizes static const QList iconSizes = { 8, 16, 22, 32, 48 }; foreach( const int& iconSize, iconSizes ) { QPixmap pixmap( iconSize, iconSize ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setWindow( rect ); painter.setBrush( Qt::NoBrush ); painter.translate( QRectF( rect ).center() ); const bool reverseLayout( option && option->direction == Qt::RightToLeft ); QPolygonF arrow = genericArrow( reverseLayout ? ArrowLeft:ArrowRight, ArrowTiny ); const qreal width( 1.1 ); painter.translate( 0, 0.5 ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( _helper->calcLightColor( buttonColor ), width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter.drawPolyline( arrow ); painter.translate( 0,-1 ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( iconColor, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter.drawPolyline( arrow ); painter.end(); icon.addPixmap( pixmap ); } return icon; } case SP_ToolBarVerticalExtensionButton: { QIcon icon; // default icon sizes static const QList iconSizes = { 8, 16, 22, 32, 48 }; foreach( const int& iconSize, iconSizes ) { QPixmap pixmap( iconSize, iconSize ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setWindow( rect ); painter.setBrush( Qt::NoBrush ); painter.translate( QRectF( rect ).center() ); QPolygonF arrow = genericArrow( ArrowDown, ArrowTiny ); const qreal width( 1.1 ); painter.translate( 0, 0.5 ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( _helper->calcLightColor( buttonColor ), width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter.drawPolyline( arrow ); painter.translate( 0,-1 ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( iconColor, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter.drawPolyline( arrow ); painter.end(); icon.addPixmap( pixmap ); } return icon; } default: // do not cache parent style icon, since it may change at runtime - #if QT_VERSION >= 0x050000 - return ParentStyleClass::standardIcon( standardPixmap, option, widget ); - #else - return ParentStyleClass::standardIconImplementation( standardPixmap, option, widget ); - #endif + return KStyle::standardIcon( standardPixmap, option, widget ); } } //_____________________________________________________________________ void Style::loadConfiguration() { // set helper configuration _helper->loadConfig(); // background gradient _helper->setUseBackgroundGradient( StyleConfigData::useBackgroundGradient() ); // update top level window hints foreach( QWidget* widget, qApp->topLevelWidgets() ) { // make sure widget has a valid WId if( !(widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() ) ) continue; // make sure widget has a decoration if( !_helper->hasDecoration( widget ) ) continue; // update flags _helper->setHasBackgroundGradient( widget->winId(), true ); } // update caches size int cacheSize( StyleConfigData::cacheEnabled() ? StyleConfigData::maxCacheSize():0 ); _helper->setMaxCacheSize( cacheSize ); // always enable blur helper _blurHelper->setEnabled( true ); // reinitialize engines _animations->setupEngines(); _transitions->setupEngines(); _windowManager->initialize(); _shadowHelper->loadConfig(); // mnemonics _mnemonics->setMode( StyleConfigData::mnemonicsMode() ); // widget explorer _widgetExplorer->setEnabled( StyleConfigData::widgetExplorerEnabled() ); _widgetExplorer->setDrawWidgetRects( StyleConfigData::drawWidgetRects() ); // splitter proxy _splitterFactory->setEnabled( StyleConfigData::splitterProxyEnabled() ); // scrollbar button dimentions. /* it has to be reinitialized here because scrollbar width might have changed */ _noButtonHeight = 0; _singleButtonHeight = qMax( StyleConfigData::scrollBarWidth() * 7 / 10, 14 ); _doubleButtonHeight = 2*_singleButtonHeight; // scrollbar buttons switch( StyleConfigData::scrollBarAddLineButtons() ) { case 0: _addLineButtons = NoButton; break; case 1: _addLineButtons = SingleButton; break; default: case 2: _addLineButtons = DoubleButton; break; } switch( StyleConfigData::scrollBarSubLineButtons() ) { case 0: _subLineButtons = NoButton; break; case 1: _subLineButtons = SingleButton; break; default: case 2: _subLineButtons = DoubleButton; break; } // frame focus if( StyleConfigData::viewDrawFocusIndicator() ) _frameFocusPrimitive = &Style::drawFrameFocusRectPrimitive; else _frameFocusPrimitive = &Style::emptyPrimitive; } //___________________________________________________________________________________________________________________ QRect Style::pushButtonContentsRect( const QStyleOption* option, const QWidget* ) const { return insideMargin( option->rect, Metrics::Frame_FrameWidth ); } //___________________________________________________________________________________________________________________ QRect Style::checkBoxContentsRect( const QStyleOption* option, const QWidget* ) const { return visualRect( option, option->rect.adjusted( Metrics::CheckBox_Size + Metrics::CheckBox_ItemSpacing, 0, 0, 0 ) ); } //___________________________________________________________________________________________________________________ QRect Style::lineEditContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const QStyleOptionFrame* frameOption( qstyleoption_cast( option ) ); if( !frameOption ) return option->rect; // check flatness const bool flat( frameOption->lineWidth == 0 ); if( flat ) return option->rect; // copy rect and take out margins QRect rect( option->rect ); // take out margins if there is enough room const int frameWidth( pixelMetric( PM_DefaultFrameWidth, option, widget ) ); if( rect.height() > option->fontMetrics.height() + 2*frameWidth ) return insideMargin( rect, frameWidth ); else return rect; } //____________________________________________________________________ QRect Style::progressBarGrooveRect( const QStyleOption* option, const QWidget* ) const { const QRect rect( option->rect ); - #if OXYGEN_USE_KDE4 - const auto progressBarOption2( qstyleoption_cast( option ) ); - #else const auto progressBarOption2( qstyleoption_cast( option ) ); - #endif const bool horizontal( !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal ); if( horizontal ) return insideMargin( rect, 1, 0 ); else return insideMargin( rect, 0, 1 ); } //____________________________________________________________________ QRect Style::progressBarContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const QStyleOptionProgressBar* progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return QRect(); // get orientation - #if OXYGEN_USE_KDE4 - const auto progressBarOption2( qstyleoption_cast( option ) ); - #else const auto progressBarOption2( qstyleoption_cast( option ) ); - #endif const bool horizontal( !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal ); // check inverted appearance const bool inverted( progressBarOption2 ? progressBarOption2->invertedAppearance : false ); // get groove rect const QRect rect( progressBarGrooveRect( option, widget ) ); // get progress qreal progress = progressBarOption->progress - progressBarOption->minimum; const bool busy = ( progressBarOption->minimum == 0 && progressBarOption->maximum == 0 ); if( busy ) progress = _animations->busyIndicatorEngine().value(); if( !( progress || busy ) ) return QRect(); const int steps = qMax( progressBarOption->maximum - progressBarOption->minimum, 1 ); //Calculate width fraction qreal widthFrac( busy ? qreal(Metrics::ProgressBar_BusyIndicatorSize)/100 : progress/steps ); widthFrac = qMin( (qreal)1, widthFrac ); // And now the pixel width const int indicatorSize( widthFrac*( horizontal ? rect.width():rect.height() ) ); // do nothing if indicator size is too small if( indicatorSize < 4 ) return QRect(); QRect indicatorRect; if( busy ) { // The space around which we move around... int remSize = ( ( 1 - widthFrac )*( horizontal ? rect.width():rect.height() ) ); remSize = qMax( remSize, 1 ); int pstep = remSize*2*progress; if( pstep > remSize ) { pstep = -( pstep - 2*remSize ); } if( horizontal ) { indicatorRect = QRect( inverted ? (rect.right() - pstep - indicatorSize + 1) : (rect.left() + pstep), rect.top(), indicatorSize, rect.height() ); indicatorRect = visualRect( option->direction, rect, indicatorRect ); } else { indicatorRect = QRect( rect.left(), inverted ? (rect.bottom() - pstep - indicatorSize + 1) : (rect.top() + pstep), rect.width(), indicatorSize ); } } else { if( horizontal ) { indicatorRect = QRect( inverted ? (rect.right() - indicatorSize + 1) : rect.left(), rect.top(), indicatorSize, rect.height() ); indicatorRect = visualRect( option->direction, rect, indicatorRect ); } else { indicatorRect = QRect( rect.left(), inverted ? rect.top() : (rect.bottom()- indicatorSize + 1), rect.width(), indicatorSize ); } } // adjust return insideMargin( indicatorRect, 1 ); } //___________________________________________________________________________________________________________________ QRect Style::headerArrowRect( const QStyleOption* option, const QWidget* ) const { // cast option and check const QStyleOptionHeader* headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return option->rect; // check if arrow is necessary if( headerOption->sortIndicator == QStyleOptionHeader::None ) return QRect(); QRect arrowRect( insideMargin( option->rect, Metrics::Header_MarginWidth ) ); arrowRect.setLeft( arrowRect.right() - Metrics::Header_ArrowSize + 1 ); return visualRect( option, arrowRect ); } //___________________________________________________________________________________________________________________ QRect Style::headerLabelRect( const QStyleOption* option, const QWidget* ) const { // cast option and check const QStyleOptionHeader* headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return option->rect; // check if arrow is necessary // QRect labelRect( insideMargin( option->rect, Metrics::Header_MarginWidth ) ); QRect labelRect( insideMargin( option->rect, Metrics::Header_MarginWidth, 0 ) ); if( headerOption->sortIndicator == QStyleOptionHeader::None ) return labelRect; labelRect.adjust( 0, 0, -Metrics::Header_ArrowSize-Metrics::Header_ItemSpacing, 0 ); return visualRect( option, labelRect ); } //____________________________________________________________________ QRect Style::tabBarTabLeftButtonRect( const QStyleOption* option, const QWidget* ) const { // cast option and check - #if OXYGEN_USE_KDE4 - const auto tabOptionV3( qstyleoption_cast( option ) ); - #else const auto tabOptionV3( qstyleoption_cast( option ) ); - #endif if( !tabOptionV3 || tabOptionV3->leftButtonSize.isEmpty() ) return QRect(); const QRect rect( option->rect ); const QSize size( tabOptionV3->leftButtonSize ); QRect buttonRect( QPoint(0,0), size ); // vertical positioning switch( tabOptionV3->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: buttonRect.moveLeft( rect.left() + Metrics::TabBar_TabMarginWidth ); buttonRect.moveTop( ( rect.height() - buttonRect.height() )/2 ); buttonRect = visualRect( option, buttonRect ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: buttonRect.moveBottom( rect.bottom() - Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: buttonRect.moveTop( rect.top() + Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; default: break; } return buttonRect; } //____________________________________________________________________ QRect Style::tabBarTabRightButtonRect( const QStyleOption* option, const QWidget* ) const { // cast option and check - #if OXYGEN_USE_KDE4 - const auto tabOptionV3( qstyleoption_cast( option ) ); - #else const auto tabOptionV3( qstyleoption_cast( option ) ); - #endif if( !tabOptionV3 || tabOptionV3->rightButtonSize.isEmpty() ) return QRect(); const QRect rect( option->rect ); const QSize size( tabOptionV3->rightButtonSize ); QRect buttonRect( QPoint(0,0), size ); // vertical positioning switch( tabOptionV3->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: buttonRect.moveRight( rect.right() - Metrics::TabBar_TabMarginWidth ); buttonRect.moveTop( ( rect.height() - buttonRect.height() )/2 ); buttonRect = visualRect( option, buttonRect ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: buttonRect.moveTop( rect.top() + Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: buttonRect.moveBottom( rect.bottom() - Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; default: break; } return buttonRect; } //____________________________________________________________________ QRect Style::tabWidgetTabBarRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const QStyleOptionTabWidgetFrame* tabOption = qstyleoption_cast( option ); - if( !tabOption ) return ParentStyleClass::subElementRect( SE_TabWidgetTabBar, option, widget ); + if( !tabOption ) return KStyle::subElementRect( SE_TabWidgetTabBar, option, widget ); // do nothing if tabbar is hidden const QSize tabBarSize( tabOption->tabBarSize ); QRect rect( option->rect ); QRect tabBarRect( QPoint(0, 0), tabBarSize ); // horizontal positioning const bool verticalTabs( isVerticalTab( tabOption->shape ) ); if( verticalTabs ) { tabBarRect.setHeight( qMin( tabBarRect.height(), rect.height() - 2 ) ); tabBarRect.moveTop( rect.top()+1 ); } else { // account for corner rects // need to re-run visualRect to remove right-to-left handling, since it is re-added on tabBarRect at the end const QRect leftButtonRect( visualRect( option, subElementRect( SE_TabWidgetLeftCorner, option, widget ) ) ); const QRect rightButtonRect( visualRect( option, subElementRect( SE_TabWidgetRightCorner, option, widget ) ) ); rect.setLeft( leftButtonRect.width() ); rect.setRight( rightButtonRect.left() - 1 ); tabBarRect.setWidth( qMin( tabBarRect.width(), rect.width() - 2 ) ); tabBarRect.moveLeft( rect.left() + 1 ); tabBarRect = visualRect( option, tabBarRect ); } // vertical positioning switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: tabBarRect.moveTop( rect.top()+1 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: tabBarRect.moveBottom( rect.bottom()-1 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: tabBarRect.moveLeft( rect.left()+1 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: tabBarRect.moveRight( rect.right()-1 ); break; default: break; } return tabBarRect; } //____________________________________________________________________ QRect Style::tabWidgetTabContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const QStyleOptionTabWidgetFrame* tabOption = qstyleoption_cast( option ); if( !tabOption ) return option->rect; // do nothing if tabbar is hidden if( tabOption->tabBarSize.isEmpty() ) return option->rect; const QRect rect = tabWidgetTabPaneRect( option, widget ); const bool documentMode( tabOption->lineWidth == 0 ); if( documentMode ) { // add margin only to the relevant side switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: return rect.adjusted( 0, Metrics::TabWidget_MarginWidth, 0, 0 ); case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: return rect.adjusted( 0, 0, 0, -Metrics::TabWidget_MarginWidth ); case QTabBar::RoundedWest: case QTabBar::TriangularWest: return rect.adjusted( Metrics::TabWidget_MarginWidth, 0, 0, 0 ); case QTabBar::RoundedEast: case QTabBar::TriangularEast: return rect.adjusted( 0, 0, -Metrics::TabWidget_MarginWidth, 0 ); default: return rect; } } else return insideMargin( rect, Metrics::TabWidget_MarginWidth ); } //____________________________________________________________________ QRect Style::tabWidgetTabPaneRect( const QStyleOption* option, const QWidget* ) const { const QStyleOptionTabWidgetFrame* tabOption = qstyleoption_cast( option ); if( !tabOption || tabOption->tabBarSize.isEmpty() ) return option->rect; const int overlap = Metrics::TabBar_BaseOverlap - 1; const QSize tabBarSize( tabOption->tabBarSize - QSize( overlap, overlap ) ); QRect rect( option->rect ); switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: rect.adjust( 0, tabBarSize.height(), 0, 0 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: rect.adjust( 0, 0, 0, -tabBarSize.height() ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: rect.adjust( tabBarSize.width(), 0, 0, 0 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: rect.adjust( 0, 0, -tabBarSize.width(), 0 ); break; default: break; } return rect; } //____________________________________________________________________ QRect Style::tabWidgetCornerRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const { // cast option and check const QStyleOptionTabWidgetFrame *tabOption = qstyleoption_cast( option ); if( !tabOption ) return QRect(); // copy rect const QRect paneRect( subElementRect( SE_TabWidgetTabPane, option, widget ) ); QRect rect; switch( element ) { case SE_TabWidgetLeftCorner: rect = QRect( QPoint(0,0), tabOption->leftCornerWidgetSize ); break; case SE_TabWidgetRightCorner: rect = QRect( QPoint(0,0), tabOption->rightCornerWidgetSize ); break; default: break; } if( element == SE_TabWidgetRightCorner ) rect.moveRight( paneRect.right() ); else rect.moveLeft( paneRect.left() ); switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: rect.moveBottom( paneRect.top() - 1 ); rect.translate( 0, 3 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: rect.moveTop( paneRect.bottom() + 1 ); rect.translate( 0, -3 ); break; default: return QRect(); } rect = visualRect( tabOption, rect ); return rect; } //____________________________________________________________________ QRect Style::toolBoxTabContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const QStyleOptionToolBox* toolBoxOption( qstyleoption_cast( option ) ); if( !toolBoxOption ) return option->rect; // copy rect const QRect& rect( option->rect ); int contentsWidth(0); if( !toolBoxOption->icon.isNull() ) { const int iconSize( pixelMetric( QStyle::PM_SmallIconSize, option, widget ) ); contentsWidth += iconSize; if( !toolBoxOption->text.isEmpty() ) contentsWidth += Metrics::ToolBox_TabItemSpacing; } if( !toolBoxOption->text.isEmpty() ) { const int textWidth = toolBoxOption->fontMetrics.size( _mnemonics->textFlags(), toolBoxOption->text ).width(); contentsWidth += textWidth; } contentsWidth = qMin( contentsWidth, rect.width() ); contentsWidth = qMax( contentsWidth, int(Metrics::ToolBox_TabMinWidth) ); return centerRect( rect, contentsWidth, rect.height() ); } //______________________________________________________________ QRect Style::groupBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { QRect rect = option->rect; switch( subControl ) { case SC_GroupBoxFrame: return rect; case SC_GroupBoxContents: { // cast option and check const QStyleOptionGroupBox *groupBoxOption = qstyleoption_cast( option ); if( !groupBoxOption ) break; // take out frame width rect = insideMargin( rect, Metrics::Frame_FrameWidth ); // get state const bool checkable( groupBoxOption->subControls & QStyle::SC_GroupBoxCheckBox ); const bool emptyText( groupBoxOption->text.isEmpty() ); // calculate title height int titleHeight( 0 ); if( !emptyText ) titleHeight = groupBoxOption->fontMetrics.height(); if( checkable ) titleHeight = qMax( titleHeight, int(Metrics::CheckBox_Size) ); // add margin if( titleHeight > 0 ) titleHeight += 2*Metrics::GroupBox_TitleMarginWidth; rect.adjust( 0, titleHeight, 0, 0 ); return rect; } case SC_GroupBoxCheckBox: case SC_GroupBoxLabel: { // cast option and check const QStyleOptionGroupBox *groupBoxOption = qstyleoption_cast( option ); if( !groupBoxOption ) break; // take out frame width rect = insideMargin( rect, Metrics::Frame_FrameWidth ); const bool emptyText( groupBoxOption->text.isEmpty() ); const bool checkable( groupBoxOption->subControls & QStyle::SC_GroupBoxCheckBox ); // calculate title height int titleHeight( 0 ); int titleWidth( 0 ); if( !emptyText ) { const QFontMetrics fontMetrics = option->fontMetrics; titleHeight = qMax( titleHeight, fontMetrics.height() ); titleWidth += fontMetrics.size( _mnemonics->textFlags(), groupBoxOption->text ).width(); } if( checkable ) { titleHeight = qMax( titleHeight, int(Metrics::CheckBox_Size) ); titleWidth += Metrics::CheckBox_Size; if( !emptyText ) titleWidth += Metrics::CheckBox_ItemSpacing; } // adjust height QRect titleRect( rect ); titleRect.setHeight( titleHeight ); titleRect.translate( 0, Metrics::GroupBox_TitleMarginWidth ); // center titleRect = centerRect( titleRect, titleWidth, titleHeight ); if( subControl == SC_GroupBoxCheckBox ) { // vertical centering titleRect = centerRect( titleRect, titleWidth, Metrics::CheckBox_Size ); // horizontal positioning const QRect subRect( titleRect.topLeft(), QSize( Metrics::CheckBox_Size, titleRect.height() ) ); return visualRect( option->direction, titleRect, subRect ); } else { // vertical centering QFontMetrics fontMetrics = option->fontMetrics; titleRect = centerRect( titleRect, titleWidth, fontMetrics.height() ); // horizontal positioning QRect subRect( titleRect ); if( checkable ) subRect.adjust( Metrics::CheckBox_Size + Metrics::CheckBox_ItemSpacing, 0, 0, 0 ); return visualRect( option->direction, titleRect, subRect ); } } default: break; } - return ParentStyleClass::subControlRect( CC_GroupBox, option, subControl, widget ); + return KStyle::subControlRect( CC_GroupBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::toolButtonSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const QStyleOptionToolButton* toolButtonOption = qstyleoption_cast( option ); - if( !toolButtonOption ) return ParentStyleClass::subControlRect( CC_ToolButton, option, subControl, widget ); + if( !toolButtonOption ) return KStyle::subControlRect( CC_ToolButton, option, subControl, widget ); const bool hasPopupMenu( toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup ); const bool hasInlineIndicator( toolButtonOption->features&QStyleOptionToolButton::HasMenu && toolButtonOption->features&QStyleOptionToolButton::PopupDelay && !hasPopupMenu ); // store rect const QRect& rect( option->rect ); const int menuButtonWidth( Metrics::MenuButton_IndicatorWidth ); switch( subControl ) { case SC_ToolButtonMenu: { // check fratures if( !(hasPopupMenu || hasInlineIndicator ) ) return QRect(); // check features QRect menuRect( rect ); menuRect.setLeft( rect.right() - menuButtonWidth + 1 ); if( hasInlineIndicator ) { menuRect.setTop( menuRect.bottom() - menuButtonWidth + 1 ); } return visualRect( option, menuRect ); } case SC_ToolButton: { if( hasPopupMenu ) { QRect contentsRect( rect ); contentsRect.setRight( rect.right() - menuButtonWidth ); return visualRect( option, contentsRect ); } else return rect; } default: return QRect(); } } //___________________________________________________________________________________________________________________ QRect Style::comboBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const QStyleOptionComboBox *comboBoxOption( qstyleoption_cast( option ) ); - if( !comboBoxOption ) return ParentStyleClass::subControlRect( CC_ComboBox, option, subControl, widget ); + if( !comboBoxOption ) return KStyle::subControlRect( CC_ComboBox, option, subControl, widget ); const bool editable( comboBoxOption->editable ); const bool flat( editable && !comboBoxOption->frame ); // copy rect QRect rect( option->rect ); switch( subControl ) { case SC_ComboBoxFrame: return flat ? rect : QRect(); case SC_ComboBoxListBoxPopup: return rect; case SC_ComboBoxArrow: { // take out frame width if( !flat ) rect = insideMargin( rect, Metrics::Frame_FrameWidth ); QRect arrowRect( rect.right() - Metrics::MenuButton_IndicatorWidth + 1, rect.top(), Metrics::MenuButton_IndicatorWidth, rect.height() ); arrowRect = centerRect( arrowRect, Metrics::MenuButton_IndicatorWidth, Metrics::MenuButton_IndicatorWidth ); return visualRect( option, arrowRect ); } case SC_ComboBoxEditField: { QRect labelRect; const int frameWidth( pixelMetric( PM_ComboBoxFrameWidth, option, widget ) ); labelRect = QRect( rect.left(), rect.top(), rect.width() - Metrics::MenuButton_IndicatorWidth, rect.height() ); // remove margins if( !flat && rect.height() > option->fontMetrics.height() + 2*frameWidth ) { labelRect.adjust( frameWidth, frameWidth, 0, -frameWidth ); } return visualRect( option, labelRect ); } default: break; } - return ParentStyleClass::subControlRect( CC_ComboBox, option, subControl, widget ); + return KStyle::subControlRect( CC_ComboBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::spinBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const QStyleOptionSpinBox *spinBoxOption( qstyleoption_cast( option ) ); - if( !spinBoxOption ) return ParentStyleClass::subControlRect( CC_SpinBox, option, subControl, widget ); + if( !spinBoxOption ) return KStyle::subControlRect( CC_SpinBox, option, subControl, widget ); const bool flat( !spinBoxOption->frame ); // copy rect QRect rect( option->rect ); switch( subControl ) { case SC_SpinBoxFrame: return flat ? QRect():rect; case SC_SpinBoxUp: case SC_SpinBoxDown: { // take out frame width if( !flat && rect.height() >= 2*Metrics::Frame_FrameWidth + Metrics::SpinBox_ArrowButtonWidth ) rect = insideMargin( rect, Metrics::Frame_FrameWidth ); QRect arrowRect; arrowRect = QRect( rect.right() - Metrics::SpinBox_ArrowButtonWidth + 1, rect.top(), Metrics::SpinBox_ArrowButtonWidth, rect.height() ); const int arrowHeight( qMin( rect.height(), int(Metrics::SpinBox_ArrowButtonWidth) ) ); arrowRect = centerRect( arrowRect, Metrics::SpinBox_ArrowButtonWidth, arrowHeight ); arrowRect.setHeight( arrowHeight/2 ); if( subControl == SC_SpinBoxDown ) arrowRect.translate( 0, arrowHeight/2 ); return visualRect( option, arrowRect ); } case SC_SpinBoxEditField: { QRect labelRect; labelRect = QRect( rect.left(), rect.top(), rect.width() - Metrics::SpinBox_ArrowButtonWidth, rect.height() ); // remove right side line editor margins const int frameWidth( pixelMetric( PM_SpinBoxFrameWidth, option, widget ) ); if( !flat && labelRect.height() > option->fontMetrics.height() + 2*frameWidth ) { labelRect.adjust( frameWidth, frameWidth, 0, -frameWidth ); } return visualRect( option, labelRect ); } default: break; } - return ParentStyleClass::subControlRect( CC_SpinBox, option, subControl, widget ); + return KStyle::subControlRect( CC_SpinBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::scrollBarInternalSubControlRect( const QStyleOptionComplex* option, SubControl subControl ) const { const QRect& rect = option->rect; const State& state( option->state ); const bool horizontal( state & State_Horizontal ); switch( subControl ) { case SC_ScrollBarSubLine: { int majorSize( scrollBarButtonHeight( _subLineButtons ) ); if( horizontal ) return visualRect( option, QRect( rect.left(), rect.top(), majorSize, rect.height() ) ); else return visualRect( option, QRect( rect.left(), rect.top(), rect.width(), majorSize ) ); } case SC_ScrollBarAddLine: { int majorSize( scrollBarButtonHeight( _addLineButtons ) ); if( horizontal ) return visualRect( option, QRect( rect.right() - majorSize + 1, rect.top(), majorSize, rect.height() ) ); else return visualRect( option, QRect( rect.left(), rect.bottom() - majorSize + 1, rect.width(), majorSize ) ); } default: return QRect(); } } //___________________________________________________________________________________________________________________ QRect Style::scrollBarSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); - if( !sliderOption ) return ParentStyleClass::subControlRect( CC_ScrollBar, option, subControl, widget ); + if( !sliderOption ) return KStyle::subControlRect( CC_ScrollBar, option, subControl, widget ); // get relevant state const State& state( option->state ); const bool horizontal( state & State_Horizontal ); switch( subControl ) { case SC_ScrollBarSubLine: case SC_ScrollBarAddLine: return scrollBarInternalSubControlRect( option, subControl ); case SC_ScrollBarGroove: { QRect topRect = visualRect( option, scrollBarInternalSubControlRect( option, SC_ScrollBarSubLine ) ); QRect bottomRect = visualRect( option, scrollBarInternalSubControlRect( option, SC_ScrollBarAddLine ) ); QPoint topLeftCorner; QPoint botRightCorner; if( horizontal ) { topLeftCorner = QPoint( topRect.right() + 1, topRect.top() ); botRightCorner = QPoint( bottomRect.left() - 1, topRect.bottom() ); } else { topLeftCorner = QPoint( topRect.left(), topRect.bottom() + 1 ); botRightCorner = QPoint( topRect.right(), bottomRect.top() - 1 ); } // define rect return visualRect( option, QRect( topLeftCorner, botRightCorner ) ); } case SC_ScrollBarSlider: { // We handle RTL here to unreflect things if need be QRect groove = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); if( sliderOption->minimum == sliderOption->maximum ) return groove; //Figure out how much room we have.. int space( horizontal ? groove.width() : groove.height() ); //Calculate the portion of this space that the slider should take up. int sliderSize = space * qreal( sliderOption->pageStep ) / ( sliderOption->maximum - sliderOption->minimum + sliderOption->pageStep ); sliderSize = qMax( sliderSize, static_cast(Metrics::ScrollBar_MinSliderHeight ) ); sliderSize = qMin( sliderSize, space ); space -= sliderSize; if( space <= 0 ) return groove; int pos = qRound( qreal( sliderOption->sliderPosition - sliderOption->minimum )/ ( sliderOption->maximum - sliderOption->minimum )*space ); if( sliderOption->upsideDown ) pos = space - pos; if( horizontal ) return visualRect( option, QRect( groove.left() + pos, groove.top(), sliderSize, groove.height() ) ); else return visualRect( option, QRect( groove.left(), groove.top() + pos, groove.width(), sliderSize ) ); } case SC_ScrollBarSubPage: { //We do visualRect here to unreflect things if need be QRect slider = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarSlider, widget ) ); QRect groove = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); if( horizontal ) return visualRect( option, QRect( groove.left(), groove.top(), slider.left() - groove.left(), groove.height() ) ); else return visualRect( option, QRect( groove.left(), groove.top(), groove.width(), slider.top() - groove.top() ) ); } case SC_ScrollBarAddPage: { //We do visualRect here to unreflect things if need be QRect slider = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarSlider, widget ) ); QRect groove = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); if( horizontal ) return visualRect( option, QRect( slider.right() + 1, groove.top(), groove.right() - slider.right(), groove.height() ) ); else return visualRect( option, QRect( groove.left(), slider.bottom() + 1, groove.width(), groove.bottom() - slider.bottom() ) ); } - default: return ParentStyleClass::subControlRect( CC_ScrollBar, option, subControl, widget );; + default: return KStyle::subControlRect( CC_ScrollBar, option, subControl, widget );; } } //___________________________________________________________________________________________________________________ QRect Style::sliderSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); - if( !sliderOption ) return ParentStyleClass::subControlRect( CC_Slider, option, subControl, widget ); + if( !sliderOption ) return KStyle::subControlRect( CC_Slider, option, subControl, widget ); switch( subControl ) { case SC_SliderGroove: { // direction const bool horizontal( sliderOption->orientation == Qt::Horizontal ); // get base class rect - QRect grooveRect( ParentStyleClass::subControlRect( CC_Slider, option, subControl, widget ) ); + QRect grooveRect( KStyle::subControlRect( CC_Slider, option, subControl, widget ) ); grooveRect = insideMargin( grooveRect, pixelMetric( PM_DefaultFrameWidth, option, widget ) ); // centering if( horizontal ) { grooveRect = centerRect( grooveRect, grooveRect.width(), Metrics::Slider_GrooveThickness ); grooveRect = insideMargin( grooveRect, 3, 0 ); } else { grooveRect = centerRect( grooveRect, Metrics::Slider_GrooveThickness, grooveRect.height() ); grooveRect = insideMargin( grooveRect, 0, 3 ); } return grooveRect; } case SC_SliderHandle: { - QRect handleRect( ParentStyleClass::subControlRect( CC_Slider, option, subControl, widget ) ); + QRect handleRect( KStyle::subControlRect( CC_Slider, option, subControl, widget ) ); handleRect = centerRect( handleRect, Metrics::Slider_ControlThickness, Metrics::Slider_ControlThickness ); return handleRect; } - default: return ParentStyleClass::subControlRect( CC_Slider, option, subControl, widget ); + default: return KStyle::subControlRect( CC_Slider, option, subControl, widget ); } } //______________________________________________________________ QSize Style::checkBoxSizeFromContents( const QStyleOption*, const QSize& contentsSize, const QWidget* ) const { // get contents size QSize size( contentsSize ); // add focus height size = expandSize( size, 0, Metrics::CheckBox_FocusMarginWidth ); // make sure there is enough height for indicator size.setHeight( qMax( size.height(), int(Metrics::CheckBox_Size) ) ); // Add space for the indicator and the icon size.rwidth() += Metrics::CheckBox_Size + Metrics::CheckBox_ItemSpacing; // also add extra space, to leave room to the right of the label size.rwidth() += Metrics::CheckBox_ItemSpacing; return size; } //______________________________________________________________ QSize Style::lineEditSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const QStyleOptionFrame* frameOption( qstyleoption_cast( option ) ); if( !frameOption ) return contentsSize; const bool flat( frameOption->lineWidth == 0 ); const int frameWidth( pixelMetric( PM_DefaultFrameWidth, option, widget ) ); return flat ? contentsSize : expandSize( contentsSize, frameWidth ); } //______________________________________________________________ QSize Style::comboBoxSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const QStyleOptionComboBox* comboBoxOption( qstyleoption_cast( option ) ); if( !comboBoxOption ) return contentsSize; // copy size QSize size( contentsSize ); // add relevant margin const bool flat( !comboBoxOption->frame ); const int frameWidth( pixelMetric( PM_ComboBoxFrameWidth, option, widget ) ); if( !flat ) size = expandSize( size, frameWidth ); // make sure there is enough height for the button size.setHeight( qMax( size.height(), int(Metrics::MenuButton_IndicatorWidth) ) ); // add button width and spacing size.rwidth() += Metrics::MenuButton_IndicatorWidth; return size; } //______________________________________________________________ QSize Style::spinBoxSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const QStyleOptionSpinBox *spinBoxOption( qstyleoption_cast( option ) ); if( !spinBoxOption ) return contentsSize; const bool flat( !spinBoxOption->frame ); // copy size QSize size( contentsSize ); // add editor margins const int frameWidth( pixelMetric( PM_SpinBoxFrameWidth, option, widget ) ); if( !flat ) size = expandSize( size, frameWidth ); // make sure there is enough height for the button size.setHeight( qMax( size.height(), int(Metrics::SpinBox_ArrowButtonWidth) ) ); // add button width and spacing size.rwidth() += Metrics::SpinBox_ArrowButtonWidth; return size; } //______________________________________________________________ QSize Style::sliderSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { // cast option and check const QStyleOptionSlider *sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return contentsSize; // store tick position and orientation const QSlider::TickPosition& tickPosition( sliderOption->tickPosition ); const bool horizontal( sliderOption->orientation == Qt::Horizontal ); const bool disableTicks( !StyleConfigData::sliderDrawTickMarks() ); /* Qt adds its own tick length directly inside QSlider. Take it out and replace by ours, if needed */ const int tickLength( disableTicks ? 0 : ( Metrics::Slider_TickLength + Metrics::Slider_TickMarginWidth + (Metrics::Slider_GrooveThickness - Metrics::Slider_ControlThickness)/2 ) ); const int builtInTickLength( 5 ); if( tickPosition == QSlider::NoTicks ) return contentsSize; QSize size( contentsSize ); if( horizontal ) { if(tickPosition & QSlider::TicksAbove) size.rheight() += tickLength - builtInTickLength; if(tickPosition & QSlider::TicksBelow) size.rheight() += tickLength - builtInTickLength; } else { if(tickPosition & QSlider::TicksAbove) size.rwidth() += tickLength - builtInTickLength; if(tickPosition & QSlider::TicksBelow) size.rwidth() += tickLength - builtInTickLength; } return size; } //______________________________________________________________ QSize Style::pushButtonSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const QStyleOptionButton* buttonOption( qstyleoption_cast( option ) ); if( !buttonOption ) return contentsSize; QSize size( contentsSize ); // add space for arrow if( buttonOption->features & QStyleOptionButton::HasMenu ) { size.rheight() += 2*Metrics::Button_MarginWidth; size.setHeight( qMax( size.height(), int( Metrics::MenuButton_IndicatorWidth ) ) ); size.rwidth() += Metrics::Button_MarginWidth; if( !( buttonOption->icon.isNull() && buttonOption->text.isEmpty() ) ) { size.rwidth() += Metrics::Button_ItemSpacing; } } else size = expandSize( size, Metrics::Button_MarginWidth ); // add space for icon if( !buttonOption->icon.isNull() ) { QSize iconSize = buttonOption->iconSize; if( !iconSize.isValid() ) iconSize = QSize( pixelMetric( PM_SmallIconSize, option, widget ), pixelMetric( PM_SmallIconSize, option, widget ) ); size.setHeight( qMax( size.height(), iconSize.height() ) ); if( !buttonOption->text.isEmpty() ) { size.rwidth() += Metrics::Button_ItemSpacing; } } // make sure buttons have a minimum width if( !buttonOption->text.isEmpty() ) { size.rwidth() = qMax( size.rwidth(), int( Metrics::Button_MinWidth ) ); } // finally add margins return expandSize( size, Metrics::Frame_FrameWidth ); } //______________________________________________________________ QSize Style::toolButtonSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { // cast option and check const QStyleOptionToolButton* toolButtonOption = qstyleoption_cast( option ); if( !toolButtonOption ) return contentsSize; // copy size QSize size = contentsSize; // get relevant state flags const State& state( option->state ); const bool autoRaise( state & State_AutoRaise ); const bool hasPopupMenu( toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup ); const bool hasInlineIndicator( toolButtonOption->features&QStyleOptionToolButton::HasMenu && toolButtonOption->features&QStyleOptionToolButton::PopupDelay && !hasPopupMenu ); const int marginWidth( autoRaise ? Metrics::ToolButton_MarginWidth : Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth ); if( hasInlineIndicator ) size.rwidth() += Metrics::ToolButton_InlineIndicatorWidth; size = expandSize( size, marginWidth ); return size; } //______________________________________________________________ QSize Style::menuBarItemSizeFromContents( const QStyleOption*, const QSize& contentsSize, const QWidget* ) const { return expandSize( contentsSize, Metrics::MenuBarItem_MarginWidth, Metrics::MenuBarItem_MarginHeight ); } //______________________________________________________________ QSize Style::menuItemSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const QStyleOptionMenuItem* menuItemOption = qstyleoption_cast( option ); if( !menuItemOption ) return contentsSize; // First, we calculate the intrinsic size of the item. // this must be kept consistent with what's in drawMenuItemControl QSize size( contentsSize ); switch( menuItemOption->menuItemType ) { case QStyleOptionMenuItem::Normal: case QStyleOptionMenuItem::DefaultItem: case QStyleOptionMenuItem::SubMenu: { const int iconWidth( isQtQuickControl( option, widget ) ? qMax( pixelMetric(PM_SmallIconSize, option, widget ), menuItemOption->maxIconWidth ) : menuItemOption->maxIconWidth ); int leftColumnWidth( iconWidth ); // add space with respect to text leftColumnWidth += Metrics::MenuItem_ItemSpacing; // add checkbox indicator width if( menuItemOption->menuHasCheckableItems ) { leftColumnWidth += Metrics::CheckBox_Size + Metrics::MenuItem_ItemSpacing; } // add spacing for accelerator /* Note: The width of the accelerator itself is not included here since Qt will add that on separately after obtaining the sizeFromContents() for each menu item in the menu to be shown ( see QMenuPrivate::calcActionRects() ) */ const bool hasAccelerator( menuItemOption->text.indexOf( QLatin1Char( '\t' ) ) >= 0 ); if( hasAccelerator ) size.rwidth() += Metrics::MenuItem_AcceleratorSpace; // right column const int rightColumnWidth = Metrics::MenuButton_IndicatorWidth + Metrics::MenuItem_ItemSpacing; size.rwidth() += leftColumnWidth + rightColumnWidth; // make sure height is large enough for icon and arrow size.setHeight( qMax( size.height(), int(Metrics::MenuButton_IndicatorWidth) ) ); size.setHeight( qMax( size.height(), int(Metrics::CheckBox_Size) ) ); size.setHeight( qMax( size.height(), iconWidth ) ); return expandSize( size, Metrics::MenuItem_MarginWidth ); } case QStyleOptionMenuItem::Separator: { if( menuItemOption->text.isEmpty() && menuItemOption->icon.isNull() ) { return expandSize( QSize(0,1), Metrics::MenuItem_MarginWidth ); } else { // build toolbutton option const QStyleOptionToolButton toolButtonOption( separatorMenuItemOption( menuItemOption, widget ) ); // make sure height is large enough for icon and text const int iconWidth( qMax( pixelMetric(PM_SmallIconSize, option, widget ), menuItemOption->maxIconWidth ) ); const int textHeight( menuItemOption->fontMetrics.height() ); if( !menuItemOption->icon.isNull() ) size.setHeight( qMax( size.height(), iconWidth ) ); if( !menuItemOption->text.isEmpty() ) { size.setHeight( qMax( size.height(), textHeight ) ); size.setWidth( qMax( size.width(), menuItemOption->fontMetrics.width( menuItemOption->text ) ) ); } return sizeFromContents( CT_ToolButton, &toolButtonOption, size, widget ); } } // for all other cases, return input default: return contentsSize; } } //______________________________________________________________ QSize Style::tabWidgetSizeFromContents( const QStyleOption*, const QSize& contentsSize, const QWidget* ) const { return expandSize( contentsSize, Metrics::TabWidget_MarginWidth ); } //______________________________________________________________ QSize Style::tabBarTabSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { const auto tabOption( qstyleoption_cast( option ) ); - #if OXYGEN_USE_KDE4 - const auto tabOptionV3( qstyleoption_cast( option ) ); - #else const auto tabOptionV3( qstyleoption_cast( option ) ); - #endif const bool hasText( tabOption && !tabOption->text.isEmpty() ); const bool hasIcon( tabOption && !tabOption->icon.isNull() ); const bool hasLeftButton( tabOptionV3 && !tabOptionV3->leftButtonSize.isEmpty() ); const bool hasRightButton( tabOptionV3 && !tabOptionV3->leftButtonSize.isEmpty() ); // calculate width increment for horizontal tabs int widthIncrement = 0; if( hasIcon && !( hasText || hasLeftButton || hasRightButton ) ) widthIncrement -= 4; if( hasText && hasIcon ) widthIncrement += Metrics::TabBar_TabItemSpacing; if( hasLeftButton && ( hasText || hasIcon ) ) widthIncrement += Metrics::TabBar_TabItemSpacing; if( hasRightButton && ( hasText || hasIcon || hasLeftButton ) ) widthIncrement += Metrics::TabBar_TabItemSpacing; // add margins QSize size( contentsSize ); // compare to minimum size const bool verticalTabs( tabOption && isVerticalTab( tabOption ) ); if( verticalTabs ) { size.rwidth() += 2*Metrics::TabBar_TabOffset; size.rheight() += widthIncrement; if( hasIcon && !hasText ) size = size.expandedTo( QSize( Metrics::TabBar_TabMinHeight, 0 ) ); else size = size.expandedTo( QSize( Metrics::TabBar_TabMinHeight, Metrics::TabBar_TabMinWidth ) ); } else { size.rheight() += 2*Metrics::TabBar_TabOffset; size.rwidth() += widthIncrement; if( hasIcon && !hasText ) size = size.expandedTo( QSize( 0, Metrics::TabBar_TabMinHeight ) ); else size = size.expandedTo( QSize( Metrics::TabBar_TabMinWidth, Metrics::TabBar_TabMinHeight ) ); } return size; } //______________________________________________________________ QSize Style::headerSectionSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { // cast option and check const QStyleOptionHeader* headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return contentsSize; // get text size const bool horizontal( headerOption->orientation == Qt::Horizontal ); const bool hasText( !headerOption->text.isEmpty() ); const bool hasIcon( !headerOption->icon.isNull() ); const QSize textSize( hasText ? headerOption->fontMetrics.size( 0, headerOption->text ) : QSize() ); const QSize iconSize( hasIcon ? QSize( 22,22 ) : QSize() ); // contents width int contentsWidth( 0 ); if( hasText ) contentsWidth += textSize.width(); if( hasIcon ) { contentsWidth += iconSize.width(); if( hasText ) contentsWidth += Metrics::Header_ItemSpacing; } // contents height int contentsHeight( headerOption->fontMetrics.height() ); if( hasIcon ) contentsHeight = qMax( contentsHeight, iconSize.height() ); if( horizontal && headerOption->sortIndicator != QStyleOptionHeader::None ) { // also add space for sort indicator contentsWidth += Metrics::Header_ArrowSize + Metrics::Header_ItemSpacing; contentsHeight = qMax( contentsHeight, int(Metrics::Header_ArrowSize) ); } // update contents size, add margins and return const QSize size( contentsSize.expandedTo( QSize( contentsWidth, contentsHeight ) ) ); return expandSize( size, Metrics::Header_MarginWidth ); } //______________________________________________________________ QSize Style::itemViewItemSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // call base class - QSize size( ParentStyleClass::sizeFromContents( CT_ItemViewItem, option, contentsSize, widget ) ); + QSize size( KStyle::sizeFromContents( CT_ItemViewItem, option, contentsSize, widget ) ); // add margins return expandSize( size, Metrics::ItemView_ItemMarginWidth ); } //___________________________________________________________________________________ bool Style::drawFramePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); - #if QT_VERSION >= 0x050000 const bool isInputWidget( ( widget && widget->testAttribute( Qt::WA_Hover ) ) || ( isQtQuickControl( option, widget ) && option->styleObject->property( "elementType" ).toString() == QStringLiteral( "edit") ) ); - #else - const bool isInputWidget( widget && widget->testAttribute( Qt::WA_Hover ) ); - #endif const bool mouseOver( enabled && isInputWidget && ( state & State_MouseOver ) ); const bool hasFocus( enabled && isInputWidget && ( state & State_HasFocus ) ); // assume focus takes precedence over hover _animations->inputWidgetEngine().updateState( widget, AnimationFocus, hasFocus ); _animations->inputWidgetEngine().updateState( widget, AnimationHover, mouseOver && !hasFocus ); if( state & State_Sunken ) { // retrieve animation mode and opacity const AnimationMode mode( _animations->inputWidgetEngine().frameAnimationMode( widget ) ); const qreal opacity( _animations->inputWidgetEngine().frameOpacity( widget ) ); if( _frameShadowFactory->isRegistered( widget ) ) { _frameShadowFactory->updateShadowsGeometry( widget, rect ); _frameShadowFactory->updateState( widget, hasFocus, mouseOver, opacity, mode ); } else { StyleOptions options; if( hasFocus ) options |= Focus; if( mouseOver ) options |= Hover; _helper->renderHole( painter, palette.color( QPalette::Window ), rect, options, opacity, mode, TileSet::Ring ); } } else if( state & State_Raised ) { const QRect local( rect ); renderSlab( painter, rect, palette.color( QPalette::Window ), NoFill ); } return true; } //___________________________________________________________________________________ bool Style::drawFrameLineEditPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // make sure there is enough room to render frame if( rect.height() < 2*Metrics::LineEdit_FrameWidth + option->fontMetrics.height() ) { const QColor background( palette.color( QPalette::Base ) ); painter->setPen( Qt::NoPen ); painter->setBrush( background ); painter->drawRect( rect ); return true; } else { // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); // assume focus takes precedence over hover _animations->inputWidgetEngine().updateState( widget, AnimationFocus, hasFocus ); _animations->inputWidgetEngine().updateState( widget, AnimationHover, mouseOver && !hasFocus ); // retrieve animation mode and opacity const AnimationMode mode( _animations->inputWidgetEngine().frameAnimationMode( widget ) ); const qreal opacity( _animations->inputWidgetEngine().frameOpacity( widget ) ); // fill painter->setPen( Qt::NoPen ); painter->setBrush( palette.color( QPalette::Base ) ); _helper->fillHole( *painter, rect ); // render hole StyleOptions options; if( hasFocus ) options |= Focus; if( mouseOver ) options |= Hover; _helper->renderHole( painter, palette.color( QPalette::Window ), rect, options, opacity, mode, TileSet::Ring ); } return true; } //___________________________________________________________________________________ bool Style::drawFrameFocusRectPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { if( !widget ) return true; // no focus indicator on buttons, since it is rendered elsewhere if( qobject_cast< const QAbstractButton*>( widget ) ) { return true; } const State& state( option->state ); const QRect rect( option->rect.adjusted( 0, 0, 0, 1 ) ); const QPalette& palette( option->palette ); if( rect.width() < 10 ) return true; const QColor outlineColor( state & State_Selected ? palette.color( QPalette::HighlightedText ):palette.color( QPalette::Highlight ) ); painter->setRenderHint( QPainter::Antialiasing, false ); painter->setPen( outlineColor ); painter->drawLine( rect.bottomLeft(), rect.bottomRight() ); return true; } //___________________________________________________________________________________ bool Style::drawFrameMenuPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // only draw frame for ( expanded ) toolbars // do nothing for other cases if( qobject_cast( widget ) ) { _helper->renderWindowBackground( painter, option->rect, widget, option->palette ); _helper->drawFloatFrame( painter, option->rect, option->palette.window().color(), true ); } else if( isQtQuickControl( option, widget ) ) { // QtQuick Control case painter->fillRect( option->rect, option->palette.window() ); _helper->drawFloatFrame( painter, option->rect, option->palette.window().color(), true ); } return true; } //______________________________________________________________ bool Style::drawFrameGroupBoxPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto frameOption( qstyleoption_cast( option ) ); if( !frameOption ) return true; // no frame for flat groupboxes - #if OXYGEN_USE_KDE4 - QStyleOptionFrameV2 frameOption2( *frameOption ); - if( frameOption2.features & QStyleOptionFrameV2::Flat ) return true; - #else if( frameOption->features & QStyleOptionFrame::Flat ) return true; - #endif // normal frame const QPalette& palette( option->palette ); const QRect& rect( option->rect ); const QColor base( _helper->backgroundColor( palette.color( QPalette::Window ), widget, rect.center() ) ); painter->save(); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); QLinearGradient innerGradient( 0, rect.top()-rect.height()+12, 0, rect.bottom()+rect.height()-19 ); QColor light( _helper->calcLightColor( base ) ); light.setAlphaF( 0.4 ); innerGradient.setColorAt( 0, light ); light.setAlphaF( 0 ); innerGradient.setColorAt( 1, light ); painter->setBrush( innerGradient ); painter->setClipRect( rect.adjusted( 0, 0, 0, -19 ) ); _helper->fillSlab( *painter, rect ); painter->setClipping( false ); _helper->slope( base, 0 ).render( rect, painter ); painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawFrameTabWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const QStyleOptionTabWidgetFrame* tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); const bool reverseLayout( option->direction == Qt::RightToLeft ); /* no frame is drawn when tabbar is empty. this is consistent with the tabWidgetTabContents subelementRect */ if( tabOption->tabBarSize.isEmpty() ) return true; // get tabbar dimensions const int width( tabOption->tabBarSize.width() ); const int height( tabOption->tabBarSize.height() ); // left corner widget const int leftWidth( tabOption->leftCornerWidgetSize.width() ); const int rightWidth( tabOption->rightCornerWidgetSize.width() ); // list of slabs to be drawn SlabRect::List slabs; QRect baseSlabRect( rect ); // render the three free sides switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { // main slab slabs << SlabRect( baseSlabRect, ( TileSet::Ring & ~TileSet::Top ) ); // top if( reverseLayout ) { // left side QRect slabRect( baseSlabRect ); slabRect.setRight( qMax( slabRect.right() - width - leftWidth, slabRect.left() + rightWidth ) ); slabRect.setHeight( 1 ); slabs << SlabRect( slabRect, TileSet::TopLeft ).adjusted( TileSet::DefaultSize ); // right side if( rightWidth > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setLeft( slabRect.right() - rightWidth ); slabRect.setHeight( 1 ); slabs << SlabRect( slabRect, TileSet::TopRight ).adjusted( TileSet::DefaultSize ); } } else { // left side if( leftWidth > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setRight( baseSlabRect.left() + leftWidth ); slabRect.setHeight( 1 ); slabs << SlabRect( slabRect, TileSet::TopLeft ).adjusted( TileSet::DefaultSize ); } // right side QRect slabRect( baseSlabRect ); slabRect.setLeft( qMin( slabRect.left() + width + leftWidth + 1, slabRect.right() - rightWidth ) ); slabRect.setHeight( 1 ); slabs << SlabRect( slabRect, TileSet::TopRight ).adjusted( TileSet::DefaultSize ); } break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Bottom ); if( reverseLayout ) { // left side QRect slabRect( baseSlabRect ); slabRect.setRight( qMax( slabRect.right() -width - leftWidth, slabRect.left() + rightWidth ) ); slabRect.setTop( slabRect.bottom() ); slabs << SlabRect( slabRect, TileSet::BottomLeft ).adjusted( TileSet::DefaultSize ); // right side if( rightWidth > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setLeft( slabRect.right() - rightWidth - TileSet::DefaultSize ); slabRect.setTop( slabRect.bottom() ); slabs << SlabRect( slabRect, TileSet::BottomRight ).adjusted( TileSet::DefaultSize ); } } else { // left side if( leftWidth > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setRight( baseSlabRect.left() + leftWidth ); slabRect.setTop( slabRect.bottom() ); slabs << SlabRect( slabRect, TileSet::BottomLeft ).adjusted( TileSet::DefaultSize ); } // right side QRect slabRect( baseSlabRect ); slabRect.setLeft( qMin( slabRect.left() + width + leftWidth + 1, slabRect.right() - rightWidth ) ); slabRect.setTop( slabRect.bottom() ); slabs << SlabRect( slabRect, TileSet::BottomRight ).adjusted( TileSet::DefaultSize ); } break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Left ); // bottom side QRect slabRect( baseSlabRect ); slabRect.setTop( qMin( slabRect.top() + height, slabRect.bottom() ) ); slabRect.setWidth( 1 ); slabs << SlabRect( slabRect, TileSet::BottomLeft ).adjusted( TileSet::DefaultSize ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Right ); // bottom side QRect slabRect( baseSlabRect ); slabRect.setTop( qMin( slabRect.top() + height, slabRect.bottom() ) ); slabRect.setLeft( slabRect.right() ); slabs << SlabRect( slabRect, TileSet::BottomRight ).adjusted( TileSet::DefaultSize ); break; } break; default: break; } // render registered slabs foreach( const SlabRect& slab, slabs ) { renderSlab( painter, slab, palette.color( QPalette::Window ), NoFill ); } return true; } //___________________________________________________________________________________ bool Style::drawFrameTabBarBasePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // tabbar frame used either for 'separate' tabbar, or in 'document mode' // cast option and check const QStyleOptionTabBarBase* tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; if( tabOption->tabBarRect.isValid() ) { // if tabBar rect is valid, all the frame is handled in tabBarTabShapeControl // nothing to be done here. // on the other hand, invalid tabBarRect corresponds to buttons in tabbars ( e.g. corner buttons ), // and the appropriate piece of frame needs to be drawn return true; } // store palette and rect const QPalette& palette( option->palette ); const QRect& rect( option->rect ); if( !rect.isValid() ) return true; QRect frameRect( rect ); SlabRect slab; switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { frameRect = insideMargin( frameRect, -8, 0 ); frameRect.translate( 0, 4 ); slab = SlabRect( frameRect, TileSet::Top ); break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { frameRect = insideMargin( frameRect, -8, 0 ); frameRect.translate( 0, -4 ); slab = SlabRect( frameRect, TileSet::Bottom ); break; } default: return true; } // render registered slabs renderSlab( painter, slab, palette.color( QPalette::Window ), NoFill ); return true; } //___________________________________________________________________________________ bool Style::drawFrameWindowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // render _helper->drawFloatFrame( painter, rect, palette.window().color(), false ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorArrowPrimitive( ArrowOrientation orientation, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // store rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); bool mouseOver( enabled && ( state & State_MouseOver ) ); bool hasFocus( enabled && ( state & State_HasFocus ) ); // detect special buttons const bool inTabBar( widget && qobject_cast( widget->parentWidget() ) ); const bool inToolButton( qstyleoption_cast( option ) ); // color QColor color; if( inTabBar ) { // for tabbar arrows one uses animations to get the arrow color // get animation state /* there is no need to update the engine since this was already done when rendering the frame */ const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); StyleOptions styleOptions; if( mouseOver ) styleOptions |= Hover; if( hasFocus ) styleOptions |= Focus; color = _helper->arrowColor( palette, styleOptions, opacity, mode ); } else if( mouseOver && !inToolButton ) { color = _helper->hoverColor( palette ); } else if( inToolButton ) { const bool flat( state & State_AutoRaise ); // cast option const QStyleOptionToolButton* toolButtonOption( static_cast( option ) ); const bool hasPopupMenu( toolButtonOption->subControls & SC_ToolButtonMenu ); if( flat && hasPopupMenu ) { // for menu arrows in flat toolbutton one uses animations to get the arrow color // handle arrow over animation const bool arrowHover( mouseOver && ( toolButtonOption->activeSubControls & SC_ToolButtonMenu ) ); _animations->toolButtonEngine().updateState( widget, AnimationHover, arrowHover ); const bool animated( _animations->toolButtonEngine().isAnimated( widget, AnimationHover ) ); const qreal opacity( _animations->toolButtonEngine().opacity( widget, AnimationHover ) ); StyleOptions styleOptions; if( arrowHover ) styleOptions |= Hover; color = _helper->arrowColor( palette, styleOptions, opacity, animated ? AnimationHover:AnimationNone ); } else { color = palette.color( flat ? QPalette::WindowText : QPalette::ButtonText ); } } else color = palette.color( QPalette::WindowText ); // get arrow polygon const QPolygonF arrow = genericArrow( orientation, ArrowNormal ); const qreal penThickness = 1.6; const qreal offset( qMin( penThickness, qreal( 1 ) ) ); painter->translate( QRectF( rect ).center() ); painter->setRenderHint( QPainter::Antialiasing ); painter->translate( 0,offset ); const QColor background = palette.color( QPalette::Window ); painter->setPen( QPen( _helper->calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->translate( 0,-offset ); painter->setPen( QPen( _helper->decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorHeaderArrowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionHeader *headerOption = qstyleoption_cast( option ); const State& state( option->state ); // arrow orientation ArrowOrientation orientation( ArrowNone ); if( state & State_UpArrow || ( headerOption && headerOption->sortIndicator==QStyleOptionHeader::SortUp ) ) orientation = ArrowUp; else if( state & State_DownArrow || ( headerOption && headerOption->sortIndicator==QStyleOptionHeader::SortDown ) ) orientation = ArrowDown; if( orientation == ArrowNone ) return true; // invert arrows if requested by (hidden) options if( StyleConfigData::viewInvertSortIndicator() ) orientation = (orientation == ArrowUp) ? ArrowDown:ArrowUp; // flags, rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); _animations->headerViewEngine().updateState( widget, rect.topLeft(), mouseOver ); const bool animated( enabled && _animations->headerViewEngine().isAnimated( widget, rect.topLeft() ) ); // define gradient and polygon for drawing arrow const QPolygonF arrow = genericArrow( orientation, ArrowNormal ); QColor color = palette.color( QPalette::WindowText ); const QColor background = palette.color( QPalette::Window ); const QColor highlight( _helper->hoverColor( palette ) ); const qreal penThickness = 1.6; const qreal offset( qMin( penThickness, qreal( 1 ) ) ); if( animated ) { const qreal opacity( _animations->headerViewEngine().opacity( widget, rect.topLeft() ) ); color = KColorUtils::mix( color, highlight, opacity ); } else if( mouseOver ) color = highlight; painter->translate( QRectF(rect).center() ); painter->translate( 0, 1 ); painter->setRenderHint( QPainter::Antialiasing ); painter->translate( 0,offset ); painter->setPen( QPen( _helper->calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->translate( 0,-offset ); painter->setPen( QPen( _helper->decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); return true; } //______________________________________________________________ bool Style::drawPanelButtonCommandPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) && !( widget && widget->focusProxy() ) ); const bool sunken( state & ( State_On|State_Sunken ) ); StyleOptions styleOptions; if( sunken ) styleOptions |= Sunken; if( hasFocus ) styleOptions |= Focus; if( mouseOver ) styleOptions |= Hover; // update animation state _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); // store animation state AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); // decide if widget must be rendered flat. /* The decision is made depending on - whether the "flat" flag is set in the option - whether the widget is hight enough to render both icons and normal margins Note: in principle one should also check for the button text height */ const QStyleOptionButton* buttonOption( qstyleoption_cast< const QStyleOptionButton* >( option ) ); bool flat = ( buttonOption && ( buttonOption->features.testFlag( QStyleOptionButton::Flat ) || ( ( !buttonOption->icon.isNull() ) && sizeFromContents( CT_PushButton, option, buttonOption->iconSize, widget ).height() > rect.height() ) ) ); if( flat ) { if( !sunken ) { const QColor glow( _helper->buttonGlowColor( palette, styleOptions, opacity, mode ) ); if( glow.isValid() ) _helper->slitFocused( glow ).render( rect, painter ); } else { _helper->renderHole( painter, palette.color( QPalette::Window ), rect, styleOptions, opacity, mode, TileSet::Ring ); } } else { // match color to the window background QColor buttonColor( _helper->backgroundColor( palette.color( QPalette::Button ), widget, rect.center() ) ); // merge button color with highlight in case of default button if( enabled && buttonOption && (buttonOption->features&QStyleOptionButton::DefaultButton) ) { const QColor tintColor( _helper->calcLightColor( buttonColor ) ); buttonColor = KColorUtils::mix( buttonColor, tintColor, 0.5 ); } // disable animation for sunken buttons if( sunken ) mode = AnimationNone; renderButtonSlab( painter, rect, buttonColor, styleOptions, opacity, mode, TileSet::Ring ); } return true; } //______________________________________________________________ bool Style::drawPanelButtonToolPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); const bool autoRaised( state & State_AutoRaise ); const bool sunken( state & ( State_On|State_Sunken ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // toolbar animation const bool isInToolBar( widget && qobject_cast( widget->parent() ) ); const bool toolBarAnimated( isInToolBar && widget && ( _animations->toolBarEngine().isAnimated( widget->parentWidget() ) || _animations->toolBarEngine().isFollowMouseAnimated( widget->parentWidget() ) ) ); const QRect animatedRect( ( isInToolBar && widget ) ? _animations->toolBarEngine().animatedRect( widget->parentWidget() ):QRect() ); const QRect childRect( ( widget && widget->parentWidget() ) ? rect.translated( widget->mapToParent( QPoint( 0,0 ) ) ):QRect() ); const QRect currentRect( widget ? _animations->toolBarEngine().currentRect( widget->parentWidget() ):QRect() ); const bool current( isInToolBar && widget && widget->parentWidget() && currentRect.intersects( rect.translated( widget->mapToParent( QPoint( 0,0 ) ) ) ) ); const bool toolBarTimerActive( isInToolBar && widget && _animations->toolBarEngine().isTimerActive( widget->parentWidget() ) ); const qreal toolBarOpacity( ( isInToolBar && widget ) ? _animations->toolBarEngine().opacity( widget->parentWidget() ):0 ); // normal animation state // no need to update, this was already done in drawToolButtonComplexControl const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); // style options StyleOptions styleOptions; if( sunken ) styleOptions |= Sunken; if( hasFocus ) styleOptions |= Focus; if( mouseOver ) styleOptions |= Hover; // non autoraised tool buttons get same slab as regular buttons if( !autoRaised ) { TileSet::Tiles tiles( TileSet::Ring ); // adjust tiles and rect in case of menubutton const QToolButton* toolButton = qobject_cast( widget ); const bool hasPopupMenu( toolButton && toolButton->popupMode() == QToolButton::MenuButtonPopup ); if( hasPopupMenu ) { if( reverseLayout ) tiles &= ~TileSet::Left; else tiles &= ~TileSet::Right; } // match button color to window background const QColor buttonColor( _helper->backgroundColor( palette.color( QPalette::Button ), widget, rect.center() ) ); // render slab renderButtonSlab( painter, rect, buttonColor, styleOptions, opacity, mode, tiles ); return true; } // normal ( auto-raised ) toolbuttons if( sunken ) { // fill hole qreal holeOpacity = 1; const qreal bias = 0.75; if( mode == AnimationHover ) holeOpacity = 1 - bias*opacity; else if( toolBarAnimated && enabled && animatedRect.isNull() && current ) holeOpacity = 1 - bias*toolBarOpacity; else if( enabled && (( toolBarTimerActive && current ) || mouseOver ) ) holeOpacity = 1 - bias; if( holeOpacity > 0 ) { QColor color( _helper->backgroundColor( _helper->calcMidColor( palette.color( QPalette::Window ) ), widget, rect.center() ) ); color = _helper->alphaColor( color, holeOpacity ); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); painter->setBrush( color ); painter->drawRoundedRect( insideMargin( rect, 1 ), 3.5, 3.5 ); } styleOptions |= HoleContrast; if( mode != AnimationNone ) { _helper->renderHole( painter, palette.color( QPalette::Window ), rect, styleOptions, opacity, mode, TileSet::Ring ); } else if( toolBarAnimated ) { if( enabled && animatedRect.isNull() && current ) { _helper->renderHole( painter, palette.color( QPalette::Window ), rect, styleOptions, toolBarOpacity, AnimationHover, TileSet::Ring ); } else { _helper->renderHole( painter, palette.color( QPalette::Window ), rect, HoleContrast ); } } else if( toolBarTimerActive && current ) { _helper->renderHole( painter, palette.color( QPalette::Window ), rect, styleOptions | Hover ); } else { _helper->renderHole( painter, palette.color( QPalette::Window ), rect, styleOptions ); } } else { const QColor glow( _helper->buttonGlowColor( palette, styleOptions, opacity, mode ) ); if( mode != AnimationNone ) _helper->slitFocused( glow ).render( rect, painter ); else if( toolBarAnimated ) { if( enabled && animatedRect.isNull() && current ) { QColor glow( _helper->alphaColor( _helper->hoverColor( palette ), toolBarOpacity ) ); _helper->slitFocused( glow ).render( rect, painter ); } } else if( hasFocus || mouseOver ) { _helper->slitFocused( glow ).render( rect, painter ); } else if( toolBarTimerActive && current ) { _helper->slitFocused( _helper->hoverColor( palette ) ).render( rect, painter ); } } return true; } //______________________________________________________________ bool Style::drawTabBarPanelButtonToolPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QPalette& palette( option->palette ); QRect rect( option->rect ); // adjust rect depending on shape const QTabBar* tabBar( static_cast( widget->parent() ) ); switch( tabBar->shape() ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: rect.adjust( 0, 0, 0, -6 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: rect.adjust( 0, 6, 0, 0 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: rect.adjust( 0, 0, -6, 0 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: rect.adjust( 6, 0, 0, 0 ); break; default: break; } const QPalette local( widget->parentWidget() ? widget->parentWidget()->palette() : palette ); // check whether parent has autofill background flag const QWidget* parent = _helper->checkAutoFillBackground( widget ); if( parent && !qobject_cast( parent ) ) painter->fillRect( rect, parent->palette().color( parent->backgroundRole() ) ); else _helper->renderWindowBackground( painter, rect, widget, local ); return true; } //___________________________________________________________________________________ bool Style::drawPanelScrollAreaCornerPrimitive( const QStyleOption*, QPainter*, const QWidget* widget ) const { // disable painting of PE_PanelScrollAreaCorner // the default implementation fills the rect with the window background color // which does not work for windows that have gradients. // unfortunately, this does not work when scrollbars are children of QWebView, // in which case, false is returned, in order to fall back to the parent style implementation return !( widget && widget->inherits( "QWebView" ) ); } //___________________________________________________________________________________ bool Style::drawPanelMenuPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // do nothing if menu is embedded in another widget // this corresponds to having a transparent background if( widget && !widget->isWindow() ) return true; // cast option and check const QStyleOptionMenuItem* menuItemOption( qstyleoption_cast( option ) ); if( !( menuItemOption && widget ) ) return true; // copy rect and get color const QRect& rect = menuItemOption->rect; const QColor color = menuItemOption->palette.color( widget->window()->backgroundRole() ); const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); if( hasAlpha ) { painter->setCompositionMode( QPainter::CompositionMode_Source ); _helper->roundCorner( color ).render( rect, painter ); painter->setCompositionMode( QPainter::CompositionMode_SourceOver ); painter->setClipPath( _helper->roundedPath( insideMargin( rect, 1 ) ), Qt::IntersectClip ); } _helper->renderMenuBackground( painter, rect, widget, menuItemOption->palette ); if( hasAlpha ) painter->setClipping( false ); _helper->drawFloatFrame( painter, rect, color, !hasAlpha ); return true; } //___________________________________________________________________________________ bool Style::drawPanelTipLabelPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // force registration of widget if( widget && widget->window() ) { _shadowHelper->registerWidget( widget->window(), true ); } const QRect& rect( option->rect ); const QColor color( option->palette.brush( QPalette::ToolTipBase ).color() ); QColor topColor( _helper->backgroundTopColor( color ) ); QColor bottomColor( _helper->backgroundBottomColor( color ) ); // make tooltip semi transparents when possible // alpha is copied from "kdebase/apps/dolphin/tooltips/filemetadatatooltip.cpp" const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); if( hasAlpha && StyleConfigData::toolTipTransparent() ) { if( widget && widget->window() ) { _blurHelper->registerWidget( widget->window() ); } topColor.setAlpha( 220 ); bottomColor.setAlpha( 220 ); } QLinearGradient gradient( 0, rect.top(), 0, rect.bottom() ); gradient.setColorAt( 0, topColor ); gradient.setColorAt( 1, bottomColor ); // contrast pixmap QLinearGradient gradient2( 0, rect.top(), 0, rect.bottom() ); gradient2.setColorAt( 0.5, _helper->calcLightColor( bottomColor ) ); gradient2.setColorAt( 0.9, bottomColor ); painter->save(); if( hasAlpha ) { painter->setRenderHint( QPainter::Antialiasing ); QRectF local( rect ); local.adjust( 0.5, 0.5, -0.5, -0.5 ); painter->setPen( Qt::NoPen ); painter->setBrush( gradient ); painter->drawRoundedRect( local, 4, 4 ); painter->setBrush( Qt::NoBrush ); painter->setPen( QPen( gradient2, 1.1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawRoundedRect( local, 3.5, 3.5 ); } else { painter->setPen( Qt::NoPen ); painter->setBrush( gradient ); painter->drawRect( rect ); painter->setBrush( Qt::NoBrush ); painter->setPen( QPen( gradient2, 1.1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawRect( rect ); } painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawPanelItemViewItemPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check - #if OXYGEN_USE_KDE4 - const auto viewItemOption = qstyleoption_cast( option ); - #else const auto viewItemOption = qstyleoption_cast( option ); - #endif if( !viewItemOption ) return false; // try cast widget const auto view = qobject_cast( widget ); // store palette and rect const auto& palette( option->palette ); QRect rect( option->rect ); // store flags const State& state( option->state ); const bool mouseOver( ( state & State_MouseOver ) && (!view || view->selectionMode() != QAbstractItemView::NoSelection) ); const bool selected( state & State_Selected ); const bool enabled( state & State_Enabled ); const bool active( state & State_Active ); const bool hasCustomBackground( viewItemOption->backgroundBrush.style() != Qt::NoBrush && !selected ); const bool hasSolidBackground( !hasCustomBackground || viewItemOption->backgroundBrush.style() == Qt::SolidPattern ); if( !mouseOver && !selected && !hasCustomBackground && !( viewItemOption->features & QStyleOptionViewItemV2::Alternate ) ) { return true; } QPalette::ColorGroup colorGroup; if( enabled ) colorGroup = active ? QPalette::Normal : QPalette::Inactive; else colorGroup = QPalette::Disabled; QColor color; if( hasCustomBackground && hasSolidBackground ) color = viewItemOption->backgroundBrush.color(); else color = palette.color( colorGroup, QPalette::Highlight ); if( mouseOver && !hasCustomBackground ) { if( !selected ) color.setAlphaF( 0.2 ); else color = color.lighter( 110 ); } if( viewItemOption && ( viewItemOption->features & QStyleOptionViewItemV2::Alternate ) ) { painter->fillRect( option->rect, palette.brush( colorGroup, QPalette::AlternateBase ) ); } if( !mouseOver && !selected && !hasCustomBackground ) { return true; } if( hasCustomBackground && !hasSolidBackground ) { const QPointF oldBrushOrigin = painter->brushOrigin(); painter->setBrushOrigin( viewItemOption->rect.topLeft() ); painter->setBrush( viewItemOption->backgroundBrush ); painter->setPen( Qt::NoPen ); painter->drawRect( viewItemOption->rect ); painter->setBrushOrigin( oldBrushOrigin ); } else { // get selection tileset TileSet tileSet( _helper->selection( color, rect.height(), hasCustomBackground ) ); bool roundedLeft = false; bool roundedRight = false; if( viewItemOption ) { - #if OXYGEN_USE_KDE4 - roundedLeft = ( viewItemOption->viewItemPosition == QStyleOptionViewItemV4::Beginning ); - roundedRight = ( viewItemOption->viewItemPosition == QStyleOptionViewItemV4::End ); - - if( viewItemOption->viewItemPosition == QStyleOptionViewItemV4::OnlyOne || - viewItemOption->viewItemPosition == QStyleOptionViewItemV4::Invalid || - ( view && view->selectionBehavior() != QAbstractItemView::SelectRows ) ) - { - roundedLeft = true; - roundedRight = true; - } - - #else roundedLeft = ( viewItemOption->viewItemPosition == QStyleOptionViewItem::Beginning ); roundedRight = ( viewItemOption->viewItemPosition == QStyleOptionViewItem::End ); if( viewItemOption->viewItemPosition == QStyleOptionViewItem::OnlyOne || viewItemOption->viewItemPosition == QStyleOptionViewItem::Invalid || ( view && view->selectionBehavior() != QAbstractItemView::SelectRows ) ) { roundedLeft = true; roundedRight = true; } - #endif - } const bool reverseLayout( option->direction == Qt::RightToLeft ); // define tiles TileSet::Tiles tiles( TileSet::Center ); if( !reverseLayout ? roundedLeft : roundedRight ) tiles |= TileSet::Left; if( !reverseLayout ? roundedRight : roundedLeft ) tiles |= TileSet::Right; // adjust rect and render rect = tileSet.adjust( rect, tiles ); if( rect.isValid() ) tileSet.render( rect, painter, tiles ); } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorMenuCheckMarkPrimitive( const QStyleOption *option, QPainter *painter, const QWidget * ) const { const QRect& rect( option->rect ); const State& state( option->state ); const QPalette& palette( option->palette ); const bool enabled( state & State_Enabled ); StyleOptions styleOptions( NoFill ); if( !enabled ) styleOptions |= Disabled; renderCheckBox( painter, rect, palette, styleOptions, CheckOn ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorCheckBoxPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // get rect const QRect& rect( option->rect ); const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); StyleOptions styleOptions; if( !enabled ) styleOptions |= Disabled; if( mouseOver ) styleOptions |= Hover; if( hasFocus ) styleOptions |= Focus; // get checkbox state CheckBoxState checkBoxState; if( state & State_NoChange ) checkBoxState = CheckTriState; else if( state & State_Sunken ) checkBoxState = CheckSunken; else if( state & State_On ) checkBoxState = CheckOn; else checkBoxState = CheckOff; // match button color to window background QPalette palette( option->palette ); palette.setColor( QPalette::Button, _helper->backgroundColor( palette.color( QPalette::Button ), widget, rect.center() ) ); // animation state: mouseOver has precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus&&!mouseOver ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); renderCheckBox( painter, rect, palette, styleOptions, checkBoxState, opacity, mode ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorRadioButtonPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect const QRect& rect( option->rect ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( state & State_HasFocus ); StyleOptions styleOptions; if( !enabled ) styleOptions |= Disabled; if( mouseOver ) styleOptions |= Hover; if( hasFocus ) styleOptions |= Focus; CheckBoxState checkBoxState; if( state & State_Sunken ) checkBoxState = CheckSunken; else if( state & State_On ) checkBoxState = CheckOn; else checkBoxState = CheckOff; // match button color to window background QPalette palette( option->palette ); palette.setColor( QPalette::Button, _helper->backgroundColor( palette.color( QPalette::Button ), widget, rect.center() ) ); // animation state: mouseOver has precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus&&!mouseOver ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); renderRadioButton( painter, rect, palette, styleOptions, checkBoxState, opacity, mode ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorButtonDropDownPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionToolButton* toolButtonOption( qstyleoption_cast( option ) ); if( !toolButtonOption ) return true; // copy palette and rect const QPalette& palette( option->palette ); const QRect& rect( option->rect ); // store state const State& state( option->state ); const bool autoRaise( state & State_AutoRaise ); // do nothing for autoraise buttons if( autoRaise || !(toolButtonOption->subControls & SC_ToolButtonMenu) ) return true; // store state const bool enabled( state & State_Enabled ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool sunken( enabled && ( state & State_Sunken ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // match button color to window background const QColor highlight( _helper->hoverColor( palette ) ); const QColor background( _helper->backgroundColor( palette.color( QPalette::Button ), widget, rect.center() ) ); StyleOptions styleOptions; if( hasFocus ) styleOptions |= Focus; if( mouseOver ) styleOptions |= Hover; // update animation state // mouse over takes precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); // paint frame TileSet::Tiles tiles( TileSet::Ring ); if( state & ( State_On|State_Sunken ) ) styleOptions |= Sunken; if( reverseLayout ) tiles &= ~TileSet::Right; else tiles &= ~TileSet::Left; painter->setClipRect( rect, Qt::IntersectClip ); renderButtonSlab( painter, rect, background, styleOptions, opacity, mode, tiles ); // draw separating vertical line const QColor color( palette.color( QPalette::Button ) ); const QColor light =_helper->alphaColor( _helper->calcLightColor( color ), 0.6 ); QColor dark = _helper->calcDarkColor( color ); dark.setAlpha( 200 ); const int top( rect.top()+ (sunken ? 3:2) ); const int bottom( rect.bottom()-4 ); painter->setPen( QPen( light,1 ) ); if( reverseLayout ) { painter->drawLine( rect.right()+1, top+1, rect.right()+1, bottom ); painter->drawLine( rect.right()-1, top+2, rect.right()-1, bottom ); painter->setPen( dark ); painter->drawLine( rect.right(), top, rect.right(), bottom ); } else { painter->drawLine( rect.left()-1, top+1, rect.left()-1, bottom-1 ); painter->drawLine( rect.left()+1, top+1, rect.left()+1, bottom-1 ); painter->setPen( dark ); painter->drawLine( rect.left(), top, rect.left(), bottom ); } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorTabClosePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { if( _tabCloseIcon.isNull() ) { // load the icon on-demand: in the constructor, KDE is not yet ready to find it! _tabCloseIcon = QIcon::fromTheme( QStringLiteral( "dialog-close" ) ); if( _tabCloseIcon.isNull() ) return false; } const int size( pixelMetric(QStyle::PM_SmallIconSize) ); QIcon::Mode mode; if( option->state & State_Enabled ) { if( option->state & State_Raised ) mode = QIcon::Active; else mode = QIcon::Normal; } else mode = QIcon::Disabled; if( !(option->state & State_Raised) && !(option->state & State_Sunken) && !(option->state & QStyle::State_Selected)) mode = QIcon::Disabled; QIcon::State state = option->state & State_Sunken ? QIcon::On:QIcon::Off; QPixmap pixmap( _tabCloseIcon.pixmap(size, mode, state) ); drawItemPixmap( painter, option->rect, Qt::AlignCenter, pixmap ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorTabTearPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionTab* tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; const QRect& rect( option->rect ); const QPalette& palette( option->palette ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // in fact with current version of Qt ( 4.6.0 ) the cast fails and document mode is always false // this will hopefully be fixed in later versions - #if OXYGEN_USE_KDE4 - const auto tabOptionV3( qstyleoption_cast( option ) ); - #else const auto tabOptionV3( qstyleoption_cast( option ) ); - #endif bool documentMode( tabOptionV3 ? tabOptionV3->documentMode : false ); const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : nullptr; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); QRect gradientRect( rect ); switch( tabOption->shape ) { case QTabBar::TriangularNorth: case QTabBar::RoundedNorth: gradientRect.adjust( 0, 0, 0, -5 ); break; case QTabBar::TriangularSouth: case QTabBar::RoundedSouth: gradientRect.adjust( 0, 5, 0, 0 ); break; case QTabBar::TriangularWest: case QTabBar::RoundedWest: gradientRect.adjust( 0, 0, -5, 0 ); break; case QTabBar::TriangularEast: case QTabBar::RoundedEast: gradientRect.adjust( 5, 0, 0, 0 ); break; default: return true; } // fade tabbar QPixmap pixmap( gradientRect.size() ); { pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); const bool verticalTabs( isVerticalTab( tabOption ) ); int width = 0; int height = 0; if( verticalTabs ) height = gradientRect.height(); else width = gradientRect.width(); QLinearGradient grad; if( reverseLayout && !verticalTabs ) grad = QLinearGradient( 0, 0, width, height ); else grad = QLinearGradient( width, height, 0, 0 ); grad.setColorAt( 0, Qt::transparent ); grad.setColorAt( 0.6, Qt::black ); if( widget ) { _helper->renderWindowBackground( &painter, pixmap.rect(), widget, palette ); } painter.setCompositionMode( QPainter::CompositionMode_DestinationAtop ); painter.fillRect( pixmap.rect(), QBrush( grad ) ); painter.end(); } // draw pixmap painter->drawPixmap( gradientRect.topLeft() + QPoint( 0,-1 ), pixmap ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorToolBarHandlePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // do nothing if disabled from options if( !StyleConfigData::toolBarDrawItemSeparator() ) { return true; } // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool horizontal( state & State_Horizontal ); int counter( 1 ); if( horizontal ) { const int center( rect.left()+ rect.width()/2 ); for( int j = rect.top()+2; j <= rect.bottom()-3; j+=3, ++counter ) { if( counter%2 == 0 ) _helper->renderDot( painter, QPoint( center+1, j ), palette.color( QPalette::Window ) ); else _helper->renderDot( painter, QPoint( center-2, j ), palette.color( QPalette::Window ) ); } } else { const int center( rect.top()+ rect.height()/2 ); for( int j = rect.left()+2; j <= rect.right()-3; j+=3, ++counter ) { if( counter%2 == 0 ) _helper->renderDot( painter, QPoint( j, center+1 ), palette.color( QPalette::Window ) ); else _helper->renderDot( painter, QPoint( j, center-2 ), palette.color( QPalette::Window ) ); } } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorToolBarSeparatorPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { /* do nothing if disabled from options also need to check if widget is a combobox, because of Qt hack using 'toolbar' separator primitive for rendering separators in comboboxes */ if( !( StyleConfigData::toolBarDrawItemSeparator() || qobject_cast( widget ) ) ) { return true; } // store rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool separatorIsVertical( state & State_Horizontal ); // define color and render const QColor color( palette.color( QPalette::Window ) ); if( separatorIsVertical ) _helper->drawSeparator( painter, rect, color, Qt::Vertical ); else _helper->drawSeparator( painter, rect, color, Qt::Horizontal ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorBranchPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // state const State& state( option->state ); const bool reverseLayout( option->direction == Qt::RightToLeft ); //draw expander int expanderAdjust = 0; if( state & State_Children ) { int sizeLimit = qMin( rect.width(), rect.height() ); const bool expanderOpen( state & State_Open ); // make sure size limit is odd expanderAdjust = sizeLimit/2 + 1; // flags const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); // color const QColor expanderColor( mouseOver ? _helper->hoverColor( palette ):palette.color( QPalette::Text ) ); // get arrow size from option ArrowSize size = ArrowSmall; qreal penThickness( 1.2 ); switch( StyleConfigData::viewTriangularExpanderSize() ) { case StyleConfigData::TE_TINY: size = ArrowTiny; break; default: case StyleConfigData::TE_SMALL: size = ArrowSmall; break; case StyleConfigData::TE_NORMAL: penThickness = 1.6; size = ArrowNormal; break; } // get arrows polygon QPolygonF arrow; if( expanderOpen ) arrow = genericArrow( ArrowDown, size ); else arrow = genericArrow( reverseLayout ? ArrowLeft:ArrowRight, size ); // render painter->save(); painter->translate( QRectF( rect ).center() ); painter->setPen( QPen( expanderColor, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->setRenderHint( QPainter::Antialiasing ); painter->drawPolyline( arrow ); painter->restore(); } // tree branches if( !StyleConfigData::viewDrawTreeBranchLines() ) return true; const QPoint center( rect.center() ); const QColor lineColor( KColorUtils::mix( palette.color( QPalette::Text ), palette.color( QPalette::Window ), 0.8 ) ); painter->setRenderHint( QPainter::Antialiasing, false ); painter->setPen( lineColor ); if( state & ( State_Item | State_Children | State_Sibling ) ) { const QLine line( QPoint( center.x(), rect.top() ), QPoint( center.x(), center.y() - expanderAdjust ) ); painter->drawLine( line ); } //The right/left ( depending on dir ) line gets drawn if we have an item if( state & State_Item ) { const QLine line = reverseLayout ? QLine( QPoint( rect.left(), center.y() ), QPoint( center.x() - expanderAdjust, center.y() ) ): QLine( QPoint( center.x() + expanderAdjust, center.y() ), QPoint( rect.right(), center.y() ) ); painter->drawLine( line ); } //The bottom if we have a sibling if( state & State_Sibling ) { const QLine line( QPoint( center.x(), center.y() + expanderAdjust ), QPoint( center.x(), rect.bottom() ) ); painter->drawLine( line ); } return true; } //___________________________________________________________________________________ bool Style::drawWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // check widget and attributes if( !widget || !widget->testAttribute( Qt::WA_StyledBackground ) || widget->testAttribute( Qt::WA_NoSystemBackground ) ) return false; if( !( ( widget->windowFlags() & Qt::WindowType_Mask ) & ( Qt::Window|Qt::Dialog ) ) ) return false; if( !widget->isWindow() ) return false; // normal "window" background const QPalette& palette( option->palette ); // do not render background if palette brush has a texture (pixmap or image) const QBrush brush( palette.brush( widget->backgroundRole() ) ); if( !( brush.texture().isNull() && brush.textureImage().isNull() ) ) { return false; } _helper->renderWindowBackground( painter, option->rect, widget, palette ); return true; } //___________________________________________________________________________________ bool Style::drawPushButtonLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionButton* buttonOption( qstyleoption_cast( option ) ); if( !buttonOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool sunken( ( state & State_On ) || ( state & State_Sunken ) ); const bool mouseOver( enabled && (option->state & State_MouseOver) ); const bool flat( buttonOption->features & QStyleOptionButton::Flat ); // content const bool hasIcon( !buttonOption->icon.isNull() ); const bool hasText( !buttonOption->text.isEmpty() ); // contents QRect contentsRect( rect ); // color role const QPalette::ColorRole textRole( flat ? QPalette::WindowText:QPalette::ButtonText ); // menu arrow if( buttonOption->features & QStyleOptionButton::HasMenu ) { // define rect QRect arrowRect( contentsRect ); arrowRect.setLeft( contentsRect.right() - Metrics::MenuButton_IndicatorWidth + 1 ); arrowRect = centerRect( arrowRect, Metrics::MenuButton_IndicatorWidth, Metrics::MenuButton_IndicatorWidth ); contentsRect.setRight( arrowRect.left() - Metrics::Button_ItemSpacing - 1 ); contentsRect.adjust( Metrics::Button_MarginWidth, 0, 0, 0 ); arrowRect = visualRect( option, arrowRect ); // arrow const qreal penThickness = 1.6; QPolygonF arrow = genericArrow( ArrowDown, ArrowNormal ); const QColor color = palette.color( flat ? QPalette::WindowText:QPalette::ButtonText ); const QColor background = palette.color( flat ? QPalette::Window:QPalette::Button ); painter->save(); painter->translate( QRectF( arrowRect ).center() ); painter->setRenderHint( QPainter::Antialiasing ); const qreal offset( qMin( penThickness, qreal( 1 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( _helper->calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->translate( 0,-offset ); painter->setPen( QPen( _helper->decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->restore(); } else contentsRect = insideMargin( contentsRect, Metrics::Button_MarginWidth, 0 ); // icon size QSize iconSize( buttonOption->iconSize ); if( !iconSize.isValid() ) { const int metric( pixelMetric( PM_SmallIconSize, option, widget ) ); iconSize = QSize( metric, metric ); } // text size const int textFlags( _mnemonics->textFlags() | Qt::AlignCenter ); const QSize textSize( option->fontMetrics.size( textFlags, buttonOption->text ) ); // adjust text and icon rect based on options QRect iconRect; QRect textRect; if( hasText && !hasIcon ) textRect = contentsRect; else if( hasIcon && !hasText ) iconRect = contentsRect; else { const int contentsWidth( iconSize.width() + textSize.width() + Metrics::Button_ItemSpacing ); iconRect = QRect( QPoint( contentsRect.left() + (contentsRect.width() - contentsWidth )/2, contentsRect.top() + (contentsRect.height() - iconSize.height())/2 ), iconSize ); textRect = QRect( QPoint( iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, contentsRect.top() + (contentsRect.height() - textSize.height())/2 ), textSize ); } // handle right to left if( iconRect.isValid() ) iconRect = visualRect( option, iconRect ); if( textRect.isValid() ) textRect = visualRect( option, textRect ); // make sure there is enough room for icon if( iconRect.isValid() ) iconRect = centerRect( iconRect, iconSize ); // render icon if( hasIcon && iconRect.isValid() ) { // icon state and mode const QIcon::State iconState( sunken ? QIcon::On : QIcon::Off ); QIcon::Mode iconMode; if( !enabled ) iconMode = QIcon::Disabled; else if( mouseOver && flat ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; const QPixmap pixmap = buttonOption->icon.pixmap( iconSize, iconMode, iconState ); drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); } // render text if( hasText && textRect.isValid() ) { drawItemText( painter, textRect, textFlags, palette, enabled, buttonOption->text, textRole ); } return true; } //___________________________________________________________________________________ bool Style::drawToolButtonLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionToolButton* toolButtonOption( qstyleoption_cast(option) ); // copy rect and palette const QRect& rect = option->rect; const QPalette& palette = option->palette; // state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool sunken( ( state & State_On ) || ( state & State_Sunken ) ); const bool mouseOver( enabled && (option->state & State_MouseOver) ); const bool flat( state & State_AutoRaise ); const bool hasArrow( toolButtonOption->features & QStyleOptionToolButton::Arrow ); const bool hasIcon( !( hasArrow || toolButtonOption->icon.isNull() ) ); const bool hasText( !toolButtonOption->text.isEmpty() ); // icon size const QSize iconSize( toolButtonOption->iconSize ); // text size int textFlags( _mnemonics->textFlags() ); const QSize textSize( option->fontMetrics.size( textFlags, toolButtonOption->text ) ); // adjust text and icon rect based on options QRect iconRect; QRect textRect; if( hasText && ( !(hasArrow||hasIcon) || toolButtonOption->toolButtonStyle == Qt::ToolButtonTextOnly ) ) { // text only textRect = rect; textFlags |= Qt::AlignCenter; } else if( (hasArrow||hasIcon) && (!hasText || toolButtonOption->toolButtonStyle == Qt::ToolButtonIconOnly ) ) { // icon only iconRect = rect; } else if( toolButtonOption->toolButtonStyle == Qt::ToolButtonTextUnderIcon ) { const int contentsHeight( iconSize.height() + textSize.height() + Metrics::ToolButton_ItemSpacing ); iconRect = QRect( QPoint( rect.left() + (rect.width() - iconSize.width())/2, rect.top() + (rect.height() - contentsHeight)/2 ), iconSize ); textRect = QRect( QPoint( rect.left() + (rect.width() - textSize.width())/2, iconRect.bottom() + Metrics::ToolButton_ItemSpacing + 1 ), textSize ); textFlags |= Qt::AlignCenter; } else { const bool leftAlign( widget && widget->property( PropertyNames::toolButtonAlignment ).toInt() == Qt::AlignLeft ); if( leftAlign ) { const int marginWidth( Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth + 1 ); iconRect = QRect( QPoint( rect.left() + marginWidth, rect.top() + (rect.height() - iconSize.height())/2 ), iconSize ); } else { const int contentsWidth( iconSize.width() + textSize.width() + Metrics::ToolButton_ItemSpacing ); iconRect = QRect( QPoint( rect.left() + (rect.width() - contentsWidth )/2, rect.top() + (rect.height() - iconSize.height())/2 ), iconSize ); } textRect = QRect( QPoint( iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, rect.top() + (rect.height() - textSize.height())/2 ), textSize ); // handle right to left layouts iconRect = visualRect( option, iconRect ); textRect = visualRect( option, textRect ); textFlags |= Qt::AlignLeft | Qt::AlignVCenter; } // make sure there is enough room for icon if( iconRect.isValid() ) iconRect = centerRect( iconRect, iconSize ); // render arrow or icon if( hasArrow && iconRect.isValid() ) { QStyleOptionToolButton copy( *toolButtonOption ); copy.rect = iconRect; switch( toolButtonOption->arrowType ) { case Qt::LeftArrow: drawPrimitive( PE_IndicatorArrowLeft, ©, painter, widget ); break; case Qt::RightArrow: drawPrimitive( PE_IndicatorArrowRight, ©, painter, widget ); break; case Qt::UpArrow: drawPrimitive( PE_IndicatorArrowUp, ©, painter, widget ); break; case Qt::DownArrow: drawPrimitive( PE_IndicatorArrowDown, ©, painter, widget ); break; default: break; } } else if( hasIcon && iconRect.isValid() ) { // icon state and mode const QIcon::State iconState( sunken ? QIcon::On : QIcon::Off ); QIcon::Mode iconMode; if( !enabled ) iconMode = QIcon::Disabled; else if( mouseOver && flat ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; const QPixmap pixmap = toolButtonOption->icon.pixmap( iconSize, iconMode, iconState ); drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); } // render text if( hasText && textRect.isValid() ) { const QPalette::ColorRole textRole( flat ? QPalette::WindowText: QPalette::ButtonText ); painter->setFont(toolButtonOption->font); drawItemText( painter, textRect, textFlags, palette, enabled, toolButtonOption->text, textRole ); } return true; } //___________________________________________________________________________________ bool Style::drawMenuBarItemControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionMenuItem* menuItemOption = qstyleoption_cast( option ); if( !menuItemOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( enabled && (state & State_Selected) ); const bool sunken( state & State_Sunken ); const bool useStrongFocus = StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG; if( enabled ) { const bool active( state & State_Selected ); const bool animated( _animations->menuBarEngine().isAnimated( widget, rect.topLeft() ) ); const qreal opacity( _animations->menuBarEngine().opacity( widget, rect.topLeft() ) ); const QRect currentRect( _animations->menuBarEngine().currentRect( widget, rect.topLeft() ) ); const QRect animatedRect( _animations->menuBarEngine().animatedRect( widget ) ); const bool intersected( animatedRect.intersects( rect ) ); const bool current( currentRect.contains( rect.topLeft() ) ); const bool timerIsActive( _animations->menuBarEngine().isTimerActive( widget ) ); // do nothing in case of empty intersection between animated rect and current if( ( intersected || !animated || animatedRect.isNull() ) && ( active || animated || timerIsActive ) ) { QColor color( _helper->calcMidColor( palette.color( QPalette::Window ) ) ); if( StyleConfigData::menuHighlightMode() != StyleConfigData::MM_DARK ) { if( state & State_Sunken ) { if( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG ) color = palette.color( QPalette::Highlight ); else color = KColorUtils::mix( color, KColorUtils::tint( color, palette.color( QPalette::Highlight ), 0.6 ) ); } else { if( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG ) color = KColorUtils::tint( color, _helper->hoverColor( palette ) ); else color = KColorUtils::mix( color, KColorUtils::tint( color, _helper->hoverColor( palette ) ) ); } } else color = _helper->backgroundColor( color, widget, rect.center() ); // drawing if( animated && intersected ) { _helper->holeFlat( color, 0 ).render( insideMargin( animatedRect, 1 ), painter, TileSet::Full ); } else if( timerIsActive && current ) { _helper->holeFlat( color, 0 ).render( insideMargin( rect, 1 ), painter, TileSet::Full ); } else if( animated && current ) { color.setAlphaF( opacity ); _helper->holeFlat( color, 0 ).render( insideMargin( rect, 1 ), painter, TileSet::Full ); } else if( active ) { _helper->holeFlat( color, 0 ).render( insideMargin( rect, 1 ), painter, TileSet::Full ); } } } /* check if item as an icon, in which case only the icon should be rendered consistently with comment in QMenuBarPrivate::calcActionRects */ if( !menuItemOption->icon.isNull() ) { // icon size is forced to SmallIconSize const auto iconSize = pixelMetric(QStyle::PM_SmallIconSize, nullptr, widget); const auto iconRect = centerRect( rect, iconSize, iconSize ); // decide icon mode and state QIcon::Mode iconMode; QIcon::State iconState; if( !enabled ) { iconMode = QIcon::Disabled; iconState = QIcon::Off; } else { if( useStrongFocus && sunken ) iconMode = QIcon::Selected; else if( selected ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; iconState = sunken ? QIcon::On : QIcon::Off; } const auto pixmap = menuItemOption->icon.pixmap( iconSize, iconMode, iconState ); drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); } else { // text role QPalette::ColorRole role( QPalette::WindowText ); if( useStrongFocus && sunken && enabled ) { role = QPalette::HighlightedText; } // text flags const int textFlags( Qt::AlignCenter|_mnemonics->textFlags() ); drawItemText( painter, rect, textFlags, palette, enabled, menuItemOption->text, role ); } return true; } //___________________________________________________________________________________ bool Style::drawMenuItemControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionMenuItem* menuItemOption = qstyleoption_cast( option ); if( !menuItemOption ) return true; if( menuItemOption->menuItemType == QStyleOptionMenuItem::EmptyArea ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // render background renderMenuItemBackground( option, painter, widget ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( enabled && (state & State_Selected) ); const bool sunken( enabled && (state & (State_On|State_Sunken) ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // Active indicator if( selected ) { // check if there is a 'sliding' animation in progress, in which case, do nothing const QRect animatedRect( _animations->menuEngine().animatedRect( widget ) ); if( animatedRect.isNull() ) { const bool animated( _animations->menuEngine().isAnimated( widget, Current ) ); const QRect currentRect( _animations->menuEngine().currentRect( widget, Current ) ); const bool intersected( currentRect.contains( rect.topLeft() ) ); const QColor color( _helper->menuBackgroundColor( _helper->calcMidColor( palette.color( QPalette::Window ) ), widget, rect.center() ) ); if( animated && intersected ) renderMenuItemRect( option, rect, color, palette, painter, _animations->menuEngine().opacity( widget, Current ) ); else renderMenuItemRect( option, rect, color, palette, painter ); } } // get rect available for contents QRect contentsRect( insideMargin( rect, Metrics::MenuItem_MarginWidth ) ); // deal with separators if( menuItemOption->menuItemType == QStyleOptionMenuItem::Separator ) { // normal separator if( menuItemOption->text.isEmpty() && menuItemOption->icon.isNull() ) { // in all other cases draw regular separator const QColor color( _helper->menuBackgroundColor( palette.color( QPalette::Window ), widget, rect.center() ) ); _helper->drawSeparator( painter, rect, color, Qt::Horizontal ); return true; } else { // separator can have a title and an icon // in that case they are rendered as sunken flat toolbuttons QStyleOptionToolButton toolButtonOption( separatorMenuItemOption( menuItemOption, widget ) ); toolButtonOption.state = State_On|State_Sunken|State_Enabled; drawComplexControl( CC_ToolButton, &toolButtonOption, painter, widget ); return true; } } // define relevant rectangles // checkbox QRect checkBoxRect; if( menuItemOption->menuHasCheckableItems ) { checkBoxRect = QRect( contentsRect.left(), contentsRect.top() + (contentsRect.height()-Metrics::CheckBox_Size)/2 - 1, Metrics::CheckBox_Size, Metrics::CheckBox_Size ); contentsRect.setLeft( checkBoxRect.right() + Metrics::MenuItem_ItemSpacing + 1 ); } // render checkbox indicator const CheckBoxState checkBoxState( menuItemOption->checked ? CheckOn:CheckOff ); if( menuItemOption->checkType == QStyleOptionMenuItem::NonExclusive ) { checkBoxRect = visualRect( option, checkBoxRect ); StyleOptions styleOptions; styleOptions |= Sunken; if( !enabled ) styleOptions |= Disabled; if( mouseOver ) styleOptions |= Hover; if( hasFocus ) styleOptions |= Focus; QPalette localPalette( palette ); localPalette.setColor( QPalette::Window, _helper->menuBackgroundColor( palette.color( QPalette::Window ), widget, rect.topLeft() ) ); renderCheckBox( painter, checkBoxRect, localPalette, styleOptions, checkBoxState ); } else if( menuItemOption->checkType == QStyleOptionMenuItem::Exclusive ) { checkBoxRect = visualRect( option, checkBoxRect ); StyleOptions styleOptions; if( !enabled ) styleOptions |= Disabled; if( mouseOver ) styleOptions |= Hover; if( hasFocus ) styleOptions |= Focus; QPalette localPalette( palette ); localPalette.setColor( QPalette::Window, _helper->menuBackgroundColor( palette.color( QPalette::Window ), widget, rect.topLeft() ) ); renderRadioButton( painter, checkBoxRect, localPalette, styleOptions, checkBoxState ); } // icon const int iconWidth( isQtQuickControl( option, widget ) ? qMax( pixelMetric(PM_SmallIconSize, option, widget ), menuItemOption->maxIconWidth ) : menuItemOption->maxIconWidth ); QRect iconRect( contentsRect.left(), contentsRect.top() + (contentsRect.height()-iconWidth)/2, iconWidth, iconWidth ); contentsRect.setLeft( iconRect.right() + Metrics::MenuItem_ItemSpacing + 1 ); if( !menuItemOption->icon.isNull() ) { const QSize iconSize( pixelMetric( PM_SmallIconSize, option, widget ), pixelMetric( PM_SmallIconSize, option, widget ) ); iconRect = centerRect( iconRect, iconSize ); iconRect = visualRect( option, iconRect ); // icon mode QIcon::Mode mode; if( (StyleConfigData::menuHighlightMode() != StyleConfigData::MM_DARK) && selected ) mode = QIcon::Selected; else if( selected ) mode = QIcon::Active; else if( enabled ) mode = QIcon::Normal; else mode = QIcon::Disabled; // icon state const QIcon::State iconState( sunken ? QIcon::On:QIcon::Off ); const QPixmap icon = menuItemOption->icon.pixmap( iconRect.size(), mode, iconState ); painter->drawPixmap( iconRect, icon ); } // text role const QPalette::ColorRole textRole( ( selected && StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG ) ? QPalette::HighlightedText: QPalette::WindowText ); QRect arrowRect( contentsRect.right() - Metrics::MenuButton_IndicatorWidth + 1, contentsRect.top() + (contentsRect.height()-Metrics::MenuButton_IndicatorWidth)/2, Metrics::MenuButton_IndicatorWidth, Metrics::MenuButton_IndicatorWidth ); contentsRect.setRight( arrowRect.left() - Metrics::MenuItem_ItemSpacing - 1 ); // arrow if( menuItemOption->menuItemType == QStyleOptionMenuItem::SubMenu ) { const qreal penThickness = 1.6; const QColor color = palette.color( textRole ); const QColor background = palette.color( QPalette::Window ); // get arrow shape QPolygonF arrow = genericArrow( option->direction == Qt::LeftToRight ? ArrowRight : ArrowLeft, ArrowNormal ); painter->save(); painter->translate( QRectF( arrowRect ).center() ); painter->setRenderHint( QPainter::Antialiasing ); // white outline const qreal offset( qMin( penThickness, qreal( 1 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( _helper->calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->translate( 0,-offset ); painter->setPen( QPen( _helper->decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->restore(); } // text QRect textRect = contentsRect; if( !menuItemOption->text.isEmpty() ) { // adjust textRect QString text = menuItemOption->text; textRect = centerRect( textRect, textRect.width(), option->fontMetrics.size( _mnemonics->textFlags(), text ).height() ); textRect = visualRect( option, textRect ); // set font painter->setFont( menuItemOption->font ); // locate accelerator and render const int tabPosition( text.indexOf( QLatin1Char( '\t' ) ) ); if( tabPosition >= 0 ) { QString accelerator( text.mid( tabPosition + 1 ) ); text = text.left( tabPosition ); drawItemText( painter, textRect, Qt::AlignRight | Qt::AlignVCenter | _mnemonics->textFlags(), palette, enabled, accelerator, textRole ); } // render text const int textFlags( Qt::AlignVCenter | (reverseLayout ? Qt::AlignRight : Qt::AlignLeft ) | _mnemonics->textFlags() ); drawItemText( painter, textRect, textFlags, palette, enabled, text, textRole ); } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionProgressBar* progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return true; - #if OXYGEN_USE_KDE4 - QStyleOptionProgressBarV2 progressBarOption2 = *progressBarOption; - #else QStyleOptionProgressBar progressBarOption2 = *progressBarOption; - #endif progressBarOption2.rect = subElementRect( SE_ProgressBarGroove, progressBarOption, widget ); drawControl( CE_ProgressBarGroove, &progressBarOption2, painter, widget ); // enable busy animations - #if QT_VERSION >= 0x050000 const QObject* styleObject( widget ? widget:progressBarOption->styleObject ); - #else - const QObject* styleObject( widget ); - #endif if( styleObject && _animations->busyIndicatorEngine().enabled() ) { - #if QT_VERSION >= 0x050000 // register QML object if defined if( !widget && progressBarOption->styleObject ) { _animations->busyIndicatorEngine().registerWidget( progressBarOption->styleObject ); } - #endif _animations->busyIndicatorEngine().setAnimated( styleObject, progressBarOption->maximum == 0 && progressBarOption->minimum == 0 ); } if( _animations->busyIndicatorEngine().isAnimated( styleObject ) ) { progressBarOption2.progress = _animations->busyIndicatorEngine().value(); } // render contents progressBarOption2.rect = subElementRect( SE_ProgressBarContents, progressBarOption, widget ); drawControl( CE_ProgressBarContents, &progressBarOption2, painter, widget ); // render text const bool textVisible( progressBarOption->textVisible ); const bool busy( progressBarOption->minimum == 0 && progressBarOption->maximum == 0 ); if( textVisible && !busy ) { progressBarOption2.rect = subElementRect( SE_ProgressBarLabel, progressBarOption, widget ); drawControl( CE_ProgressBarLabel, &progressBarOption2, painter, widget ); } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarContentsControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const QStyleOptionProgressBar* progressBarOption = qstyleoption_cast( option ); if( !progressBarOption ) return true; // get orientation - #if OXYGEN_USE_KDE4 - const auto progressBarOption2 = qstyleoption_cast( option ); - #else const auto progressBarOption2 = qstyleoption_cast( option ); - #endif - const bool horizontal( !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal ); // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // make sure rect is large enough if( rect.isValid() ) { // calculate dimension int dimension( 20 ); if( progressBarOption2 ) dimension = qMax( 5, horizontal ? rect.height() : rect.width() ); _helper->progressBarIndicator( palette, dimension ).render( rect, painter, TileSet::Full ); } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarGrooveControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { - #if OXYGEN_USE_KDE4 - const auto progressBarOption = qstyleoption_cast( option ); - #else const auto progressBarOption = qstyleoption_cast( option ); - #endif const Qt::Orientation orientation( progressBarOption? progressBarOption->orientation : Qt::Horizontal ); renderScrollBarHole( painter, option->rect, option->palette.color( QPalette::Window ), orientation ); return true; } //___________________________________________________________________________________ bool Style::drawProgressBarLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionProgressBar* progressBarOption = qstyleoption_cast( option ); if( !progressBarOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool reverseLayout = ( option->direction == Qt::RightToLeft ); // get orientation - #if OXYGEN_USE_KDE4 - const auto progressBarOption2 = qstyleoption_cast( option ); - #else const auto progressBarOption2 = qstyleoption_cast( option ); - #endif - const bool horizontal = !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal; // check inverted appearance const bool inverted( progressBarOption2 ? progressBarOption2->invertedAppearance : false ); // rotate label for vertical layout QTransform transform; if( !horizontal ) { if( reverseLayout ) transform.rotate( -90 ); else transform.rotate( 90 ); } painter->setTransform( transform ); const QRect progressRect( transform.inverted().mapRect( subElementRect( SE_ProgressBarContents, progressBarOption, widget ) ) ); QRect textRect( transform.inverted().mapRect( rect ) ); Qt::Alignment hAlign( ( progressBarOption->textAlignment == Qt::AlignLeft ) ? Qt::AlignHCenter : progressBarOption->textAlignment ); /* Figure out the geometry of the indicator. This is copied from drawProgressBarContentsControl */ if( progressRect.isValid() ) { // first pass ( normal ) QRect textClipRect( textRect ); if( horizontal ) { if( (reverseLayout && !inverted) || (inverted && !reverseLayout) ) textClipRect.setRight( progressRect.left() ); else textClipRect.setLeft( progressRect.right() + 1 ); } else if( (reverseLayout && !inverted) || (inverted && !reverseLayout) ) textClipRect.setLeft( progressRect.right() + 1 ); else textClipRect.setRight( progressRect.left() ); painter->setClipRect( textClipRect ); drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, progressBarOption->text, QPalette::WindowText ); // second pass ( highlighted ) painter->setClipRect( progressRect ); drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, progressBarOption->text, QPalette::HighlightedText ); } else { drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, progressBarOption->text, QPalette::WindowText ); } return true; } //___________________________________________________________________________________ bool Style::drawScrollBarSliderControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionSlider *sliderOption = qstyleoption_cast( option ); if( !sliderOption ) return true; // store rect and palette QRect rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const Qt::Orientation orientation( (state & State_Horizontal) ? Qt::Horizontal : Qt::Vertical ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); // update animations _animations->scrollBarEngine().updateState( widget, enabled && ( sliderOption->activeSubControls & SC_ScrollBarSlider ) ); const bool animated( enabled && _animations->scrollBarEngine().isAnimated( widget, SC_ScrollBarSlider ) ); if( orientation == Qt::Horizontal ) rect = insideMargin( rect, 0, 1 ); else rect = insideMargin( rect, 1, 0 ); // render if( animated ) renderScrollBarHandle( painter, rect, palette, orientation, mouseOver, _animations->scrollBarEngine().opacity( widget, SC_ScrollBarSlider ) ); else renderScrollBarHandle( painter, rect, palette, orientation, mouseOver ); return true; } //___________________________________________________________________________________ bool Style::drawScrollBarAddLineControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // do nothing if no buttons are defined if( _addLineButtons == NoButton ) return true; // cast option and check const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; const State& state( option->state ); const bool horizontal( state & State_Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // colors const QPalette& palette( option->palette ); const QColor background( palette.color( QPalette::Window ) ); // adjust rect, based on number of buttons to be drawn const QRect rect( scrollBarInternalSubControlRect( sliderOption, SC_ScrollBarAddLine ) ); QColor color; QStyleOptionSlider copy( *sliderOption ); if( _addLineButtons == DoubleButton ) { if( horizontal ) { //Draw the arrows const QSize halfSize( rect.width()/2, rect.height() ); const QRect leftSubButton( rect.topLeft(), halfSize ); const QRect rightSubButton( leftSubButton.topRight() + QPoint( 1, 0 ), halfSize ); copy.rect = leftSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarAddLine:SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, leftSubButton, color, background, ArrowLeft ); copy.rect = rightSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarSubLine:SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, rightSubButton, color, background, ArrowRight ); } else { const QSize halfSize( rect.width(), rect.height()/2 ); const QRect topSubButton( rect.topLeft(), halfSize ); const QRect botSubButton( topSubButton.bottomLeft() + QPoint( 0, 1 ), halfSize ); copy.rect = topSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, topSubButton, color, background, ArrowUp ); copy.rect = botSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, botSubButton, color, background, ArrowDown ); } } else if( _addLineButtons == SingleButton ) { copy.rect = rect; color = scrollBarArrowColor( ©, SC_ScrollBarAddLine, widget ); if( horizontal ) renderScrollBarArrow( painter, rect, color, background, reverseLayout ? ArrowLeft : ArrowRight ); else renderScrollBarArrow( painter, rect, color, background, ArrowDown ); } return true; } //___________________________________________________________________________________ bool Style::drawScrollBarSubLineControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // do nothing if no buttons are set if( _subLineButtons == NoButton ) return true; // cast option and check const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; const State& state( option->state ); const bool horizontal( state & State_Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // colors const QPalette& palette( option->palette ); const QColor background( palette.color( QPalette::Window ) ); // adjust rect, based on number of buttons to be drawn QRect rect( scrollBarInternalSubControlRect( sliderOption, SC_ScrollBarSubLine ) ); QColor color; QStyleOptionSlider copy( *sliderOption ); if( _subLineButtons == DoubleButton ) { if( horizontal ) { //Draw the arrows const QSize halfSize( rect.width()/2, rect.height() ); const QRect leftSubButton( rect.topLeft(), halfSize ); const QRect rightSubButton( leftSubButton.topRight() + QPoint( 1, 0 ), halfSize ); copy.rect = leftSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarAddLine:SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, leftSubButton, color, background, ArrowLeft ); copy.rect = rightSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarSubLine:SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, rightSubButton, color, background, ArrowRight ); } else { const QSize halfSize( rect.width(), rect.height()/2 ); const QRect topSubButton( rect.topLeft(), halfSize ); const QRect botSubButton( topSubButton.bottomLeft() + QPoint( 0, 1 ), halfSize ); copy.rect = topSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, topSubButton, color, background, ArrowUp ); copy.rect = botSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, botSubButton, color, background, ArrowDown ); } } else if( _subLineButtons == SingleButton ) { copy.rect = rect; color = scrollBarArrowColor( ©, SC_ScrollBarSubLine, widget ); if( horizontal ) renderScrollBarArrow( painter, rect, color, background, reverseLayout ? ArrowRight : ArrowLeft ); else renderScrollBarArrow( painter, rect, color, background, ArrowUp ); } return true; } //___________________________________________________________________________________ bool Style::drawShapedFrameControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check - #if OXYGEN_USE_KDE4 - const auto frameOption = qstyleoption_cast( option ); - #else const auto frameOption = qstyleoption_cast( option ); - #endif if( !frameOption ) return false; switch( frameOption->frameShape ) { case QFrame::Box: { if( option->state & State_Sunken ) return true; else break; } case QFrame::HLine: { const QColor color( _helper->backgroundColor( option->palette.color( QPalette::Window ), widget, option->rect.center() ) ); _helper->drawSeparator( painter, option->rect, color, Qt::Horizontal ); return true; } case QFrame::VLine: { const QColor color( _helper->backgroundColor( option->palette.color( QPalette::Window ), widget, option->rect.center() ) ); _helper->drawSeparator( painter, option->rect, color, Qt::Vertical ); return true; } case QFrame::StyledPanel: { if( isQtQuickControl( option, widget ) ) { // ComboBox popup frame drawFrameMenuPrimitive( option, painter, widget ); return true; } else break; } default: break; } return false; } //___________________________________________________________________________________ bool Style::drawRubberBandControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const QPalette& palette( option->palette ); const QRect rect( option->rect ); QColor color = palette.color( QPalette::Highlight ); painter->setPen( KColorUtils::mix( color, palette.color( QPalette::Active, QPalette::WindowText ) ) ); color.setAlpha( 50 ); painter->setBrush( color ); painter->setClipRegion( rect ); painter->drawRect( rect.adjusted( 0, 0, -1, -1 ) ); return true; } //___________________________________________________________________________________ bool Style::drawHeaderSectionControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionHeader* headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const bool horizontal( headerOption->orientation == Qt::Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const bool isFirst( horizontal && ( headerOption->position == QStyleOptionHeader::Beginning ) ); const bool isCorner( widget && widget->inherits( "QTableCornerButton" ) ); // corner header lines if( isCorner ) { if( widget ) _helper->renderWindowBackground( painter, rect, widget, palette ); else painter->fillRect( rect, palette.color( QPalette::Window ) ); if( reverseLayout ) renderHeaderLines( rect, palette, painter, TileSet::BottomLeft ); else renderHeaderLines( rect, palette, painter, TileSet::BottomRight ); } else renderHeaderBackground( rect, palette, painter, widget, horizontal, reverseLayout ); // dots const QColor color( palette.color( QPalette::Window ) ); if( horizontal ) { if( headerOption->section != 0 || isFirst ) { const int center( rect.center().y() ); const int pos( reverseLayout ? rect.left()+1 : rect.right()-1 ); _helper->renderDot( painter, QPoint( pos, center-3 ), color ); _helper->renderDot( painter, QPoint( pos, center ), color ); _helper->renderDot( painter, QPoint( pos, center+3 ), color ); } } else { const int center( rect.center().x() ); const int pos( rect.bottom()-1 ); _helper->renderDot( painter, QPoint( center-3, pos ), color ); _helper->renderDot( painter, QPoint( center, pos ), color ); _helper->renderDot( painter, QPoint( center+3, pos ), color ); } return true; } //___________________________________________________________________________________ bool Style::drawHeaderEmptyAreaControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // use the same background as in drawHeaderPrimitive QPalette palette( option->palette ); if( widget && _animations->widgetEnableStateEngine().isAnimated( widget, AnimationEnable ) ) { palette = _helper->disabledPalette( palette, _animations->widgetEnableStateEngine().opacity( widget, AnimationEnable ) ); } const bool horizontal( option->state & QStyle::State_Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); renderHeaderBackground( option->rect, palette, painter, widget, horizontal, reverseLayout ); return true; } //___________________________________________________________________________________ bool Style::drawTabBarTabLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // call parent style method - ParentStyleClass::drawControl( CE_TabBarTabLabel, option, painter, widget ); + KStyle::drawControl( CE_TabBarTabLabel, option, painter, widget ); // store rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // check focus const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( state & State_Selected ); const bool hasFocus( enabled && selected && (state & State_HasFocus) ); // update mouse over animation state _animations->tabBarEngine().updateState( widget, rect.topLeft(), AnimationFocus, hasFocus ); const bool animated( enabled && selected && _animations->tabBarEngine().isAnimated( widget, rect.topLeft(), AnimationFocus ) ); const qreal opacity( _animations->tabBarEngine().opacity( widget, rect.topLeft(), AnimationFocus ) ); if( !( hasFocus || animated ) ) return true; // code is copied from QCommonStyle, but adds focus // cast option and check const QStyleOptionTab *tabOption( qstyleoption_cast(option) ); if( !tabOption || tabOption->text.isEmpty() ) return true; // tab option rect const bool verticalTabs( isVerticalTab( tabOption ) ); const int textFlags( Qt::AlignCenter | _mnemonics->textFlags() ); // text rect QRect textRect( subElementRect(SE_TabBarTabText, option, widget) ); if( verticalTabs ) { // properly rotate painter painter->save(); int newX, newY, newRot; if( tabOption->shape == QTabBar::RoundedEast || tabOption->shape == QTabBar::TriangularEast) { newX = rect.width() + rect.x(); newY = rect.y(); newRot = 90; } else { newX = rect.x(); newY = rect.y() + rect.height(); newRot = -90; } QTransform transform; transform.translate( newX, newY ); transform.rotate(newRot); painter->setTransform( transform, true ); } // adjust text rect based on font metrics textRect = option->fontMetrics.boundingRect( textRect, textFlags, tabOption->text ); // focus color QColor focusColor; if( animated ) focusColor = _helper->alphaColor( _helper->focusColor( palette ), opacity ); else if( hasFocus ) focusColor = _helper->focusColor( palette ); // render focus line if( focusColor.isValid() ) { painter->save(); painter->setRenderHint( QPainter::Antialiasing, false ); painter->setBrush( Qt::NoBrush ); painter->setPen( focusColor ); painter->translate( 0, 2 ); painter->drawLine( textRect.bottomLeft(), textRect.bottomRight() ); painter->restore(); } if( verticalTabs ) painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawTabBarTabShapeControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // check if tabwidget is selected and redirect const State& state( option->state ); const bool selected( state & State_Selected ); if( selected ) return drawTabBarTabShapeControl_selected( option, painter, widget ); else return drawTabBarTabShapeControl_unselected( option, painter, widget ); } //___________________________________________________________________________________ bool Style::drawTabBarTabShapeControl_selected( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionTab* tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // tab position and state const QStyleOptionTab::TabPosition& position = tabOption->position; bool isFirst( position == QStyleOptionTab::OnlyOneTab || position == QStyleOptionTab::Beginning ); bool isLast( position == QStyleOptionTab::OnlyOneTab || position == QStyleOptionTab::End ); // document mode - #if OXYGEN_USE_KDE4 - const auto tabOptionV3 = qstyleoption_cast( option ); - #else const auto tabOptionV3 = qstyleoption_cast( option ); - #endif bool documentMode = tabOptionV3 ? tabOptionV3->documentMode : false; const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : nullptr; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); // this is needed to complete the base frame when there are widgets in tabbar const QTabBar* tabBar( qobject_cast( widget ) ); const QRect tabBarRect( tabBar ? tabBar->rect():QRect() ); // check if tab is being dragged const bool isDragged( painter->device() != tabBar ); // hover and animation state /* all are disabled when tabBar is locked ( drag in progress ) */ const bool tabBarLocked( _tabBarData->locks( tabBar ) ); const bool mouseOver( enabled && !tabBarLocked && ( state & State_MouseOver ) ); // animation state _animations->tabBarEngine().updateState( widget, rect.topLeft(), AnimationHover, mouseOver ); // handle base frame painting, for tabbars in which tab is being dragged _tabBarData->drawTabBarBaseControl( tabOption, painter, widget ); if( tabBar && isDragged ) _tabBarData->lock( tabBar ); else if( _tabBarData->locks( tabBar ) ) _tabBarData->release(); // corner widgets const bool verticalTabs( isVerticalTab( tabOption ) ); const bool hasLeftCornerWidget( (tabOption->cornerWidgets & QStyleOptionTab::LeftCornerWidget) && !verticalTabs ); // true if widget is aligned to the frame const bool isFrameAligned( !documentMode && isFirst && !hasLeftCornerWidget && !isDragged ); // swap state based on reverse layout, so that they become layout independent if( reverseLayout && !verticalTabs ) qSwap( isFirst, isLast ); // part of the tab in which the text is drawn QRect tabRect( insideMargin( rect, -1 ) ); SlabRect tabSlab( insideMargin( rect, -1 ), TileSet::Ring ); // connection to the frame SlabRect::List slabs; switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { tabSlab.tiles &= ~TileSet::Bottom; tabSlab.rect.adjust( 0, 0, 0, 2 ); if( isDragged ) break; // left side if( isFrameAligned && !reverseLayout ) { QRect frameRect( rect ); frameRect.setLeft( frameRect.left() - 1 ); frameRect.setRight( tabRect.left() ); frameRect.setTop( tabRect.bottom() - 4 ); slabs << SlabRect( frameRect, TileSet::Left ).adjusted( TileSet::DefaultSize ); } else { QRect frameRect( rect ); frameRect.setRight( tabRect.left() + 3 ); frameRect.setTop( rect.bottom() - TileSet::DefaultSize + 1 ); slabs << SlabRect( frameRect, TileSet::Top ).adjusted( TileSet::DefaultSize ); } // right side if( isFrameAligned && reverseLayout ) { QRect frameRect( rect ); frameRect.setLeft( tabRect.right() ); frameRect.setRight( frameRect.right() + 1 ); frameRect.setTop( tabRect.bottom() - 4 ); slabs << SlabRect( frameRect, TileSet::Right ).adjusted( TileSet::DefaultSize ); } else { QRect frameRect( rect ); frameRect.setLeft( tabRect.right() - 3 ); frameRect.setTop( rect.bottom() - TileSet::DefaultSize + 1 ); slabs << SlabRect( frameRect, TileSet::Top ).adjusted( TileSet::DefaultSize ); } // extra base, to extend below inactive tabs and buttons if( tabBar ) { QRect frameRect( rect ); frameRect.setTop( rect.bottom() - Metrics::TabBar_BaseOverlap + 1 ); if( rect.left() > tabBarRect.left() ) { frameRect.setLeft( tabBarRect.left() - Metrics::TabBar_BaseOverlap ); frameRect.setRight( rect.left() + Metrics::TabBar_BaseOverlap - 1 ); if( documentMode || reverseLayout ) slabs << SlabRect( frameRect, TileSet::Top ); else slabs << SlabRect( frameRect, TileSet::TopLeft ); } if( rect.right() < tabBarRect.right() ) { frameRect.setLeft( rect.right() - Metrics::TabBar_BaseOverlap + 1 ); frameRect.setRight( tabBarRect.right() + Metrics::TabBar_BaseOverlap ); if( documentMode || !reverseLayout ) slabs << SlabRect( frameRect, TileSet::Top ); else slabs << SlabRect( frameRect, TileSet::TopRight ); } } break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { tabSlab.tiles &= ~TileSet::Top; tabSlab.rect.adjust( 0, -2, 0, 0 ); if( isDragged ) break; // left side if( isFrameAligned && !reverseLayout ) { QRect frameRect( rect ); frameRect.setLeft( frameRect.left() - 1 ); frameRect.setRight( tabRect.left() ); frameRect.setBottom( tabRect.top() + 4 ); slabs << SlabRect( frameRect, TileSet::Left ).adjusted( TileSet::DefaultSize ); } else { QRect frameRect( rect ); frameRect.setRight( tabRect.left() + 3 ); frameRect.setBottom( rect.top() + TileSet::DefaultSize - 1 ); slabs << SlabRect( frameRect, TileSet::Bottom ).adjusted( TileSet::DefaultSize ); } // right side if( isFrameAligned && reverseLayout ) { QRect frameRect( rect ); frameRect.setLeft( tabRect.right() ); frameRect.setRight( frameRect.right() + 1 ); frameRect.setBottom( tabRect.top() + 4 ); slabs << SlabRect( frameRect, TileSet::Right ).adjusted( TileSet::DefaultSize ); } else { QRect frameRect( rect ); frameRect.setLeft( tabRect.right() - 3 ); frameRect.setBottom( rect.top() + TileSet::DefaultSize - 1 ); slabs << SlabRect( frameRect, TileSet::Bottom ).adjusted( TileSet::DefaultSize ); } // extra base, to extend below tabbar buttons if( tabBar ) { QRect frameRect( rect ); frameRect.setBottom( rect.top() + Metrics::TabBar_BaseOverlap - 1 ); if( rect.left() > tabBarRect.left() ) { frameRect.setLeft( tabBarRect.left() - Metrics::TabBar_BaseOverlap ); frameRect.setRight( rect.left() + Metrics::TabBar_BaseOverlap - 1 ); if( documentMode || reverseLayout ) slabs << SlabRect( frameRect, TileSet::Bottom ); else slabs << SlabRect( frameRect, TileSet::BottomLeft ); } if( rect.right() < tabBarRect.right() ) { frameRect.setLeft( rect.right() - Metrics::TabBar_BaseOverlap + 1 ); frameRect.setRight( tabBarRect.right() + Metrics::TabBar_BaseOverlap ); if( documentMode || !reverseLayout ) slabs << SlabRect( frameRect, TileSet::Bottom ); else slabs << SlabRect( frameRect, TileSet::BottomRight ); } } break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { tabSlab.tiles &= ~TileSet::Right; tabSlab.rect.adjust( 0, 0, 2, 0 ); if( isDragged ) break; // top side if( isFrameAligned ) { QRect frameRect( rect ); frameRect.setLeft( tabRect.right() - 4 ); frameRect.setTop( frameRect.top() - 1 ); frameRect.setBottom( tabRect.top() ); slabs << SlabRect( frameRect, TileSet::Top ).adjusted( TileSet::DefaultSize ); } else { QRect frameRect( rect ); frameRect.setLeft( rect.right() - TileSet::DefaultSize + 1 ); frameRect.setBottom( tabRect.top() + 3 ); slabs << SlabRect( frameRect, TileSet::Left ).adjusted( TileSet::DefaultSize ); } // bottom side QRect frameRect( rect ); frameRect.setLeft( rect.right() - TileSet::DefaultSize + 1 ); frameRect.setTop( tabRect.bottom() - 3 ); slabs << SlabRect( frameRect, TileSet::Left ).adjusted( TileSet::DefaultSize ); // extra base, to extend below tabbar buttons if( tabBar ) { QRect frameRect( rect ); frameRect.setLeft( rect.right() - Metrics::TabBar_BaseOverlap + 1 ); if( rect.top() > tabBarRect.top() ) { frameRect.setTop( tabBarRect.top() - Metrics::TabBar_BaseOverlap ); frameRect.setBottom( rect.top() + Metrics::TabBar_BaseOverlap - 1 ); if( documentMode ) slabs << SlabRect( frameRect, TileSet::Left ); else slabs << SlabRect( frameRect, TileSet::TopLeft ); } if( rect.bottom() < tabBarRect.bottom() ) { frameRect.setTop( rect.bottom() - Metrics::TabBar_BaseOverlap + 1 ); frameRect.setBottom( tabBarRect.bottom() + Metrics::TabBar_BaseOverlap - 1 ); slabs << SlabRect( frameRect, TileSet::Left ); } } break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { tabSlab.tiles &= ~TileSet::Left; tabSlab.rect.adjust( -2, 0, 0, 0 ); if( isDragged ) break; // top side if( isFrameAligned ) { QRect frameRect( rect ); frameRect.setRight( tabRect.left() + 4 ); frameRect.setTop( frameRect.top() - 1 ); frameRect.setBottom( tabRect.top() ); slabs << SlabRect( frameRect, TileSet::Top ).adjusted( TileSet::DefaultSize ); } else { QRect frameRect( rect ); frameRect.setRight( rect.left() + TileSet::DefaultSize - 1 ); frameRect.setBottom( tabRect.top() + 3 ); slabs << SlabRect( frameRect, TileSet::Right ).adjusted( TileSet::DefaultSize ); } // bottom side QRect frameRect( rect ); frameRect.setRight( rect.left() + TileSet::DefaultSize - 1 ); frameRect.setTop( tabRect.bottom() - 3 ); slabs << SlabRect( frameRect, TileSet::Right ).adjusted( TileSet::DefaultSize ); // extra base, to extend below tabbar buttons if( tabBar ) { QRect frameRect( rect ); frameRect.setRight( rect.left() + Metrics::TabBar_BaseOverlap - 1 ); if( rect.top() > tabBarRect.top() ) { frameRect.setTop( tabBarRect.top() - Metrics::TabBar_BaseOverlap ); frameRect.setBottom( rect.top() + Metrics::TabBar_BaseOverlap - 1 ); if( documentMode ) slabs << SlabRect( frameRect, TileSet::Right ); else slabs << SlabRect( frameRect, TileSet::TopRight ); } if( rect.bottom() < tabBarRect.bottom() ) { frameRect.setTop( rect.bottom() - Metrics::TabBar_BaseOverlap + 1 ); frameRect.setBottom( tabBarRect.bottom() + Metrics::TabBar_BaseOverlap - 1 ); slabs << SlabRect( frameRect, TileSet::Right ); } } break; } default: break; } // store default color const QColor color( palette.color( QPalette::Window ) ); // render connections to frame // extra care must be taken care of so that no slab // extends beyond tabWidget frame, if any const QRect tabWidgetRect( tabWidget ? tabWidget->rect().translated( -widget->geometry().topLeft() ) : QRect() ); foreach( SlabRect slab, slabs ) // krazy:exclude=foreach { adjustSlabRect( slab, tabWidgetRect, documentMode, verticalTabs ); renderSlab( painter, slab, color, NoFill ); } // adjust clip rect and render tab if( tabBar ) { painter->save(); painter->setClipRegion( tabBarClipRegion( tabBar ) ); } // fill tab if( isDragged ) fillTabBackground( painter, tabRect, color, widget ); // slab options renderSlab( painter, tabSlab, color, NoFill ); fillTab( painter, tabRect, color, tabOption->shape ); // restore clip region if( tabBar ) painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawTabBarTabShapeControl_unselected( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionTab* tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // tab position and flags const QStyleOptionTab::TabPosition& position = tabOption->position; bool isFirst( position == QStyleOptionTab::OnlyOneTab || position == QStyleOptionTab::Beginning ); bool isLast( position == QStyleOptionTab::OnlyOneTab || position == QStyleOptionTab::End ); bool isLeftOfSelected( tabOption->selectedPosition == QStyleOptionTab::NextIsSelected ); bool isRightOfSelected( tabOption->selectedPosition == QStyleOptionTab::PreviousIsSelected ); // document mode - #if OXYGEN_USE_KDE4 - const auto tabOptV3 = qstyleoption_cast( option ); - #else const auto tabOptV3 = qstyleoption_cast( option ); - #endif bool documentMode = tabOptV3 ? tabOptV3->documentMode : false; const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : nullptr; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); // this is needed to complete the base frame when there are widgets in tabbar const QTabBar* tabBar( qobject_cast( widget ) ); const QRect tabBarRect( tabBar ? tabBar->rect():QRect() ); // hover and animation flags /* all are disabled when tabBar is locked ( drag in progress ) */ const bool tabBarLocked( _tabBarData->locks( tabBar ) ); const bool mouseOver( enabled && !tabBarLocked && ( state & State_MouseOver ) ); // animation state _animations->tabBarEngine().updateState( widget, rect.topLeft(), AnimationHover, mouseOver ); const bool animated( enabled && !tabBarLocked && _animations->tabBarEngine().isAnimated( widget, rect.topLeft(), AnimationHover ) ); // corner widgets const bool verticalTabs( isVerticalTab( tabOption ) ); const bool hasLeftCornerWidget( ( tabOption->cornerWidgets & QStyleOptionTab::LeftCornerWidget ) && !verticalTabs ); // true if widget is aligned to the frame /* need to check for 'isRightOfSelected' because for some reason the isFirst flag is set when active tab is being moved */ const bool isFrameAligned( !documentMode && isFirst && !hasLeftCornerWidget && !isRightOfSelected ); isFirst &= !isRightOfSelected; isLast &= !isLeftOfSelected; // swap flags based on reverse layout, so that they become layout independent if( reverseLayout && !verticalTabs ) { qSwap( isFirst, isLast ); qSwap( isLeftOfSelected, isRightOfSelected ); } const qreal radius = 4; // part of the tab in which the text is drawn QRect tabRect( rect ); QPainterPath path; // highlighted slab (if any) SlabRect highlightSlab; switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { tabRect.adjust( 0, 3, 1, -4 ); // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.adjust( 0, 0, 2, 0 ); else if( isRightOfSelected ) tabRect.adjust( -2, 0, 0, 0 ); if( isFirst ) { tabRect.adjust( 1, 0, 0, 0 ); if( isFrameAligned ) path.moveTo( tabRect.bottomLeft() + QPoint( 0, 2 ) ); else path.moveTo( tabRect.bottomLeft() ); path.lineTo( tabRect.topLeft() + QPointF( 0, radius ) ); path.quadTo( tabRect.topLeft(), tabRect.topLeft() + QPoint( radius, 0 ) ); path.lineTo( tabRect.topRight() ); path.lineTo( tabRect.bottomRight() ); } else if( isLast ) { tabRect.adjust( 0, 0, -2, 0 ); path.moveTo( tabRect.bottomLeft() ); path.lineTo( tabRect.topLeft() ); path.lineTo( tabRect.topRight() - QPointF( radius, 0 ) ); path.quadTo( tabRect.topRight(), tabRect.topRight() + QPointF( 0, radius ) ); if( isFrameAligned ) path.lineTo( tabRect.bottomRight() + QPointF( 0, 2 ) ); else path.lineTo( tabRect.bottomRight() ); } else { path.moveTo( tabRect.bottomLeft() ); path.lineTo( tabRect.topLeft() ); path.lineTo( tabRect.topRight() ); path.lineTo( tabRect.bottomRight() ); } // highlight QRect highlightRect( tabRect.left(), tabRect.bottom() - Metrics::TabBar_BaseOverlap + Metrics::TabBar_TabOffset, tabRect.width(), 1 ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( -2, 0, 0, 0 ), TileSet::TopLeft ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( 0, 0, 2, 0 ), TileSet::TopRight ); else highlightSlab = SlabRect( highlightRect, TileSet::Top ); break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { tabRect.adjust( 0, 4, 1, -3 ); // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.adjust( 0, 0, 2, 0 ); else if( isRightOfSelected ) tabRect.adjust( -2, 0, 0, 0 ); if( isFirst ) { tabRect.adjust( 1, 0, 0, 0 ); if( isFrameAligned ) path.moveTo( tabRect.topLeft() - QPoint( 0, 2 ) ); else path.moveTo( tabRect.topLeft() ); path.lineTo( tabRect.bottomLeft() - QPointF( 0, radius ) ); path.quadTo( tabRect.bottomLeft(), tabRect.bottomLeft() + QPoint( radius, 0 ) ); path.lineTo( tabRect.bottomRight() ); path.lineTo( tabRect.topRight() ); } else if( isLast ) { tabRect.adjust( 0, 0, -2, 0 ); path.moveTo( tabRect.topLeft() ); path.lineTo( tabRect.bottomLeft() ); path.lineTo( tabRect.bottomRight() - QPointF( radius, 0 ) ); path.quadTo( tabRect.bottomRight(), tabRect.bottomRight() - QPointF( 0, radius ) ); if( isFrameAligned ) path.lineTo( tabRect.topRight() - QPointF( 0, 2 ) ); else path.lineTo( tabRect.topRight() ); } else { path.moveTo( tabRect.topLeft() ); path.lineTo( tabRect.bottomLeft() ); path.lineTo( tabRect.bottomRight() ); path.lineTo( tabRect.topRight() ); } // highlight QRect highlightRect( tabRect.left(), tabRect.top() - Metrics::TabBar_BaseOverlap + Metrics::TabBar_TabOffset, tabRect.width(), TileSet::DefaultSize ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( -2, 0, 0, 0 ), TileSet::BottomLeft ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( 0, 0, 2, 0 ), TileSet::BottomRight ); else highlightSlab = SlabRect( highlightRect, TileSet::Bottom ); break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { tabRect.adjust( 3, 0, -4, 1 ); // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.adjust( 0, 0, 0, 2 ); else if( isRightOfSelected ) tabRect.adjust( 0, -2, 0, 0 ); if( isFirst ) { tabRect.adjust( 0, 1, 0, 0 ); if( isFrameAligned ) path.moveTo( tabRect.topRight() + QPoint( 2, 0 ) ); else path.moveTo( tabRect.topRight() ); path.lineTo( tabRect.topLeft() + QPointF( radius, 0 ) ); path.quadTo( tabRect.topLeft(), tabRect.topLeft() + QPoint( 0, radius ) ); path.lineTo( tabRect.bottomLeft() ); path.lineTo( tabRect.bottomRight() ); } else if( isLast ) { tabRect.adjust( 0, 0, 0, -1 ); path.moveTo( tabRect.topRight() ); path.lineTo( tabRect.topLeft() ); path.lineTo( tabRect.bottomLeft() - QPointF( 0, radius ) ); path.quadTo( tabRect.bottomLeft(), tabRect.bottomLeft() + QPointF( radius, 0 ) ); path.lineTo( tabRect.bottomRight() ); } else { path.moveTo( tabRect.topRight() ); path.lineTo( tabRect.topLeft() ); path.lineTo( tabRect.bottomLeft() ); path.lineTo( tabRect.bottomRight() ); } // highlight QRect highlightRect( tabRect.right() - Metrics::TabBar_BaseOverlap + Metrics::TabBar_TabOffset, tabRect.top(), 1, tabRect.height() ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( 0, -2, 0, 0 ), TileSet::TopLeft ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( 0, 0, 0, 2 ), TileSet::BottomLeft ); else highlightSlab = SlabRect( highlightRect, TileSet::Left ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { tabRect.adjust( 4, 0, -3, 1 ); // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.adjust( 0, 0, 0, 2 ); else if( isRightOfSelected ) tabRect.adjust( 0, -2, 0, 0 ); if( isFirst ) { tabRect.adjust( 0, 1, 0, 0 ); if( isFrameAligned ) path.moveTo( tabRect.topLeft() - QPoint( 2, 0 ) ); else path.moveTo( tabRect.topLeft() ); path.lineTo( tabRect.topRight() - QPointF( radius, 0 ) ); path.quadTo( tabRect.topRight(), tabRect.topRight() + QPoint( 0, radius ) ); path.lineTo( tabRect.bottomRight() ); path.lineTo( tabRect.bottomLeft() ); } else if( isLast ) { tabRect.adjust( 0, 0, 0, -1 ); path.moveTo( tabRect.topLeft() ); path.lineTo( tabRect.topRight() ); path.lineTo( tabRect.bottomRight() - QPointF( 0, radius ) ); path.quadTo( tabRect.bottomRight(), tabRect.bottomRight() - QPointF( radius, 0 ) ); path.lineTo( tabRect.bottomLeft() ); } else { path.moveTo( tabRect.topLeft() ); path.lineTo( tabRect.topRight() ); path.lineTo( tabRect.bottomRight() ); path.lineTo( tabRect.bottomLeft() ); } // highlight QRect highlightRect( tabRect.left() - Metrics::TabBar_BaseOverlap + Metrics::TabBar_TabOffset, tabRect.top(), TileSet::DefaultSize, tabRect.height() ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( 0, -2, 0, 0 ), TileSet::TopRight ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( 0, 0, 0, 2 ), TileSet::BottomRight ); else highlightSlab = SlabRect( highlightRect, TileSet::Right ); break; } default: break; } const QColor color( palette.color( QPalette::Window ) ); // adjust clip rect and render tab if( tabBar ) { painter->save(); painter->setClipRegion( tabBarClipRegion( tabBar ) ); } // fill tab const QColor backgroundColor = _helper->backgroundColor( color, widget, rect.center() ); const QColor midColor = _helper->alphaColor( _helper->calcDarkColor( backgroundColor ), 0.4 ); const QColor darkColor = _helper->alphaColor( _helper->calcDarkColor( backgroundColor ), 0.6 ); painter->save(); painter->translate( 0.5, 0.5 ); painter->setRenderHints( QPainter::Antialiasing ); painter->setPen( darkColor ); painter->setBrush( midColor ); painter->drawPath( path ); painter->restore(); // restore clip region if( tabBar ) painter->restore(); // handle base frame painting, for tabbars in which tab is being dragged _tabBarData->drawTabBarBaseControl( tabOption, painter, widget ); // hovered highlight if( ( animated || mouseOver ) && highlightSlab.isValid() ) { highlightSlab.adjust( TileSet::DefaultSize ); const QRect tabWidgetRect( tabWidget ? tabWidget->rect().translated( -widget->geometry().topLeft() ) : QRect() ); adjustSlabRect( highlightSlab, tabWidgetRect, documentMode, verticalTabs ); const qreal opacity( _animations->tabBarEngine().opacity( widget, rect.topLeft(), AnimationHover ) ); const StyleOptions hoverTabOpts( NoFill | Hover ); // pass an invalid color to have only the glow painted if( animated ) renderSlab( painter, highlightSlab, QColor(), hoverTabOpts, opacity, AnimationHover ); else renderSlab( painter, highlightSlab, QColor(), hoverTabOpts ); } return true; } //___________________________________________________________________________________ bool Style::drawToolBoxTabLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionToolBox* toolBoxOption( qstyleoption_cast( option ) ); if( !toolBoxOption ) return true; // copy palette const QPalette& palette( option->palette ); const State& state( option->state ); const bool enabled( state & State_Enabled ); // text alignment const int textFlags( _mnemonics->textFlags() | Qt::AlignCenter ); // contents rect const QRect rect( subElementRect( SE_ToolBoxTabContents, option, widget ) ); // store icon size const int iconSize( pixelMetric( QStyle::PM_SmallIconSize, option, widget ) ); // find contents size and rect QRect contentsRect( rect ); QSize contentsSize; if( !toolBoxOption->text.isEmpty() ) { contentsSize = option->fontMetrics.size( _mnemonics->textFlags(), toolBoxOption->text ); if( !toolBoxOption->icon.isNull() ) contentsSize.rwidth() += Metrics::ToolBox_TabItemSpacing; } // icon size if( !toolBoxOption->icon.isNull() ) { contentsSize.setHeight( qMax( contentsSize.height(), iconSize ) ); contentsSize.rwidth() += iconSize; } // adjust contents rect contentsRect = centerRect( contentsRect, contentsSize ); // render icon if( !toolBoxOption->icon.isNull() ) { // icon rect QRect iconRect; if( toolBoxOption->text.isEmpty() ) iconRect = centerRect( contentsRect, iconSize, iconSize ); else { iconRect = contentsRect; iconRect.setWidth( iconSize ); iconRect = centerRect( iconRect, iconSize, iconSize ); contentsRect.setLeft( iconRect.right() + Metrics::ToolBox_TabItemSpacing + 1 ); } iconRect = visualRect( option, iconRect ); const QIcon::Mode mode( enabled ? QIcon::Normal : QIcon::Disabled ); const QPixmap pixmap( toolBoxOption->icon.pixmap( iconSize, mode ) ); drawItemPixmap( painter, iconRect, textFlags, pixmap ); } // render text if( !toolBoxOption->text.isEmpty() ) { contentsRect = visualRect( option, contentsRect ); drawItemText( painter, contentsRect, textFlags, palette, enabled, toolBoxOption->text, QPalette::WindowText ); } return true; } //___________________________________________________________________________________ bool Style::drawToolBoxTabShapeControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // copy state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( state & State_Selected ); const bool mouseOver( enabled && !selected && ( state & State_MouseOver ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // cast option and check - #if OXYGEN_USE_KDE4 - const auto v2 = qstyleoption_cast( option ); - if( v2 && v2->position == QStyleOptionToolBoxV2::Beginning && selected ) return true; - #else const auto v2 = qstyleoption_cast( option ); if( v2 && v2->position == QStyleOptionToolBox::Beginning && selected ) return true; - #endif /* the proper widget ( the toolbox tab ) is not passed as argument by Qt. What is passed is the toolbox directly. To implement animations properly, the painter->device() is used instead */ bool animated( false ); qreal opacity( AnimationData::OpacityInvalid ); if( enabled ) { // try retrieve button from painter device. if( QPaintDevice* device = painter->device() ) { _animations->toolBoxEngine().updateState( device, mouseOver ); animated = _animations->toolBoxEngine().isAnimated( device ); opacity = _animations->toolBoxEngine().opacity( device ); } } // save colors for shadow /* important: option returns a wrong color. We use the widget's palette when widget is set */ const QColor color( widget ? widget->palette().color( widget->backgroundRole() ) : palette.color( QPalette::Window ) ); const QColor dark( _helper->calcDarkColor( color ) ); QList colors; colors.append( _helper->calcLightColor( color ) ); if( mouseOver || animated ) { QColor highlight = _helper->hoverColor( palette ); if( animated ) { colors.append( KColorUtils::mix( dark, highlight, opacity ) ); colors.append( _helper->alphaColor( highlight, 0.2*opacity ) ); } else { colors.append( highlight ); colors.append( _helper->alphaColor( highlight, 0.2 ) ); } } else colors.append( dark ); // create path const qreal radius( 8 ); const qreal offset( radius * std::tan( M_PI/8 ) ); const QRectF rectf( rect ); QPainterPath path; if( reverseLayout ) { path.moveTo( rectf.right()-1, rectf.top() ); path.lineTo( rectf.left() + 50 + radius + offset, rectf.top() ); path.arcTo( QRectF( rectf.left() + 50 + radius + offset - 2*radius, rectf.top(), radius*2, radius*2 ), 90, 45 ); path.lineTo( rectf.left() + 50 - rectf.height() + 3 + offset/std::sqrt(2), rectf.bottom() - 3 - offset/std::sqrt(2) ); path.arcTo( QRectF( rectf.left() + 50 - rectf.height() + 3 + radius - offset - 2*radius, rectf.bottom() - 3 - 2*radius, 2*radius, 2*radius ), 315, -45 ); path.lineTo( rectf.left(), rectf.bottom() - 3 ); } else { path.moveTo( rectf.left(), rectf.top() ); path.lineTo( rectf.right()- 50 - radius - offset, rectf.top() ); path.arcTo( QRectF( rectf.right() - 50 - radius - offset, rectf.top(), radius*2, radius*2 ), 90, -45 ); path.lineTo( rectf.right() - 50 + rectf.height() - 3 - offset/std::sqrt(2), rectf.bottom() - 3 - offset/std::sqrt(2) ); path.arcTo( QRectF( rectf.right() - 50 + rectf.height() - 3 - radius + offset, rectf.bottom() - 3 - 2*radius, 2*radius, 2*radius ), 225, 45 ); path.lineTo( rectf.right() - 1, rectf.bottom() - 3 ); } // paint painter->setRenderHint( QPainter::Antialiasing, true ); painter->translate(0.5, 0.5 ); painter->translate( 0, 2 ); foreach( const QColor& color, colors ) { painter->setPen( color ); painter->drawPath( path ); painter->translate( 0,-1 ); } return true; } //___________________________________________________________________________________ bool Style::drawDockWidgetTitleControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionDockWidget* dockWidgetOption = qstyleoption_cast( option ); if( !dockWidgetOption ) return true; // copy palette const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // cast to v2 to check vertical bar - #if OXYGEN_USE_KDE4 - const auto v2 = qstyleoption_cast( option ); - #else const auto v2 = qstyleoption_cast( option ); - #endif - const bool verticalTitleBar( v2 ? v2->verticalTitleBar : false ); const QRect buttonRect( subElementRect( dockWidgetOption->floatable ? SE_DockWidgetFloatButton : SE_DockWidgetCloseButton, option, widget ) ); // get rectangle and adjust to properly accounts for buttons QRect rect( insideMargin( dockWidgetOption->rect, Metrics::Frame_FrameWidth ) ); if( verticalTitleBar ) { if( buttonRect.isValid() ) rect.setTop( buttonRect.bottom()+1 ); } else if( reverseLayout ) { if( buttonRect.isValid() ) rect.setLeft( buttonRect.right()+1 ); rect.adjust( 0, 0, -4, 0 ); } else { if( buttonRect.isValid() ) rect.setRight( buttonRect.left()-1 ); rect.adjust( 4, 0, 0, 0 ); } QString title( dockWidgetOption->title ); int titleWidth = dockWidgetOption->fontMetrics.size( _mnemonics->textFlags(), title ).width(); int width = verticalTitleBar ? rect.height() : rect.width(); if( width < titleWidth ) title = dockWidgetOption->fontMetrics.elidedText( title, Qt::ElideRight, width, Qt::TextShowMnemonic ); if( verticalTitleBar ) { QSize s = rect.size(); s.transpose(); rect.setSize( s ); painter->save(); painter->translate( rect.left(), rect.top() + rect.width() ); painter->rotate( -90 ); painter->translate( - rect.left(), - rect.top() ); drawItemText( painter, rect, Qt::AlignLeft | Qt::AlignVCenter | _mnemonics->textFlags(), palette, enabled, title, QPalette::WindowText ); painter->restore(); } else { drawItemText( painter, rect, Qt::AlignLeft | Qt::AlignVCenter | _mnemonics->textFlags(), palette, enabled, title, QPalette::WindowText ); } return true; } //___________________________________________________________________________________ bool Style::drawToolBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // when timeLine is running draw border event if not hovered const bool toolBarAnimated( _animations->toolBarEngine().isFollowMouseAnimated( widget ) ); const QRect animatedRect( _animations->toolBarEngine().animatedRect( widget ) ); const bool toolBarIntersected( toolBarAnimated && animatedRect.intersects( rect ) ); if( toolBarIntersected ) { _helper->slitFocused( _helper->focusColor( palette ) ).render( animatedRect, painter ); } // draw nothing otherwise ( toolbars are transparent ) return true; } //______________________________________________________________ bool Style::drawToolButtonComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // check autoRaise state const State& state( option->state ); const bool isInToolBar( widget && qobject_cast( widget->parent() ) ); // get rect and palette const QRect& rect( option->rect ); const QStyleOptionToolButton *toolButtonOption( qstyleoption_cast( option ) ); if( !toolButtonOption ) return true; const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); const bool sunken( state & ( State_Sunken|State_On ) ); const bool autoRaise( state & State_AutoRaise ); if( isInToolBar ) { _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); } else { // mouseOver has precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus&&!mouseOver ); } // toolbar animation QWidget* parent( widget ? widget->parentWidget():0 ); const bool toolBarAnimated( isInToolBar && _animations->toolBarEngine().isAnimated( parent ) ); const QRect animatedRect( _animations->toolBarEngine().animatedRect( parent ) ); const QRect currentRect( _animations->toolBarEngine().currentRect( parent ) ); const bool current( isInToolBar && currentRect.intersects( rect.translated( widget->mapToParent( QPoint( 0,0 ) ) ) ) ); const bool toolBarTimerActive( isInToolBar && _animations->toolBarEngine().isTimerActive( widget->parentWidget() ) ); // normal toolbutton animation const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); // detect buttons in tabbar, for which special rendering is needed const bool inTabBar( widget && qobject_cast( widget->parentWidget() ) ); // local copy of option QStyleOptionToolButton copy( *toolButtonOption ); const bool hasPopupMenu( toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup ); const bool hasInlineIndicator( toolButtonOption->features&QStyleOptionToolButton::HasMenu && toolButtonOption->features&QStyleOptionToolButton::PopupDelay && !hasPopupMenu ); const QRect buttonRect( subControlRect( CC_ToolButton, option, SC_ToolButton, widget ) ); const QRect menuRect( subControlRect( CC_ToolButton, option, SC_ToolButtonMenu, widget ) ); // frame const bool drawFrame( (enabled && !( mouseOver || hasFocus || sunken ) && ((mode != AnimationNone) || ( ( ( toolBarAnimated && animatedRect.isNull() )||toolBarTimerActive ) && current )) ) || (toolButtonOption->subControls & SC_ToolButton) ); if( drawFrame ) { copy.rect = buttonRect; if( inTabBar ) drawTabBarPanelButtonToolPrimitive( ©, painter, widget ); else drawPrimitive( PE_PanelButtonTool, ©, painter, widget); } if( hasPopupMenu ) { copy.rect = menuRect; if( !autoRaise ) { drawPrimitive( PE_IndicatorButtonDropDown, ©, painter, widget ); copy.state &= ~(State_MouseOver|State_HasFocus); } drawPrimitive( PE_IndicatorArrowDown, ©, painter, widget ); } else if( hasInlineIndicator ) { copy.rect = menuRect; copy.state &= ~(State_MouseOver|State_HasFocus); drawPrimitive( PE_IndicatorArrowDown, ©, painter, widget ); } // contents { // restore state copy.state = state; // define contents rect QRect contentsRect( buttonRect ); // detect dock widget title button /* for dockwidget title buttons, do not take out margins, so that icon do not get scaled down */ const bool isDockWidgetTitleButton( widget && widget->inherits( "QDockWidgetTitleButton" ) ); if( isDockWidgetTitleButton ) { // cast to abstract button // adjust state to have correct icon rendered const QAbstractButton* button( qobject_cast( widget ) ); if( button->isChecked() || button->isDown() ) copy.state |= State_On; } else if( !inTabBar && hasInlineIndicator ) { const int marginWidth( autoRaise ? Metrics::ToolButton_MarginWidth : Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth ); contentsRect = insideMargin( contentsRect, marginWidth, 0 ); contentsRect.setRight( contentsRect.right() - Metrics::ToolButton_InlineIndicatorWidth ); contentsRect = visualRect( option, contentsRect ); } copy.rect = contentsRect; // render drawControl( CE_ToolButtonLabel, ©, painter, widget); } return true; } //______________________________________________________________ bool Style::drawComboBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionComboBox* comboBoxOption( qstyleoption_cast( option ) ); if( !comboBoxOption ) return true; // rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); const bool editable( comboBoxOption->editable ); const bool sunken( state & (State_On|State_Sunken) ); bool flat( !comboBoxOption->frame ); // style options StyleOptions styleOptions; if( mouseOver ) styleOptions |= Hover; if( hasFocus ) styleOptions |= Focus; if( sunken && !editable ) styleOptions |= Sunken; // frame if( comboBoxOption->subControls & SC_ComboBoxFrame ) { if( editable ) { // editable combobox. Make it look like a LineEdit // focus takes precedence over hover _animations->inputWidgetEngine().updateState( widget, AnimationFocus, hasFocus ); _animations->inputWidgetEngine().updateState( widget, AnimationHover, mouseOver && !hasFocus ); // input area painter->setRenderHint( QPainter::Antialiasing ); flat |= ( rect.height() <= 2*Metrics::Frame_FrameWidth + Metrics::MenuButton_IndicatorWidth ); if( flat ) { const QColor background( palette.color( QPalette::Base ) ); painter->setPen( Qt::NoPen ); painter->setBrush( background ); painter->drawRect( rect ); } else { drawPrimitive( PE_FrameLineEdit, option, painter, widget ); } } else { // non editable combobox. Make it look like a PushButton // hover takes precedence over focus _animations->inputWidgetEngine().updateState( widget, AnimationHover, mouseOver ); _animations->inputWidgetEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); const AnimationMode mode( _animations->inputWidgetEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->inputWidgetEngine().buttonOpacity( widget ) ); // blend button color to the background const QColor buttonColor( _helper->backgroundColor( palette.color( QPalette::Button ), widget, rect.center() ) ); const QRect slabRect( rect ); if( flat ) { if( !sunken ) { // hover rect const QColor glow( _helper->buttonGlowColor( palette, styleOptions, opacity, mode ) ); if( glow.isValid() ) _helper->slitFocused( glow ).render( rect, painter ); } else { styleOptions |= HoleContrast; _helper->renderHole( painter, palette.color( QPalette::Window ), rect, styleOptions, opacity, mode ); } } else { renderButtonSlab( painter, slabRect, buttonColor, styleOptions, opacity, mode, TileSet::Ring ); } } } if( comboBoxOption->subControls & SC_ComboBoxArrow ) { const QComboBox* comboBox = qobject_cast( widget ); const bool empty( comboBox && !comboBox->count() ); QColor color; QColor background; bool drawContrast( true ); if( comboBoxOption->editable ) { if( enabled && empty ) color = palette.color( QPalette::Disabled, QPalette::Text ); else { // check animation state const bool subControlHover( enabled && mouseOver && comboBoxOption->activeSubControls&SC_ComboBoxArrow ); _animations->comboBoxEngine().updateState( widget, AnimationHover, subControlHover ); const bool animated( enabled && _animations->comboBoxEngine().isAnimated( widget, AnimationHover ) ); const qreal opacity( _animations->comboBoxEngine().opacity( widget, AnimationHover ) ); if( animated ) { QColor highlight = _helper->hoverColor( palette ); color = KColorUtils::mix( palette.color( QPalette::Text ), highlight, opacity ); } else if( subControlHover ) { color = _helper->hoverColor( palette ); } else { color = palette.color( QPalette::Text ); } } background = palette.color( QPalette::Window ); if( enabled ) drawContrast = false; } else { // foreground color const QPalette::ColorRole role( flat ? QPalette::WindowText : QPalette::ButtonText ); if( enabled && empty ) color = palette.color( QPalette::Disabled, role ); else color = palette.color( role ); // background color background = palette.color( flat ? QPalette::Window : QPalette::Button ); } // draw the arrow QRect arrowRect = subControlRect( CC_ComboBox, option, SC_ComboBoxArrow, widget ); const QPolygonF arrow( genericArrow( ArrowDown, ArrowNormal ) ); const qreal penThickness = 1.6; painter->save(); painter->translate( QRectF( arrowRect ).center() ); painter->setRenderHint( QPainter::Antialiasing ); if( drawContrast ) { const qreal offset( qMin( penThickness, qreal( 1 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( _helper->calcLightColor( palette.color( QPalette::Window ) ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->translate( 0,-offset ); } painter->setPen( QPen( _helper->decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->restore(); } return true; } //______________________________________________________________ bool Style::drawSpinBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionSpinBox *spinBoxOption = qstyleoption_cast( option ); if( !spinBoxOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); if( spinBoxOption->subControls & SC_SpinBoxFrame ) { // detect flat spinboxes bool flat( !spinBoxOption->frame ); flat |= ( rect.height() <= 2*Metrics::Frame_FrameWidth + Metrics::MenuButton_IndicatorWidth ); if( flat ) { const QColor background( palette.color( QPalette::Base ) ); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); painter->setBrush( background ); painter->drawRect( rect ); } else { drawPrimitive( PE_FrameLineEdit, option, painter, widget ); } } if( spinBoxOption->subControls & SC_SpinBoxUp ) renderSpinBoxArrow( painter, spinBoxOption, widget, SC_SpinBoxUp ); if( spinBoxOption->subControls & SC_SpinBoxDown ) renderSpinBoxArrow( painter, spinBoxOption, widget, SC_SpinBoxDown ); return true; } //______________________________________________________________ bool Style::drawSliderComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionSlider *sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // copy state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( state & State_HasFocus ); // direction const bool horizontal( sliderOption->orientation == Qt::Horizontal ); if( sliderOption->subControls & SC_SliderTickmarks ) { const bool upsideDown( sliderOption->upsideDown ); const int tickPosition( sliderOption->tickPosition ); const int available( pixelMetric( PM_SliderSpaceAvailable, option, widget ) ); int interval = sliderOption->tickInterval; if( interval < 1 ) interval = sliderOption->pageStep; if( interval >= 1 ) { const int fudge( pixelMetric( PM_SliderLength, option, widget ) / 2 ); int current( sliderOption->minimum ); // store tick lines const QRect grooveRect( subControlRect( CC_Slider, sliderOption, SC_SliderGroove, widget ) ); QList tickLines; if( horizontal ) { if( tickPosition & QSlider::TicksAbove ) tickLines.append( QLine( rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength ) ); if( tickPosition & QSlider::TicksBelow ) tickLines.append( QLine( rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength ) ); } else { if( tickPosition & QSlider::TicksAbove ) tickLines.append( QLine( grooveRect.left() - Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.left() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength, rect.top() ) ); if( tickPosition & QSlider::TicksBelow ) tickLines.append( QLine( grooveRect.right() + Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.right() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength, rect.top() ) ); } // colors QColor base( _helper->backgroundColor( palette.color( QPalette::Window ), widget, rect.center() ) ); base = _helper->calcDarkColor( base ); painter->setPen( base ); while( current <= sliderOption->maximum ) { // calculate positions and draw lines int position( sliderPositionFromValue( sliderOption->minimum, sliderOption->maximum, current, available ) + fudge ); foreach( const QLine& tickLine, tickLines ) { if( horizontal ) painter->drawLine( tickLine.translated( upsideDown ? (rect.width() - position) : position, 0 ) ); else painter->drawLine( tickLine.translated( 0, upsideDown ? (rect.height() - position):position ) ); } // go to next position current += interval; } } } // groove if( sliderOption->subControls & SC_SliderGroove ) { // get rect QRect grooveRect( subControlRect( CC_Slider, sliderOption, SC_SliderGroove, widget ) ); // render _helper->scrollHole( palette.color( QPalette::Window ), sliderOption->orientation, true ).render( grooveRect, painter, TileSet::Full ); } // handle if( sliderOption->subControls & SC_SliderHandle ) { // get rect and center QRect handleRect( subControlRect( CC_Slider, sliderOption, SC_SliderHandle, widget ) ); // handle state const bool handleActive( sliderOption->activeSubControls & SC_SliderHandle ); const bool sunken( state & (State_On|State_Sunken) ); StyleOptions styleOptions; if( hasFocus ) styleOptions |= Focus; if( handleActive && mouseOver ) styleOptions |= Hover; // animation state _animations->widgetStateEngine().updateState( widget, AnimationHover, handleActive && mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); // define colors const QColor color( _helper->backgroundColor( palette.color( QPalette::Button ), widget, handleRect.center() ) ); const QColor glow( _helper->buttonGlowColor( palette, styleOptions, opacity, mode ) ); // render painter->drawPixmap( handleRect.topLeft(), _helper->sliderSlab( color, glow, sunken, 0 ) ); } return true; } //______________________________________________________________ bool Style::drawDialComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const State& state( option->state ); const bool enabled = state & State_Enabled; const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); const bool sunken( state & ( State_On|State_Sunken ) ); StyleOptions styleOptions; if( sunken ) styleOptions |= Sunken; if( hasFocus ) styleOptions |= Focus; if( mouseOver ) styleOptions |= Hover; // mouseOver has precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); const QRect rect( option->rect ); const QPalette &palette( option->palette ); const QColor buttonColor( _helper->backgroundColor( palette.color( QPalette::Button ), widget, rect.center() ) ); renderDialSlab( painter, rect, buttonColor, option, styleOptions, opacity, mode ); return true; } //______________________________________________________________ bool Style::drawScrollBarComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // render full groove directly, rather than using the addPage and subPage control element methods if( option->subControls & SC_ScrollBarGroove ) { // retrieve groove rectangle QRect grooveRect( subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); const QPalette& palette( option->palette ); const QColor color( palette.color( QPalette::Window ) ); const State& state( option->state ); const bool horizontal( state & State_Horizontal ); if( horizontal ) grooveRect = centerRect( grooveRect, grooveRect.width(), StyleConfigData::scrollBarWidth() ); else grooveRect = centerRect( grooveRect, StyleConfigData::scrollBarWidth(), grooveRect.height() ); // render renderScrollBarHole( painter, grooveRect, color, Qt::Horizontal ); } // call base class primitive - ParentStyleClass::drawComplexControl( CC_ScrollBar, option, painter, widget ); + KStyle::drawComplexControl( CC_ScrollBar, option, painter, widget ); return true; } //______________________________________________________________ bool Style::drawTitleBarComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionTitleBar *titleBarOption( qstyleoption_cast( option ) ); if( !titleBarOption ) return true; const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool active( enabled && ( titleBarOption->titleBarState & Qt::WindowActive ) ); // draw title text { QRect textRect = subControlRect( CC_TitleBar, titleBarOption, SC_TitleBarLabel, widget ); // enable state transition _animations->widgetEnableStateEngine().updateState( widget, AnimationEnable, active ); // make sure palette has the correct color group QPalette palette( option->palette ); if( _animations->widgetEnableStateEngine().isAnimated( widget, AnimationEnable ) ) { palette = _helper->disabledPalette( palette, _animations->widgetEnableStateEngine().opacity( widget, AnimationEnable ) ); } palette.setCurrentColorGroup( active ? QPalette::Active: QPalette::Disabled ); - ParentStyleClass::drawItemText( painter, textRect, Qt::AlignCenter, palette, active, titleBarOption->text, QPalette::WindowText ); + KStyle::drawItemText( painter, textRect, Qt::AlignCenter, palette, active, titleBarOption->text, QPalette::WindowText ); } // menu button if( ( titleBarOption->subControls & SC_TitleBarSysMenu ) && ( titleBarOption->titleBarFlags & Qt::WindowSystemMenuHint ) && !titleBarOption->icon.isNull() ) { QRect iconRect = subControlRect( CC_TitleBar, titleBarOption, SC_TitleBarSysMenu, widget ); const int iconWidth( pixelMetric( PM_SmallIconSize, option, widget ) ); const QSize iconSize( iconWidth, iconWidth ); iconRect = centerRect( iconRect, iconSize ); const QPixmap pixmap = titleBarOption->icon.pixmap( iconSize, QIcon::Normal, QIcon::On ); painter->drawPixmap( iconRect, pixmap ); } if( ( titleBarOption->subControls & SC_TitleBarMinButton ) && ( titleBarOption->titleBarFlags & Qt::WindowMinimizeButtonHint ) ) { renderTitleBarButton( painter, titleBarOption, widget, SC_TitleBarMinButton ); } if( ( titleBarOption->subControls & SC_TitleBarMaxButton ) && ( titleBarOption->titleBarFlags & Qt::WindowMaximizeButtonHint ) ) { renderTitleBarButton( painter, titleBarOption, widget, SC_TitleBarMaxButton ); } if( ( titleBarOption->subControls & SC_TitleBarCloseButton ) ) { renderTitleBarButton( painter, titleBarOption, widget, SC_TitleBarCloseButton ); } if( ( titleBarOption->subControls & SC_TitleBarNormalButton ) && ( ( ( titleBarOption->titleBarFlags & Qt::WindowMinimizeButtonHint ) && ( titleBarOption->titleBarState & Qt::WindowMinimized ) ) || ( ( titleBarOption->titleBarFlags & Qt::WindowMaximizeButtonHint ) && ( titleBarOption->titleBarState & Qt::WindowMaximized ) ) ) ) { renderTitleBarButton( painter, titleBarOption, widget, SC_TitleBarNormalButton ); } if( titleBarOption->subControls & SC_TitleBarShadeButton ) { renderTitleBarButton( painter, titleBarOption, widget, SC_TitleBarShadeButton ); } if( titleBarOption->subControls & SC_TitleBarUnshadeButton ) { renderTitleBarButton( painter, titleBarOption, widget, SC_TitleBarUnshadeButton ); } if( ( titleBarOption->subControls & SC_TitleBarContextHelpButton ) && ( titleBarOption->titleBarFlags & Qt::WindowContextHelpButtonHint ) ) { renderTitleBarButton( painter, titleBarOption, widget, SC_TitleBarContextHelpButton ); } return true; } //_________________________________________________________________________________ void Style::renderDialSlab( QPainter *painter, const QRect& constRect, const QColor &color, const QStyleOption *option, StyleOptions styleOptions, qreal opacity, AnimationMode mode ) const { // cast option and check const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return; // copy palette const QPalette& palette( option->palette ); // adjust rect to be square, and centered const int dimension( qMin( constRect.width(), constRect.height() ) ); const QRect rect( centerRect( constRect, dimension, dimension ) ); // calculate glow color const QColor glow( _helper->buttonGlowColor( palette, styleOptions, opacity, mode ) ); // get main slab QPixmap pixmap( _helper->dialSlab( color, glow, 0, dimension ) ); { const QColor light( _helper->calcLightColor( color ) ); const QColor shadow( _helper->calcShadowColor( color ) ); QPainter painter( &pixmap ); painter.setPen( Qt::NoPen ); painter.setRenderHints( QPainter::Antialiasing ); // indicator const qreal angle( dialAngle( sliderOption, sliderOption->sliderPosition ) ); QPointF center( pixmap.rect().center()/_helper->devicePixelRatio( pixmap ) ); const int sliderWidth( dimension/6 ); const qreal radius( 0.5*( dimension - 2*sliderWidth ) ); center += QPointF( radius*cos( angle ), -radius*sin( angle ) ); QRectF sliderRect( 0, 0, sliderWidth, sliderWidth ); sliderRect.moveCenter( center ); // outline circle const qreal offset( 0.3 ); painter.setBrush( light ); painter.setPen( Qt::NoPen ); painter.drawEllipse( sliderRect.translated( 0, offset ) ); // mask painter.setPen( Qt::NoPen ); painter.save(); painter.setCompositionMode( QPainter::CompositionMode_DestinationOut ); painter.setBrush( QBrush( Qt::black ) ); painter.drawEllipse( sliderRect ); painter.restore(); // shadow painter.translate( sliderRect.topLeft() ); _helper->drawInverseShadow( painter, shadow.darker( 200 ), 0, sliderRect.width(), 0 ); // glow if( glow.isValid() ) _helper->drawInverseGlow( painter, glow, 0, sliderRect.width(), sliderRect.width() ); painter.end(); } painter->drawPixmap( rect.topLeft(), pixmap ); return; } //____________________________________________________________________________________ void Style::renderButtonSlab( QPainter *painter, QRect rect, const QColor &color, StyleOptions options, qreal opacity, AnimationMode mode, TileSet::Tiles tiles ) const { // check rect if( !rect.isValid() ) return; // edges // for slabs, hover takes precedence over focus ( other way around for holes ) // but in any case if the button is sunken we don't show focus nor hover TileSet tileSet; if( options & Sunken ) { tileSet = _helper->slabSunken( color ); } else { QColor glow = _helper->buttonGlowColor( QPalette::Active, options, opacity, mode ); tileSet = _helper->slab( color, glow, 0 ); } // adjust rect to account for missing tiles if( tileSet.isValid() ) rect = tileSet.adjust( rect, tiles ); // fill if( !( options & NoFill ) ) _helper->fillButtonSlab( *painter, rect, color, options&Sunken ); // render slab if( tileSet.isValid() ) tileSet.render( rect, painter, tiles ); } //____________________________________________________________________________________ void Style::renderSlab( QPainter *painter, QRect rect, const QColor &color, StyleOptions options, qreal opacity, AnimationMode mode, TileSet::Tiles tiles ) const { // check rect if( !rect.isValid() ) return; // fill if( !( options & NoFill ) ) { painter->save(); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); if( _helper->calcShadowColor( color ).value() > color.value() && ( options & Sunken ) ) { QLinearGradient innerGradient( 0, rect.top(), 0, rect.bottom() + rect.height() ); innerGradient.setColorAt( 0, color ); innerGradient.setColorAt( 1, _helper->calcLightColor( color ) ); painter->setBrush( innerGradient ); } else { QLinearGradient innerGradient( 0, rect.top() - rect.height(), 0, rect.bottom() ); innerGradient.setColorAt( 0, _helper->calcLightColor( color ) ); innerGradient.setColorAt( 1, color ); painter->setBrush( innerGradient ); } _helper->fillSlab( *painter, rect ); painter->restore(); } // edges // for slabs, hover takes precedence over focus ( other way around for holes ) // but in any case if the button is sunken we don't show focus nor hover TileSet tileSet; if( ( options & Sunken ) && color.isValid() ) { tileSet = _helper->slabSunken( color ); } else { // calculate proper glow color based on current settings and opacity const QColor glow( _helper->buttonGlowColor( QPalette::Active, options, opacity, mode ) ); if( color.isValid() || glow.isValid() ) tileSet = _helper->slab( color, glow , 0 ); else return; } // render tileset if( tileSet.isValid() ) tileSet.render( rect, painter, tiles ); } //______________________________________________________________________________________________________________________________ void Style::fillTabBackground( QPainter* painter, const QRect& rect, const QColor &color, const QWidget* widget ) const { // filling const QRect fillRect( insideMargin( rect, Metrics::TabBar_TabOffset ) ); if( widget ) _helper->renderWindowBackground( painter, fillRect, widget, color ); else painter->fillRect( fillRect, color ); } //______________________________________________________________________________________________________________________________ void Style::fillTab( QPainter* painter, const QRect &rect, const QColor &color, QTabBar::Shape shape ) const { const QColor dark( _helper->calcDarkColor( color ) ); const QColor shadow( _helper->calcShadowColor( color ) ); const QColor light( _helper->calcLightColor( color ) ); const QRect fillRect( insideMargin( rect, Metrics::TabBar_TabOffset ) ); QLinearGradient gradient; switch( shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: gradient = QLinearGradient( fillRect.topLeft(), fillRect.bottomLeft() ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: gradient = QLinearGradient( fillRect.bottomLeft(), fillRect.topLeft() ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: gradient = QLinearGradient( fillRect.topRight(), fillRect.topLeft() ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: gradient = QLinearGradient( fillRect.topLeft(), fillRect.topRight() ); break; default: return; } gradient.setColorAt( 0, _helper->alphaColor( light, 0.5 ) ); gradient.setColorAt( 0.1, _helper->alphaColor( light, 0.5 ) ); gradient.setColorAt( 0.25, _helper->alphaColor( light, 0.3 ) ); gradient.setColorAt( 0.5, _helper->alphaColor( light, 0.2 ) ); gradient.setColorAt( 0.75, _helper->alphaColor( light, 0.1 ) ); gradient.setColorAt( 0.9, Qt::transparent ); painter->setRenderHints( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); painter->setBrush( gradient ); painter->drawRoundedRect( fillRect, 2, 2 ); } //____________________________________________________________________________________________________ void Style::renderSpinBoxArrow( QPainter* painter, const QStyleOptionSpinBox* option, const QWidget* widget, const SubControl& subControl ) const { const QPalette& palette( option->palette ); const State& state( option->state ); // enable state bool enabled( state & State_Enabled ); // check steps enable step const bool atLimit( (subControl == SC_SpinBoxUp && !(option->stepEnabled & QAbstractSpinBox::StepUpEnabled )) || (subControl == SC_SpinBoxDown && !(option->stepEnabled & QAbstractSpinBox::StepDownEnabled ) ) ); // update enabled state accordingly enabled &= !atLimit; // update mouse-over effect const bool mouseOver( enabled && ( state & State_MouseOver ) ); // check animation state const bool subControlHover( enabled && mouseOver && ( option->activeSubControls & subControl ) ); _animations->spinBoxEngine().updateState( widget, subControl, subControlHover ); const bool animated( enabled && _animations->spinBoxEngine().isAnimated( widget, subControl ) ); const qreal opacity( _animations->spinBoxEngine().opacity( widget, subControl ) ); QColor color; if( animated ) { QColor highlight = _helper->hoverColor( palette ); color = KColorUtils::mix( palette.color( QPalette::Text ), highlight, opacity ); } else if( subControlHover ) { color = _helper->hoverColor( palette ); } else if( atLimit ) { color = palette.color( QPalette::Disabled, QPalette::Text ); } else { color = palette.color( QPalette::Text ); } const qreal penThickness = 1.6; const QColor background = palette.color( QPalette::Window ); const QPolygonF arrow( genericArrow( ( subControl == SC_SpinBoxUp ) ? ArrowUp:ArrowDown, ArrowNormal ) ); const QRect arrowRect( subControlRect( CC_SpinBox, option, subControl, widget ) ); painter->save(); painter->translate( QRectF( arrowRect ).center() ); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( QPen( _helper->decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->restore(); return; } //___________________________________________________________________________________ void Style::renderSplitter( const QStyleOption* option, QPainter* painter, const QWidget* widget, bool horizontal ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & ( State_MouseOver|State_Sunken ) ) ); // get orientation const Qt::Orientation orientation( horizontal ? Qt::Horizontal : Qt::Vertical ); bool animated( false ); qreal opacity( AnimationData::OpacityInvalid ); if( enabled ) { if( qobject_cast( widget ) ) { _animations->dockSeparatorEngine().updateRect( widget, rect, orientation, mouseOver ); animated = _animations->dockSeparatorEngine().isAnimated( widget, rect, orientation ); opacity = animated ? _animations->dockSeparatorEngine().opacity( widget, orientation ) : AnimationData::OpacityInvalid; } else if( QPaintDevice* device = painter->device() ) { /* try update QSplitterHandle using painter device, because Qt passes QSplitter as the widget to the QStyle primitive. */ _animations->splitterEngine().updateState( device, mouseOver ); animated = _animations->splitterEngine().isAnimated( device ); opacity = _animations->splitterEngine().opacity( device ); } } // get base color const QColor color = palette.color( QPalette::Window ); if( horizontal ) { const int hCenter = rect.center().x(); const int h = rect.height(); if( animated || mouseOver ) { const QColor highlight = _helper->alphaColor( _helper->calcLightColor( color ),0.5*( animated ? opacity:1 ) ); const qreal fraction( rect.height() > 30 ? 10/rect.height():0.1 ); QLinearGradient gradient( rect.topLeft(), rect.bottomLeft() ); gradient.setColorAt( 0, Qt::transparent ); gradient.setColorAt( fraction, highlight ); gradient.setColorAt( 1-fraction, highlight ); gradient.setColorAt( 1, Qt::transparent ); painter->fillRect( rect, gradient ); } const int ngroups( qMax( 1,h / 250 ) ); int center( ( h - ( ngroups-1 ) * 250 ) /2 + rect.top() ); for( int k = 0; k < ngroups; k++, center += 250 ) { _helper->renderDot( painter, QPoint( hCenter, center-3 ), color ); _helper->renderDot( painter, QPoint( hCenter, center ), color ); _helper->renderDot( painter, QPoint( hCenter, center+3 ), color ); } } else { const int vCenter( rect.center().y() ); const int w( rect.width() ); if( animated || mouseOver ) { const QColor highlight( _helper->alphaColor( _helper->calcLightColor( color ),0.5*( animated ? opacity:1 ) ) ); const qreal fraction( rect.width() > 30 ? 10 / rect.width():0.1 ); QLinearGradient gradient( rect.topLeft(), rect.topRight() ); gradient.setColorAt( 0, Qt::transparent ); gradient.setColorAt( fraction, highlight ); gradient.setColorAt( 1 - fraction, highlight ); gradient.setColorAt( 1, Qt::transparent ); painter->fillRect( rect, gradient ); } const int ngroups( qMax( 1, w / 250 ) ); int center = ( w - ( ngroups-1 ) * 250 ) /2 + rect.left(); for( int k = 0; k < ngroups; k++, center += 250 ) { _helper->renderDot( painter, QPoint( center-3, vCenter ), color ); _helper->renderDot( painter, QPoint( center, vCenter ), color ); _helper->renderDot( painter, QPoint( center+3, vCenter ), color ); } } } //____________________________________________________________________________________________________ void Style::renderTitleBarButton( QPainter* painter, const QStyleOptionTitleBar* option, const QWidget* widget, const SubControl& subControl ) const { // get relevant rect const QRect rect = subControlRect( CC_TitleBar, option, subControl, widget ); if( !rect.isValid() ) return; // copy palette QPalette palette = option->palette; // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool active( enabled && ( option->titleBarState & Qt::WindowActive ) ); // enable state transition _animations->widgetEnableStateEngine().updateState( widget, AnimationEnable, active ); if( _animations->widgetEnableStateEngine().isAnimated( widget, AnimationEnable ) ) { palette = _helper->disabledPalette( palette, _animations->widgetEnableStateEngine().opacity( widget, AnimationEnable ) ); } const bool sunken( state & State_Sunken ); const bool mouseOver( ( !sunken ) && widget && rect.translated( widget->mapToGlobal( QPoint( 0,0 ) ) ).contains( QCursor::pos() ) ); _animations->mdiWindowEngine().updateState( widget, subControl, enabled && mouseOver ); const bool animated( enabled && _animations->mdiWindowEngine().isAnimated( widget, subControl ) ); const qreal opacity( _animations->mdiWindowEngine().opacity( widget, subControl ) ); // contrast color const QColor base =option->palette.color( QPalette::Active, QPalette::Window ); // icon color QColor color; if( animated ) { const QColor base( palette.color( active ? QPalette::Active : QPalette::Disabled, QPalette::WindowText ) ); const QColor glow( subControl == SC_TitleBarCloseButton ? _helper->negativeTextColor( palette ): _helper->hoverColor( palette ) ); color = KColorUtils::mix( base, glow, opacity ); } else if( mouseOver ) { color = ( subControl == SC_TitleBarCloseButton ) ? _helper->negativeTextColor( palette ): _helper->hoverColor( palette ); } else { color = palette.color( active ? QPalette::Active : QPalette::Disabled, QPalette::WindowText ); } // rendering renderTitleBarButton( painter, rect, base, color, subControl ); } //____________________________________________________________________________________________________ void Style::renderTitleBarButton( QPainter* painter, const QRect& rect, const QColor& base, const QColor& color, const SubControl& subControl ) const { painter->save(); painter->setRenderHints( QPainter::Antialiasing ); painter->setBrush( Qt::NoBrush ); painter->drawPixmap( rect, _helper->dockWidgetButton( base, true, rect.width() ) ); const qreal width( 1.1 ); // contrast painter->translate( 0, 0.5 ); painter->setPen( QPen( _helper->calcLightColor( base ), width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); renderTitleBarIcon( painter, rect, subControl ); // main icon painting painter->translate( 0,-1 ); painter->setPen( QPen( color, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); renderTitleBarIcon( painter, rect, subControl ); painter->restore(); } //____________________________________________________________________________________ void Style::renderTitleBarIcon( QPainter *painter, const QRect& rect, const SubControl& subControl ) const { painter->save(); painter->translate( rect.topLeft() ); painter->scale( qreal( rect.width() )/16, qreal( rect.height() )/16 ); switch( subControl ) { case SC_TitleBarContextHelpButton: { painter->drawArc( 6, 4, 3, 3, 135*16, -180*16 ); painter->drawArc( 8, 7, 3, 3, 135*16, 45*16 ); painter->drawPoint( 8, 11 ); break; } case SC_TitleBarMinButton: { painter->drawPolyline( QPolygon() << QPoint( 5, 7 ) << QPoint( 8, 10 ) << QPoint( 11, 7 ) ); break; } case SC_TitleBarNormalButton: { painter->drawPolygon( QPolygon() << QPoint( 8, 5 ) << QPoint( 11, 8 ) << QPoint( 8, 11 ) << QPoint( 5, 8 ) ); break; } case SC_TitleBarMaxButton: { painter->drawPolyline( QPolygon() << QPoint( 5, 9 ) << QPoint( 8, 6 ) << QPoint( 11, 9 ) ); break; } case SC_TitleBarCloseButton: { painter->drawLine( QPointF( 5.5, 5.5 ), QPointF( 10.5, 10.5 ) ); painter->drawLine( QPointF( 10.5, 5.5 ), QPointF( 5.5, 10.5 ) ); break; } case SC_TitleBarShadeButton: { painter->drawLine( QPoint( 5, 11 ), QPoint( 11, 11 ) ); painter->drawPolyline( QPolygon() << QPoint( 5, 5 ) << QPoint( 8, 8 ) << QPoint( 11, 5 ) ); break; } case SC_TitleBarUnshadeButton: { painter->drawPolyline( QPolygon() << QPoint( 5, 8 ) << QPoint( 8, 5 ) << QPoint( 11, 8 ) ); painter->drawLine( QPoint( 5, 11 ), QPoint( 11, 11 ) ); break; } default: break; } painter->restore(); } //__________________________________________________________________________ void Style::renderHeaderBackground( const QRect& rect, const QPalette& palette, QPainter* painter, const QWidget* widget, bool horizontal, bool reverse ) const { // use window background for the background if( widget ) _helper->renderWindowBackground( painter, rect, widget, palette ); else painter->fillRect( rect, palette.color( QPalette::Window ) ); if( horizontal ) renderHeaderLines( rect, palette, painter, TileSet::Bottom ); else if( reverse ) renderHeaderLines( rect, palette, painter, TileSet::Left ); else renderHeaderLines( rect, palette, painter, TileSet::Right ); } //__________________________________________________________________________ void Style::renderHeaderLines( const QRect& constRect, const QPalette& palette, QPainter* painter, TileSet::Tiles tiles ) const { // add horizontal lines const QColor color( palette.color( QPalette::Window ) ); const QColor dark( _helper->calcDarkColor( color ) ); const QColor light( _helper->calcLightColor( color ) ); painter->save(); QRect rect( constRect ); if( tiles & TileSet::Bottom ) { painter->setPen( dark ); if( tiles & TileSet::Left ) painter->drawPoint( rect.bottomLeft() ); else if( tiles& TileSet::Right ) painter->drawPoint( rect.bottomRight() ); else painter->drawLine( rect.bottomLeft(), rect.bottomRight() ); rect.adjust( 0, 0, 0, -1 ); painter->setPen( light ); if( tiles & TileSet::Left ) { painter->drawLine( rect.bottomLeft(), rect.bottomLeft()+QPoint( 1, 0 ) ); painter->drawLine( rect.bottomLeft()+ QPoint( 1, 0 ), rect.bottomLeft()+QPoint( 1, 1 ) ); } else if( tiles & TileSet::Right ) { painter->drawLine( rect.bottomRight(), rect.bottomRight() - QPoint( 1, 0 ) ); painter->drawLine( rect.bottomRight() - QPoint( 1, 0 ), rect.bottomRight() - QPoint( 1, -1 ) ); } else { painter->drawLine( rect.bottomLeft(), rect.bottomRight() ); } } else if( tiles & TileSet::Left ) { painter->setPen( dark ); painter->drawLine( rect.topLeft(), rect.bottomLeft() ); rect.adjust( 1, 0, 0, 0 ); painter->setPen( light ); painter->drawLine( rect.topLeft(), rect.bottomLeft() ); } else if( tiles & TileSet::Right ) { painter->setPen( dark ); painter->drawLine( rect.topRight(), rect.bottomRight() ); rect.adjust( 0, 0, -1, 0 ); painter->setPen( light ); painter->drawLine( rect.topRight(), rect.bottomRight() ); } painter->restore(); return; } //__________________________________________________________________________ void Style::renderMenuItemBackground( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QRect& rect( option->rect ); const QPalette& palette( option->palette ); const QRect animatedRect( _animations->menuEngine().animatedRect( widget ) ); if( !animatedRect.isNull() ) { if( animatedRect.intersects( rect ) ) { const QColor color( _helper->menuBackgroundColor( _helper->calcMidColor( palette.color( QPalette::Window ) ), widget, animatedRect.center() ) ); renderMenuItemRect( option, animatedRect, color, palette, painter ); } } else if( _animations->menuEngine().isTimerActive( widget ) ) { const QRect previousRect( _animations->menuEngine().currentRect( widget, Previous ) ); if( previousRect.intersects( rect ) ) { const QColor color( _helper->menuBackgroundColor( _helper->calcMidColor( palette.color( QPalette::Window ) ), widget, previousRect.center() ) ); renderMenuItemRect( option, previousRect, color, palette, painter ); } } else if( _animations->menuEngine().isAnimated( widget, Previous ) ) { QRect previousRect( _animations->menuEngine().currentRect( widget, Previous ) ); if( previousRect.intersects( rect ) ) { const qreal opacity( _animations->menuEngine().opacity( widget, Previous ) ); const QColor color( _helper->menuBackgroundColor( _helper->calcMidColor( palette.color( QPalette::Window ) ), widget, previousRect.center() ) ); renderMenuItemRect( option, previousRect, color, palette, painter, opacity ); } } return; } //__________________________________________________________________________ void Style::renderMenuItemRect( const QStyleOption* option, const QRect& rect, const QColor& base, const QPalette& palette, QPainter* painter, qreal opacity ) const { if( opacity == 0 ) return; // get relevant color // TODO: this is inconsistent with MenuBar color. // this should change to properly account for 'sunken' state QColor color( base ); if( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG ) { color = palette.color( QPalette::Highlight ); } else if( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_SUBTLE ) { color = KColorUtils::mix( color, KColorUtils::tint( color, palette.color( QPalette::Highlight ), 0.6 ) ); } // special painting for items with submenus const QStyleOptionMenuItem* menuItemOption = qstyleoption_cast( option ); if( menuItemOption && menuItemOption->menuItemType == QStyleOptionMenuItem::SubMenu ) { QPixmap pixmap( rect.size() ); { pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); const QRect pixmapRect( pixmap.rect() ); painter.setRenderHint( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); painter.setBrush( color ); _helper->fillHole( painter, pixmapRect ); _helper->holeFlat( color, 0 ).render( pixmapRect.adjusted( 1, 2, -2, -1 ), &painter ); QRect maskRect( visualRect( option->direction, pixmapRect, QRect( pixmapRect.width()-40, 0, 40, pixmapRect.height() ) ) ); QLinearGradient gradient( visualPos( option->direction, maskRect, QPoint( maskRect.left(), 0 ) ), visualPos( option->direction, maskRect, QPoint( maskRect.right()-4, 0 ) ) ); gradient.setColorAt( 0, Qt::black ); gradient.setColorAt( 1, Qt::transparent ); painter.setBrush( gradient ); painter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); painter.drawRect( maskRect ); if( opacity >= 0 && opacity < 1 ) { painter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); painter.fillRect( pixmapRect, _helper->alphaColor( Qt::black, opacity ) ); } painter.end(); } painter->drawPixmap( visualRect( option, rect ), pixmap ); } else { if( opacity >= 0 && opacity < 1 ) { color.setAlphaF( opacity ); } _helper->holeFlat( color, 0 ).render( rect.adjusted( 1, 2, -2, -1 ), painter, TileSet::Full ); } } //________________________________________________________________________ void Style::renderCheckBox( QPainter *painter, const QRect &constRect, const QPalette &palette, StyleOptions options, CheckBoxState state, qreal opacity, AnimationMode mode ) const { const int size( qMin( constRect.width(), constRect.height() ) ); const QRect rect( centerRect( constRect, size, size ) ); if( !( options & NoFill ) ) { if( options & Sunken ) _helper->holeFlat( palette.color( QPalette::Window ), 0, false ).render( insideMargin( rect, 1 ), painter, TileSet::Full ); else renderSlab( painter, rect, palette.color( QPalette::Button ), options, opacity, mode, TileSet::Ring ); } if( state == CheckOff ) return; // check mark qreal penThickness( 2 ); const QColor color( palette.color( ( options&Sunken ) ? QPalette::WindowText:QPalette::ButtonText ) ); const QColor background( palette.color( ( options&Sunken ) ? QPalette::Window:QPalette::Button ) ); QPen pen( _helper->decoColor( background, color ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ); QPen contrastPen( _helper->calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ); if( state == CheckTriState ) { QVector dashes; dashes << 1 << 2; penThickness = 1.3; pen.setWidthF( penThickness ); contrastPen.setWidthF( penThickness ); pen.setDashPattern( dashes ); contrastPen.setDashPattern( dashes ); } else if( state == CheckSunken ) { pen.setColor( _helper->alphaColor( pen.color(), 0.3 ) ); contrastPen.setColor( _helper->alphaColor( contrastPen.color(), 0.3 ) ); } painter->save(); painter->translate( QRectF( rect ).center() ); if( !( options&Sunken ) ) painter->translate( 0, -1 ); painter->setRenderHint( QPainter::Antialiasing ); QPolygonF checkMark; checkMark << QPointF( 5, -2 ) << QPointF( -1, 5 ) << QPointF( -4, 2 ); const qreal offset( qMin( penThickness, qreal( 1 ) ) ); painter->setPen( contrastPen ); painter->translate( 0, offset ); painter->drawPolyline( checkMark ); painter->setPen( pen ); painter->translate( 0, -offset ); painter->drawPolyline( checkMark ); painter->restore(); return; } //___________________________________________________________________ void Style::renderRadioButton( QPainter* painter, const QRect& constRect, const QPalette& palette, StyleOptions options, CheckBoxState state, qreal opacity, AnimationMode mode ) const { // get pixmap const QColor color( palette.color( QPalette::Button ) ); const QColor glow( _helper->buttonGlowColor( palette, options, opacity, mode ) ); QPixmap pixmap( _helper->roundSlab( color, glow, 0 ) ); // center rect const QRect rect( centerRect( constRect, pixmap.size()/_helper->devicePixelRatio( pixmap ) ) ); // render painter->drawPixmap( rect.topLeft(), pixmap ); // draw the radio mark if( state != CheckOff ) { const qreal radius( 2.6 ); const qreal dx( 0.5*rect.width() - radius ); const qreal dy( 0.5*rect.height() - radius ); const QRectF symbolRect( QRectF( rect ).adjusted( dx, dy, -dx, -dy ) ); painter->save(); painter->setRenderHints( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); const QColor background( palette.color( QPalette::Button ) ); const QColor color( palette.color( QPalette::ButtonText ) ); // contrast if( state == CheckOn ) painter->setBrush( _helper->calcLightColor( background ) ); else painter->setBrush( _helper->alphaColor( _helper->calcLightColor( background ), 0.3 ) ); painter->translate( 0, radius/2 ); painter->drawEllipse( symbolRect ); // symbol if( state == CheckOn ) painter->setBrush( _helper->decoColor( background, color ) ); else painter->setBrush( _helper->alphaColor( _helper->decoColor( background, color ), 0.3 ) ); painter->translate( 0, -radius/2 ); painter->drawEllipse( symbolRect ); painter->restore(); } return; } //______________________________________________________________________________ void Style::renderScrollBarHole( QPainter *painter, const QRect &rect, const QColor &color, const Qt::Orientation& orientation, const TileSet::Tiles& tiles ) const { if( !rect.isValid() ) return; // one need to make smaller shadow // notably on the size when rect height is too high const bool smallShadow( orientation == Qt::Horizontal ? rect.height() < 10 : rect.width() < 10 ); _helper->scrollHole( color, orientation, smallShadow ).render( rect, painter, tiles ); } //______________________________________________________________________________ void Style::renderScrollBarHandle( QPainter* painter, const QRect& constRect, const QPalette& palette, const Qt::Orientation& orientation, const bool& hover, const qreal& opacity ) const { if( !constRect.isValid() ) return; // define rect and check QRect rect( insideMargin( constRect, 3 ) ); painter->save(); painter->setRenderHints( QPainter::Antialiasing ); const QColor color( palette.color( QPalette::Button ) ); // draw the slider const qreal radius = 3.5; // glow / shadow QColor glow; const QColor shadow( _helper->alphaColor( _helper->calcShadowColor( color ), 0.4 ) ); const QColor hovered( _helper->hoverColor( palette ) ); if( opacity >= 0 ) glow = KColorUtils::mix( shadow, hovered, opacity ); else if( hover ) glow = hovered; else glow = shadow; _helper->scrollHandle( color, glow ).render( constRect, painter, TileSet::Full ); // contents const QColor mid( _helper->calcMidColor( color ) ); QLinearGradient gradient( rect.topLeft(), rect.bottomLeft() ); gradient.setColorAt(0, color ); gradient.setColorAt(1, mid ); painter->setPen( Qt::NoPen ); painter->setBrush( gradient ); painter->drawRoundedRect( insideMargin( rect, 1 ), radius - 2, radius - 2 ); // bevel pattern const QColor light( _helper->calcLightColor( color ) ); const bool horizontal( orientation == Qt::Horizontal ); QLinearGradient patternGradient( 0, 0, horizontal ? 30:0, horizontal? 0:30 ); patternGradient.setSpread( QGradient::ReflectSpread ); patternGradient.setColorAt( 0, Qt::transparent ); patternGradient.setColorAt( 1, _helper->alphaColor( light, 0.1 ) ); QRect bevelRect( rect ); if( horizontal ) bevelRect = insideMargin( bevelRect, 0, 3 ); else bevelRect = insideMargin( bevelRect, 3, 0 ); if( bevelRect.isValid() ) { painter->setBrush( patternGradient ); painter->drawRect( bevelRect ); } painter->restore(); return; } //______________________________________________________________________________ void Style::renderScrollBarArrow( QPainter* painter, const QRect& rect, const QColor& color, const QColor& background, ArrowOrientation orientation ) const { const qreal penThickness = 1.6; QPolygonF arrow( genericArrow( orientation, ArrowNormal ) ); const QColor contrast( _helper->calcLightColor( background ) ); const QColor base( _helper->decoColor( background, color ) ); painter->save(); painter->translate( QRectF(rect).center() ); painter->setRenderHint( QPainter::Antialiasing ); const qreal offset( qMin( penThickness, qreal( 1 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( contrast, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->translate( 0,-offset ); painter->setPen( QPen( base, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( arrow ); painter->restore(); return; } //______________________________________________________________________________ QColor Style::scrollBarArrowColor( const QStyleOptionSlider* option, const SubControl& control, const QWidget* widget ) const { // copy rect and palette const QRect& rect( option->rect ); const QPalette& palette( option->palette ); // color QColor color( palette.color( QPalette::WindowText ) ); // check enabled state const bool enabled( option->state & State_Enabled ); if( !enabled ) return color; if( ( control == SC_ScrollBarSubLine && option->sliderValue == option->minimum ) || ( control == SC_ScrollBarAddLine && option->sliderValue == option->maximum ) ) { // manually disable arrow, to indicate that scrollbar is at limit return palette.color( QPalette::Disabled, QPalette::WindowText ); } const bool mouseOver( _animations->scrollBarEngine().isHovered( widget, control ) ); const bool animated( _animations->scrollBarEngine().isAnimated( widget, control ) ); const qreal opacity( _animations->scrollBarEngine().opacity( widget, control ) ); // retrieve mouse position from engine QPoint position( mouseOver ? _animations->scrollBarEngine().position( widget ) : QPoint( -1, -1 ) ); if( mouseOver && rect.contains( position ) ) { // need to update the arrow controlRect on fly because there is no // way to get it from the styles directly, outside of repaint events _animations->scrollBarEngine().setSubControlRect( widget, control, rect ); } if( rect.intersects( _animations->scrollBarEngine().subControlRect( widget, control ) ) ) { QColor highlight = _helper->hoverColor( palette ); if( animated ) { color = KColorUtils::mix( color, highlight, opacity ); } else if( mouseOver ) { color = highlight; } } return color; } //______________________________________________________________________________ qreal Style::dialAngle( const QStyleOptionSlider* sliderOption, int value ) const { // calculate angle at which handle needs to be drawn qreal angle( 0 ); if( sliderOption->maximum == sliderOption->minimum ) angle = M_PI / 2; else { qreal fraction( qreal( value - sliderOption->minimum )/qreal( sliderOption->maximum - sliderOption->minimum ) ); if( !sliderOption->upsideDown ) fraction = 1 - fraction; if( sliderOption->dialWrapping ) angle = 1.5*M_PI - fraction*2*M_PI; else angle = ( M_PI*8 - fraction*10*M_PI )/6; } return angle; } //______________________________________________________________ void Style::polishScrollArea( QAbstractScrollArea* scrollArea ) const { if( !scrollArea ) return; // HACK: add exception for KPIM transactionItemView, which is an overlay widget // and must have filled background. This is a temporary workaround until a more // robust solution is found. if( scrollArea->inherits( "KPIM::TransactionItemView" ) ) { // also need to make the scrollarea background plain ( using autofill background ) // so that optional vertical scrollbar background is not transparent either. // TODO: possibly add an event filter to use the "normal" window background // instead of something flat. scrollArea->setAutoFillBackground( true ); return; } // check frame style and background role if( !(scrollArea->frameShape() == QFrame::NoFrame || scrollArea->backgroundRole() == QPalette::Window ) ) { return; } // get viewport and check background role QWidget* viewport( scrollArea->viewport() ); if( !( viewport && viewport->backgroundRole() == QPalette::Window ) ) return; // change viewport autoFill background. // do the same for children if the background role is QPalette::Window viewport->setAutoFillBackground( false ); QList children( viewport->findChildren() ); foreach( QWidget* child, children ) { if( child->parent() == viewport && child->backgroundRole() == QPalette::Window ) { child->setAutoFillBackground( false ); } } } //_______________________________________________________________ QRegion Style::tabBarClipRegion( const QTabBar* tabBar ) const { // need to mask-out arrow buttons, if visible. QRegion mask( tabBar->rect() ); foreach( const QObject* child, tabBar->children() ) { const QToolButton* toolButton( qobject_cast( child ) ); if( toolButton && toolButton->isVisible() ) mask -= toolButton->geometry(); } return mask; } //____________________________________________________________________________________ QPolygonF Style::genericArrow( ArrowOrientation orientation, ArrowSize size ) const { QPolygonF arrow; switch( orientation ) { case ArrowUp: { if( size == ArrowTiny ) arrow << QPointF( -2.25, 1.125 ) << QPointF( 0, -1.125 ) << QPointF( 2.25, 1.125 ); else if( size == ArrowSmall ) arrow << QPointF( -2.5, 1.5 ) << QPointF( 0, -1.5 ) << QPointF( 2.5, 1.5 ); else arrow << QPointF( -3.5, 2 ) << QPointF( 0, -2 ) << QPointF( 3.5, 2 ); break; } case ArrowDown: { if( size == ArrowTiny ) arrow << QPointF( -2.25, -1.125 ) << QPointF( 0, 1.125 ) << QPointF( 2.25, -1.125 ); else if( size == ArrowSmall ) arrow << QPointF( -2.5, -1.5 ) << QPointF( 0, 1.5 ) << QPointF( 2.5, -1.5 ); else arrow << QPointF( -3.5, -2 ) << QPointF( 0, 2 ) << QPointF( 3.5, -2 ); break; } case ArrowLeft: { if( size == ArrowTiny ) arrow << QPointF( 1.125, -2.25 ) << QPointF( -1.125, 0 ) << QPointF( 1.125, 2.25 ); else if( size == ArrowSmall ) arrow << QPointF( 1.5, -2.5 ) << QPointF( -1.5, 0 ) << QPointF( 1.5, 2.5 ); else arrow << QPointF( 2, -3.5 ) << QPointF( -2, 0 ) << QPointF( 2, 3.5 ); break; } case ArrowRight: { if( size == ArrowTiny ) arrow << QPointF( -1.125, -2.25 ) << QPointF( 1.125, 0 ) << QPointF( -1.125, 2.25 ); else if( size == ArrowSmall ) arrow << QPointF( -1.5, -2.5 ) << QPointF( 1.5, 0 ) << QPointF( -1.5, 2.5 ); else arrow << QPointF( -2, -3.5 ) << QPointF( 2, 0 ) << QPointF( -2, 3.5 ); break; } default: break; } return arrow; } //____________________________________________________________________________________ QStyleOptionToolButton Style::separatorMenuItemOption( const QStyleOptionMenuItem* menuItemOption, const QWidget* widget ) const { // separator can have a title and an icon // in that case they are rendered as sunken flat toolbuttons QStyleOptionToolButton toolButtonOption; toolButtonOption.initFrom( widget ); toolButtonOption.rect = menuItemOption->rect; toolButtonOption.features = QStyleOptionToolButton::None; toolButtonOption.state = State_On|State_Sunken|State_Enabled; toolButtonOption.subControls = SC_ToolButton; toolButtonOption.icon = menuItemOption->icon; const int iconWidth( pixelMetric( PM_SmallIconSize, menuItemOption, widget ) ); toolButtonOption.iconSize = QSize( iconWidth, iconWidth ); toolButtonOption.text = menuItemOption->text; toolButtonOption.toolButtonStyle = Qt::ToolButtonTextBesideIcon; return toolButtonOption; } //____________________________________________________________________ bool Style::isQtQuickControl( const QStyleOption* option, const QWidget* widget ) const { - #if QT_VERSION >= 0x050000 const bool is = (widget == nullptr) && option && option->styleObject && option->styleObject->inherits( "QQuickItem" ); if ( is ) _windowManager->registerQuickItem( static_cast( option->styleObject ) ); return is; - #else - Q_UNUSED( widget ); - Q_UNUSED( option ); - return false; - #endif } //_____________________________________________________________ Style::SlabRect::SlabRect(void): tiles( TileSet::Ring ) {} //_____________________________________________________________ Style::SlabRect::SlabRect( const QRect& rect, int tiles ): rect( rect ), tiles( TileSet::Tiles(tiles) ) {} //_____________________________________________________________ bool Style::SlabRect::isValid( void ) const { return rect.isValid() && tiles; } //_____________________________________________________________ void Style::SlabRect::adjust( int tileSize ) { if( !( tiles & TileSet::Left ) ) rect.adjust( -tileSize, 0, 0, 0 ); if( !( tiles & TileSet::Right ) ) rect.adjust( 0, 0, tileSize, 0 ); if( !( tiles & TileSet::Top ) ) rect.adjust( 0, -tileSize, 0, 0 ); if( !( tiles & TileSet::Bottom ) ) rect.adjust( 0, 0, 0, tileSize ); } //_____________________________________________________________ Style::SlabRect Style::SlabRect::adjusted( int tileSize ) const { SlabRect copy( *this ); copy.adjust( tileSize ); return copy; } } namespace OxygenPrivate { //_________________________________________________________________________________________________________ void TabBarData::drawTabBarBaseControl( const QStyleOptionTab* tabOption, QPainter* painter, const QWidget* widget ) { // check parent if( !_style ) return; // make sure widget is locked if( !locks( widget ) ) return; // make sure dirty flag is set if( !_dirty ) return; // cast to TabBar and check const QTabBar* tabBar( qobject_cast( widget ) ); if( !tabBar ) return; // get reverseLayout flag const bool reverseLayout( tabOption->direction == Qt::RightToLeft ); // get documentMode flag - #if OXYGEN_USE_KDE4 - const auto tabOptionV3 = qstyleoption_cast( tabOption ); - #else const auto tabOptionV3 = qstyleoption_cast( tabOption ); - #endif bool documentMode = tabOptionV3 ? tabOptionV3->documentMode : false; const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : nullptr; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); const QRect tabBarRect( tabBar->rect() ); // define slab Oxygen::Style::SlabRect slab; // switch on tab shape switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { Oxygen::TileSet::Tiles tiles( Oxygen::TileSet::Top ); QRect frameRect; frameRect.setLeft( tabBarRect.left() - Oxygen::TileSet::DefaultSize ); frameRect.setRight( tabBarRect.right() + Oxygen::TileSet::DefaultSize ); frameRect.setTop( tabBarRect.bottom() - Oxygen::TileSet::DefaultSize + 1 ); frameRect.setHeight( 4 ); if( !( documentMode || reverseLayout ) ) tiles |= Oxygen::TileSet::Left; if( !documentMode && reverseLayout ) tiles |= Oxygen::TileSet::Right; slab = Oxygen::Style::SlabRect( frameRect, tiles ); break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { Oxygen::TileSet::Tiles tiles( Oxygen::TileSet::Bottom ); QRect frameRect; frameRect.setLeft( tabBarRect.left() - Oxygen::TileSet::DefaultSize ); frameRect.setRight( tabBarRect.right() + Oxygen::TileSet::DefaultSize ); frameRect.setBottom( tabBarRect.top() + Oxygen::TileSet::DefaultSize - 1 ); frameRect.setTop( frameRect.bottom() - 4 ); if( !( documentMode || reverseLayout ) ) tiles |= Oxygen::TileSet::Left; if( !documentMode && reverseLayout ) tiles |= Oxygen::TileSet::Right; slab = Oxygen::Style::SlabRect( frameRect, tiles ); break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { Oxygen::TileSet::Tiles tiles( Oxygen::TileSet::Left ); QRect frameRect; frameRect.setTop( tabBarRect.top() - Oxygen::TileSet::DefaultSize ); frameRect.setBottom( tabBarRect.bottom() + Oxygen::TileSet::DefaultSize ); frameRect.setLeft( tabBarRect.right() - Oxygen::TileSet::DefaultSize + 1 ); frameRect.setWidth( 4 ); if( !( documentMode || reverseLayout ) ) tiles |= Oxygen::TileSet::Top; if( !documentMode && reverseLayout ) tiles |= Oxygen::TileSet::Bottom; slab = Oxygen::Style::SlabRect( frameRect, tiles ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { Oxygen::TileSet::Tiles tiles( Oxygen::TileSet::Right ); QRect frameRect; frameRect.setTop( tabBarRect.top() - Oxygen::TileSet::DefaultSize ); frameRect.setBottom( tabBarRect.bottom() + Oxygen::TileSet::DefaultSize ); frameRect.setRight( tabBarRect.left() + Oxygen::TileSet::DefaultSize - 1 ); frameRect.setLeft( frameRect.right() - 4 ); if( !( documentMode || reverseLayout ) ) tiles |= Oxygen::TileSet::Top; if( !documentMode && reverseLayout ) tiles |= Oxygen::TileSet::Bottom; slab = Oxygen::Style::SlabRect( frameRect, tiles ); break; } default: break; } const bool verticalTabs( _style.data()->isVerticalTab( tabOption ) ); const QRect tabWidgetRect( tabWidget ? tabWidget->rect().translated( -widget->geometry().topLeft() ) : QRect() ); const QPalette& palette( tabOption->palette ); const QColor color( palette.color( QPalette::Window ) ); _style.data()->adjustSlabRect( slab, tabWidgetRect, documentMode, verticalTabs ); _style.data()->renderSlab( painter, slab, color, Oxygen::NoFill ); setDirty( false ); return; } } diff --git a/kstyle/oxygenstyle.h b/kstyle/oxygenstyle.h index 62170f65..db68d0f3 100644 --- a/kstyle/oxygenstyle.h +++ b/kstyle/oxygenstyle.h @@ -1,778 +1,756 @@ #ifndef oxygenstyle_h #define oxygenstyle_h ////////////////////////////////////////////////////////////////////////////// // oxygenstyle.h // Oxygen widget style for KDE 4 // ------------------- // // Copyright (C) 2009-2010 Hugo Pereira Da Costa // Copyright (C) 2008 Long Huynh Huu // Copyright (C) 2007-2008 Casper Boemann // Copyright (C) 2007 Matthew Woehlke // Copyright (C) 2003-2005 Sandro Giessl // // based on the KDE style "dotNET": // Copyright (C) 2001-2002, Chris Lee // Carsten Pfeiffer // Karol Szwed // Drawing routines completely reimplemented from KDE3 HighColor, which was // originally based on some stuff from the KDE2 HighColor. // // based on drawing routines of the style "Keramik": // Copyright (c) 2002 Malte Starostik // (c) 2002,2003 Maksim Orlovich // based on the KDE3 HighColor Style // Copyright (C) 2001-2002 Karol Szwed // (C) 2001-2002 Fredrik H�glund // Drawing routines adapted from the KDE2 HCStyle, // Copyright (C) 2000 Daniel M. Duley // (C) 2000 Dirk Mueller // (C) 2001 Martijn Klingens // Progressbar code based on KStyle, // Copyright (C) 2001-2002 Karol Szwed // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License version 2 as published by the Free Software Foundation. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with this library; see the file COPYING.LIB. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. ////////////////////////////////////////////////////////////////////////////// #include "oxygen.h" #include "oxygentileset.h" #include "config-liboxygen.h" -#if OXYGEN_USE_KDE4 -#include "kstylekde4compat.h" -#else #include -#endif #include +#include #include #include #include #include #include #include #include #include #include -#if QT_VERSION >= 0x050000 -#include -#endif - namespace OxygenPrivate { class TabBarData; } namespace Oxygen { class Animations; class FrameShadowFactory; class MdiWindowShadowFactory; class Mnemonics; class ShadowHelper; class SplitterFactory; class StyleHelper; class Transitions; class TopLevelManager; class WindowManager; class WidgetExplorer; class BlurHelper; - //* convenience typedef for base class - #if OXYGEN_USE_KDE4 - using ParentStyleClass = KStyleKDE4Compat; - #else - using ParentStyleClass = KStyle; - #endif - //* base class for oxygen style /** it is responsible to draw all the primitives to be displayed on screen, on request from Qt paint engine */ - class Style: public ParentStyleClass + class Style: public KStyle { Q_OBJECT /* this tells kde applications that custom style elements are supported, using the kstyle mechanism */ Q_CLASSINFO ("X-KDE-CustomElements", "true") public: //* constructor explicit Style( void ); //* destructor ~Style( void ) override; //* needed to avoid warnings at compilation time - using ParentStyleClass::polish; - using ParentStyleClass::unpolish; + using KStyle::polish; + using KStyle::unpolish; //* widget polishing void polish( QWidget* ) override; //* widget unpolishing void unpolish( QWidget* ) override; //* pixel metrics int pixelMetric(PixelMetric, const QStyleOption* = nullptr, const QWidget* = nullptr) const override; //* style hints int styleHint(StyleHint, const QStyleOption* = nullptr, const QWidget* = nullptr, QStyleHintReturn* = nullptr) const override; //* returns rect corresponding to one widget's subelement QRect subElementRect( SubElement, const QStyleOption*, const QWidget* ) const override; //* returns rect corresponding to one widget's subcontrol QRect subControlRect( ComplexControl, const QStyleOptionComplex*, SubControl, const QWidget* ) const override; //* returns size matching contents QSize sizeFromContents( ContentsType, const QStyleOption*, const QSize&, const QWidget* ) const override; //* returns which subcontrol given QPoint corresponds to SubControl hitTestComplexControl( ComplexControl, const QStyleOptionComplex*, const QPoint&, const QWidget* ) const override; //* primitives void drawPrimitive( PrimitiveElement, const QStyleOption*, QPainter*, const QWidget* ) const override; //* controls void drawControl( ControlElement, const QStyleOption*, QPainter*, const QWidget* ) const override; //* complex controls void drawComplexControl( ComplexControl, const QStyleOptionComplex*, QPainter*, const QWidget* ) const override; //* generic text rendering void drawItemText( QPainter*, const QRect&, int alignment, const QPalette&, bool enabled, const QString&, QPalette::ColorRole = QPalette::NoRole) const override; //*@name event filters //@{ bool eventFilter(QObject *, QEvent *) override; bool eventFilterComboBoxContainer( QWidget*, QEvent* ); bool eventFilterDockWidget( QDockWidget*, QEvent* ); bool eventFilterMdiSubWindow( QMdiSubWindow*, QEvent* ); - - #if QT_VERSION >= 0x050000 bool eventFilterCommandLinkButton( QCommandLinkButton*, QEvent* ); - #endif bool eventFilterScrollBar( QWidget*, QEvent* ); bool eventFilterTabBar( QWidget*, QEvent* ); bool eventFilterToolBar( QToolBar*, QEvent* ); bool eventFilterToolBox( QToolBox*, QEvent* ); //* install event filter to object, in a unique way void addEventFilter( QObject* object ) { object->removeEventFilter( this ); object->installEventFilter( this ); } //@} protected Q_SLOTS: //* standard icons virtual QIcon standardIconImplementation( StandardPixmap, const QStyleOption*, const QWidget* ) const; protected: - #if OXYGEN_USE_KDE4 - //* standard icons - QIcon standardIcon( StandardPixmap pixmap, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const - #else //* standard icons QIcon standardIcon( StandardPixmap pixmap, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override - #endif { return standardIconImplementation( pixmap, option, widget ); } private Q_SLOTS: //* update configuration void configurationChanged( void ); private: //* load configuration void loadConfiguration(); //*@name enumerations and convenience classes //@{ //* used to store slab characteristics class SlabRect { public: //* constructor explicit SlabRect(void); //* constructor SlabRect( const QRect& rect, int tiles ); //* validity bool isValid( void ) const; /** adjust rectangle depending on tiles and tileSize so that it is rendered properly **/ void adjust( int ); /** adjust rectangle depending on tiles and tileSize so that it is rendered properly **/ SlabRect adjusted( int ) const; QRect rect; TileSet::Tiles tiles; //* list of slabs using List = QList; }; //@} //*@name subelementRect specialized functions //@{ //* default implementation. Does not change anything QRect defaultSubElementRect( const QStyleOption* option, const QWidget* ) const { return option->rect; } QRect pushButtonContentsRect( const QStyleOption* option, const QWidget* ) const; QRect checkBoxContentsRect( const QStyleOption* option, const QWidget* ) const; QRect lineEditContentsRect( const QStyleOption*, const QWidget* ) const; QRect progressBarGrooveRect( const QStyleOption* option, const QWidget* ) const; QRect progressBarContentsRect( const QStyleOption* option, const QWidget* ) const; QRect headerArrowRect( const QStyleOption* option, const QWidget* ) const; QRect headerLabelRect( const QStyleOption* option, const QWidget* ) const; QRect tabBarTabLeftButtonRect( const QStyleOption*, const QWidget* ) const; QRect tabBarTabRightButtonRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetTabBarRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetTabContentsRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetTabPaneRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetCornerRect( SubElement, const QStyleOption* option, const QWidget* widget ) const; QRect toolBoxTabContentsRect( const QStyleOption* option, const QWidget* ) const; //@} //*@name subcontrol Rect specialized functions //@{ QRect groupBoxSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect toolButtonSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect comboBoxSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect spinBoxSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect scrollBarInternalSubControlRect( const QStyleOptionComplex*, SubControl ) const; QRect scrollBarSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect sliderSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; //@} //*@name sizeFromContents //@{ QSize defaultSizeFromContents( const QStyleOption*, const QSize& size, const QWidget* ) const { return size; } QSize checkBoxSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize lineEditSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize comboBoxSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize spinBoxSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize sliderSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize pushButtonSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize toolButtonSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize menuBarItemSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize menuItemSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize tabWidgetSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize tabBarTabSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize headerSectionSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize itemViewItemSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; //@} //*@name primitives specialized functions //@{ bool emptyPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const { return true; } bool drawFramePrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameLineEditPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameFocusRectPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameMenuPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameGroupBoxPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameTabWidgetPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameTabBarBasePrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameWindowPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorArrowUpPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowUp, option, painter, widget ); } bool drawIndicatorArrowDownPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowDown, option, painter, widget ); } bool drawIndicatorArrowLeftPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowLeft, option, painter, widget ); } bool drawIndicatorArrowRightPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowRight, option, painter, widget ); } //* dock widget separators /** it uses the same painting as QSplitter, but due to Qt, the horizontal/vertical convention is inverted */ bool drawIndicatorDockWidgetResizeHandlePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const { renderSplitter( option, painter, widget, !(option->state & State_Horizontal ) ); return true; } bool drawIndicatorArrowPrimitive( ArrowOrientation, const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorHeaderArrowPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelButtonCommandPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelButtonToolPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawTabBarPanelButtonToolPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelScrollAreaCornerPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelMenuPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelTipLabelPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelItemViewItemPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorMenuCheckMarkPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorCheckBoxPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorRadioButtonPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorButtonDropDownPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorTabClosePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const; bool drawIndicatorTabTearPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorToolBarHandlePrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorToolBarSeparatorPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorBranchPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawWidgetPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; //@} //*@name controls specialized functions //@{ bool emptyControl( const QStyleOption*, QPainter*, const QWidget* ) const { return true; } bool drawPushButtonLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawToolButtonLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawMenuBarItemControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawMenuItemControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawProgressBarControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawProgressBarContentsControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawProgressBarGrooveControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawProgressBarLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawScrollBarSliderControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawScrollBarAddLineControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawScrollBarSubLineControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawShapedFrameControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawRubberBandControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawHeaderSectionControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawHeaderEmptyAreaControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawTabBarTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawTabBarTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawTabBarTabShapeControl_selected( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawTabBarTabShapeControl_unselected( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawToolBoxTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawToolBoxTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawDockWidgetTitleControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawToolBarControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawSplitterControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { renderSplitter( option, painter, widget, option->state & State_Horizontal ); return true; } //*@} //*@name complex ontrols specialized functions //@{ bool drawToolButtonComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawComboBoxComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawSpinBoxComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawSliderComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawDialComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawScrollBarComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawTitleBarComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; //@} //*@name internal rendering methods /** here mostly to avoid code duplication */ //@{ //* qdial slab void renderDialSlab( QPainter* p, const QRect& r, const QColor& c, const QStyleOption* option, StyleOptions opts = {} ) const { renderDialSlab( p, r, c, option, opts, -1, AnimationNone ); } //* qdial slab void renderDialSlab( QPainter*, const QRect&, const QColor&, const QStyleOption*, StyleOptions, qreal, AnimationMode ) const; //* generic button slab void renderButtonSlab( QPainter* p, QRect r, const QColor& c, StyleOptions opts = {}, TileSet::Tiles tiles = TileSet::Ring) const { renderButtonSlab( p, r, c, opts, -1, AnimationNone, tiles ); } //* generic button slab void renderButtonSlab( QPainter*, QRect, const QColor&, StyleOptions, qreal, AnimationMode, TileSet::Tiles ) const; //* generic slab void renderSlab( QPainter* painter, const SlabRect& slab, const QColor& color, StyleOptions options = {} ) const { renderSlab( painter, slab.rect, color, options, slab.tiles ); } //* generic slab void renderSlab( QPainter* painter, QRect rect, const QColor& color, StyleOptions options = {}, TileSet::Tiles tiles = TileSet::Ring) const { renderSlab( painter, rect, color, options, -1, AnimationNone, tiles ); } //* generic slab void renderSlab( QPainter* painter, const SlabRect& slab, const QColor& color, StyleOptions options, qreal opacity, AnimationMode mode ) const { renderSlab( painter, slab.rect, color, options, opacity, mode, slab.tiles ); } //* generic slab void renderSlab( QPainter*, QRect, const QColor&, StyleOptions, qreal, AnimationMode, TileSet::Tiles ) const; //* tab background /** this paints window background behind tab when tab is being dragged */ void fillTabBackground( QPainter*, const QRect&, const QColor&, const QWidget* ) const; //* tab filling void fillTab( QPainter*, const QRect&, const QColor&, const QTabBar::Shape ) const; //* spinbox arrows void renderSpinBoxArrow( QPainter*, const QStyleOptionSpinBox*, const QWidget*, const SubControl& ) const; //* splitter void renderSplitter( const QStyleOption*, QPainter*, const QWidget*, bool ) const; //* mdi subwindow titlebar button void renderTitleBarButton( QPainter*, const QStyleOptionTitleBar*, const QWidget*, const SubControl& ) const; void renderTitleBarButton( QPainter*, const QRect& r, const QColor&, const QColor&, const SubControl& ) const; void renderTitleBarIcon( QPainter*, const QRect&, const SubControl& ) const; //* header background void renderHeaderBackground( const QRect&, const QPalette&, QPainter*, const QWidget*, bool horizontal, bool reverse ) const; void renderHeaderLines( const QRect&, const QPalette&, QPainter*, TileSet::Tiles ) const; //* menu item background void renderMenuItemBackground( const QStyleOption*, QPainter*, const QWidget* ) const; void renderMenuItemRect( const QStyleOption* opt, const QRect& rect, const QPalette& pal, QPainter* p, qreal opacity = -1 ) const { renderMenuItemRect( opt, rect, pal.color(QPalette::Window), p, opacity ); } void renderMenuItemRect( const QStyleOption*, const QRect&, const QColor&, const QPalette&, QPainter* p, qreal opacity = -1 ) const; //* checkbox state (used for checkboxes _and_ radio buttons) enum CheckBoxState { CheckOn, CheckOff, CheckTriState, CheckSunken }; //* checkbox void renderCheckBox( QPainter*, const QRect&, const QPalette&, StyleOptions, CheckBoxState, qreal opacity = -1, AnimationMode mode = AnimationNone ) const; //* radio button void renderRadioButton( QPainter*, const QRect&, const QPalette&, StyleOptions, CheckBoxState, qreal opacity = -1, AnimationMode mode = AnimationNone ) const; //* scrollbar hole void renderScrollBarHole( QPainter*, const QRect&, const QColor&, const Qt::Orientation&, const TileSet::Tiles& = TileSet::Full ) const; //* scrollbar handle (non animated) void renderScrollBarHandle( QPainter* painter, const QRect& r, const QPalette& palette, const Qt::Orientation& orientation, const bool& hover) const { renderScrollBarHandle( painter, r, palette, orientation, hover, -1 ); } //* scrollbar handle (animated) void renderScrollBarHandle( QPainter*, const QRect&, const QPalette&, const Qt::Orientation&, const bool&, const qreal& ) const; //* scrollbar arrow void renderScrollBarArrow( QPainter*, const QRect&, const QColor&, const QColor&, ArrowOrientation ) const; //* returns true if given scrollbar arrow is animated QColor scrollBarArrowColor( const QStyleOptionSlider*, const SubControl&, const QWidget* ) const; //@} //**@name various utilty functions //@{ //* return dial angle based on option and value qreal dialAngle( const QStyleOptionSlider*, int ) const; //* polish scrollarea void polishScrollArea( QAbstractScrollArea* ) const; //* toolbar mask /** this masks out toolbar expander buttons, when visible, from painting */ QRegion tabBarClipRegion( const QTabBar* ) const; //* returns point position for generic arrows QPolygonF genericArrow( ArrowOrientation, ArrowSize = ArrowNormal ) const; //* scrollbar buttons enum ScrollBarButtonType { NoButton, SingleButton, DoubleButton }; //* returns height for scrollbar buttons depending of button types int scrollBarButtonHeight( const ScrollBarButtonType& type ) const { switch( type ) { case NoButton: return _noButtonHeight; case SingleButton: return _singleButtonHeight; case DoubleButton: return _doubleButtonHeight; default: return 0; } } /** separator can have a title and an icon in that case they are rendered as sunken flat toolbuttons return toolbutton option that matches named separator menu items */ QStyleOptionToolButton separatorMenuItemOption( const QStyleOptionMenuItem*, const QWidget* ) const; //* return true if option corresponds to QtQuick control bool isQtQuickControl( const QStyleOption*, const QWidget* ) const; //@} //* adjust rect based on provided margins QRect insideMargin( const QRect& r, int margin ) const { return insideMargin( r, margin, margin ); } //* adjust rect based on provided margins QRect insideMargin( const QRect& r, int marginWidth, int marginHeight ) const { return r.adjusted( marginWidth, marginHeight, -marginWidth, -marginHeight ); } //* expand size based on margins QSize expandSize( const QSize& size, int margin ) const { return expandSize( size, margin, margin ); } //* expand size based on margins QSize expandSize( const QSize& size, int marginWidth, int marginHeight ) const { return size + 2*QSize( marginWidth, marginHeight ); } //* returns true for vertical tabs bool isVerticalTab( const QStyleOptionTab* option ) const { return isVerticalTab( option->shape ); } bool isVerticalTab( const QTabBar::Shape& shape ) const { return shape == QTabBar::RoundedEast || shape == QTabBar::RoundedWest || shape == QTabBar::TriangularEast || shape == QTabBar::TriangularWest; } //* right to left alignment handling - using ParentStyleClass::visualRect; + using KStyle::visualRect; QRect visualRect(const QStyleOption* opt, const QRect& subRect) const - { return ParentStyleClass::visualRect(opt->direction, opt->rect, subRect); } + { return KStyle::visualRect(opt->direction, opt->rect, subRect); } //* centering QRect centerRect(const QRect &rect, const QSize& size ) const { return centerRect( rect, size.width(), size.height() ); } QRect centerRect(const QRect &rect, int width, int height) const { return QRect(rect.left() + (rect.width() - width)/2, rect.top() + (rect.height() - height)/2, width, height); } /* Checks whether the point is before the bound rect for bound of given orientation. This is needed to implement custom number of buttons in scrollbars, as well as proper mouse-hover */ inline bool preceeds( const QPoint&, const QRect&, const QStyleOption* ) const; //* return which arrow button is hit by point for scrollbar double buttons inline QStyle::SubControl scrollBarHitTest( const QRect&, const QPoint&, const QStyleOption* ) const; //* adjusted slabRect inline void adjustSlabRect( SlabRect& slab, const QRect&, bool documentMode, bool vertical ) const; //* return true if one of the widget's parent inherits requested type inline bool hasParent( const QWidget*, const char* ) const; //* return true if one of the widget's parent inherits requested type template bool hasParent( const QWidget* ) const; //*@name scrollbar button types (for addLine and subLine ) //@{ ScrollBarButtonType _addLineButtons = DoubleButton; ScrollBarButtonType _subLineButtons = SingleButton; //@} //*@name metrics for scrollbar buttons //@{ int _noButtonHeight = 0; int _singleButtonHeight = 14; int _doubleButtonHeight = 28; //@} //* helper StyleHelper* _helper; //* shadow helper ShadowHelper* _shadowHelper; //* animations Animations* _animations; //* transitions Transitions* _transitions; //* window manager WindowManager* _windowManager; //* toplevel manager TopLevelManager* _topLevelManager; //* frame shadows FrameShadowFactory* _frameShadowFactory; //* mdi window shadows MdiWindowShadowFactory* _mdiWindowShadowFactory; //* keyboard accelerators Mnemonics* _mnemonics; //* blur helper BlurHelper* _blurHelper; //* widget explorer WidgetExplorer* _widgetExplorer; //* tabBar data OxygenPrivate::TabBarData* _tabBarData; //* splitter Factory, to extend splitters hit area SplitterFactory* _splitterFactory; //* pointer to primitive specialized function using StylePrimitive = bool(Style::*)(const QStyleOption*, QPainter*, const QWidget* ) const; StylePrimitive _frameFocusPrimitive = nullptr; //* pointer to control specialized function using StyleControl = bool (Style::*)( const QStyleOption*, QPainter*, const QWidget* ) const; //* pointer to control specialized function using StyleComplexControl = bool (Style::*)( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; //*@name custom elements //@{ //* use Argb Drag and Drop Window QStyle::StyleHint SH_ArgbDndWindow; //* styled painting for KCapacityBar QStyle::ControlElement CE_CapacityBar; //@} //* tab close button icon (cached) mutable QIcon _tabCloseIcon; friend class OxygenPrivate::TabBarData; }; //_________________________________________________________________________ bool Style::preceeds( const QPoint& point, const QRect& bound, const QStyleOption* option ) const { if( option->state&QStyle::State_Horizontal) { if( option->direction == Qt::LeftToRight) return point.x() < bound.right(); else return point.x() > bound.x(); } else return point.y() < bound.y(); } //_________________________________________________________________________ QStyle::SubControl Style::scrollBarHitTest( const QRect& rect, const QPoint& point, const QStyleOption* option ) const { if( option->state & QStyle::State_Horizontal) { if( option->direction == Qt::LeftToRight ) return point.x() < rect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; else return point.x() > rect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; } else return point.y() < rect.center().y() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; } //___________________________________________________________________________________ void Style::adjustSlabRect( SlabRect& slab, const QRect& tabWidgetRect, bool documentMode, bool vertical ) const { // no tabWidget found, do nothing if( documentMode || !tabWidgetRect.isValid() ) return; else if( vertical ) { slab.rect.setTop( qMax( slab.rect.top(), tabWidgetRect.top() ) ); slab.rect.setBottom( qMin( slab.rect.bottom(), tabWidgetRect.bottom() ) ); } else { slab.rect.setLeft( qMax( slab.rect.left(), tabWidgetRect.left() ) ); slab.rect.setRight( qMin( slab.rect.right(), tabWidgetRect.right() ) ); } return; } //_________________________________________________________________________ bool Style::hasParent( const QWidget* widget, const char* className ) const { if( !widget ) return false; while( (widget = widget->parentWidget()) ) { if( widget->inherits( className ) ) return true; } return false; } //_________________________________________________________________________ template< typename T > bool Style::hasParent( const QWidget* widget ) const { if( !widget ) return false; while( (widget = widget->parentWidget()) ) { if( qobject_cast( widget ) ) return true; } return false; } } #endif diff --git a/kstyle/oxygenstylehelper.cpp b/kstyle/oxygenstylehelper.cpp index 1ff6e50a..f0c88948 100644 --- a/kstyle/oxygenstylehelper.cpp +++ b/kstyle/oxygenstylehelper.cpp @@ -1,1489 +1,1482 @@ /* * Copyright 2013 Hugo Pereira Da Costa * Copyright 2008 Long Huynh Huu * Copyright 2007 Matthew Woehlke * Copyright 2007 Casper Boemann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "oxygenstylehelper.h" #include #include #include #include #include #include #if OXYGEN_HAVE_X11 #include #endif namespace Oxygen { //______________________________________________________________________________ StyleHelper::StyleHelper( KSharedConfigPtr config ): Helper( config ) { init(); } - //______________________________________________________________________________ - #if OXYGEN_USE_KDE4 - StyleHelper::StyleHelper( const QByteArray& name ): - Helper( name ) - { init(); } - #endif - //______________________________________________________________________________ void StyleHelper::invalidateCaches( void ) { _slabCache.clear(); _slabSunkenCache.clear(); _dialSlabCache.clear(); _roundSlabCache.clear(); _sliderSlabCache.clear(); _holeCache.clear(); _midColorCache.clear(); _dockWidgetButtonCache.clear(); _progressBarCache.clear(); _cornerCache.clear(); _selectionCache.clear(); _holeFlatCache.clear(); _slopeCache.clear(); _slitCache.clear(); _dockFrameCache.clear(); _scrollHoleCache.clear(); _scrollHandleCache.clear(); Helper::invalidateCaches(); } //____________________________________________________________________ void StyleHelper::setMaxCacheSize( int value ) { // base class Helper::setMaxCacheSize( value ); // assign max cache size _slabCache.setMaxCacheSize( value ); _slabSunkenCache.setMaxCost( value ); _dialSlabCache.setMaxCacheSize( value ); _roundSlabCache.setMaxCacheSize( value ); _sliderSlabCache.setMaxCacheSize( value ); _holeCache.setMaxCacheSize( value ); _scrollHandleCache.setMaxCacheSize( value ); _dockWidgetButtonCache.setMaxCost( value ); _progressBarCache.setMaxCost( value ); _cornerCache.setMaxCost( value ); _selectionCache.setMaxCost( value ); _holeFlatCache.setMaxCost( value ); _slopeCache.setMaxCost( value ); _slitCache.setMaxCost( value ); _dockFrameCache.setMaxCost( value ); _scrollHoleCache.setMaxCost( value ); } //____________________________________________________________________ void StyleHelper::renderWindowBackground( QPainter* painter, const QRect& clipRect, const QWidget* widget, const QColor& color, int y_shift) { if( _useBackgroundGradient ) { // normal background gradient Helper::renderWindowBackground( painter, clipRect, widget, widget->window(), color, y_shift ); } else { // if background gradient is disabled, simply render flat background if ( clipRect.isValid() ) { painter->setClipRegion( clipRect,Qt::IntersectClip ); } painter->fillRect( widget->rect(), color ); } } //____________________________________________________________________ void StyleHelper::setHasBackgroundGradient( WId id, bool value ) const { Helper::setHasBackgroundGradient( id, value && _useBackgroundGradient ); } //____________________________________________________________________ void StyleHelper::renderMenuBackground( QPainter* painter, const QRect& clipRect, const QWidget* widget, const QColor& color ) { // get coordinates relative to the client area // this is stupid. One could use mapTo if this was taking const QWidget* and not // QWidget* as argument. const QWidget* w( widget ); int x( 0 ); int y( 0 ); while( !w->isWindow() && w != w->parentWidget() ) { x += w->geometry().x(); y += w->geometry().y(); w = w->parentWidget(); } if ( clipRect.isValid() ) { painter->save(); painter->setClipRegion( clipRect,Qt::IntersectClip ); } // calculate upper part height // special tricks are needed // to handle both window contents and window decoration QRect r = w->rect(); const int height( w->frameGeometry().height() ); const int splitY( qMin( 200, ( 3*height )/4 ) ); const QRect upperRect( QRect( 0, 0, r.width(), splitY ) ); const QPixmap tile( verticalGradient( color, splitY ) ); painter->drawTiledPixmap( upperRect, tile ); const QRect lowerRect( 0,splitY, r.width(), r.height() - splitY ); painter->fillRect( lowerRect, backgroundBottomColor( color ) ); if ( clipRect.isValid() ) { painter->restore(); } } //____________________________________________________________________________________ QColor StyleHelper::arrowColor( const QPalette& palette, StyleOptions options, qreal opacity, AnimationMode mode ) const { QColor glow( palette.color( QPalette::WindowText ) ); if( mode == AnimationNone || opacity < 0 ) { if( options & Hover ) glow = hoverColor( palette ); else if( options & Focus ) glow = focusColor( palette ); } else if( mode == AnimationHover ) { // animated color, hover if( options & Focus ) glow = focusColor( palette ); if( glow.isValid() ) glow = KColorUtils::mix( glow, hoverColor( palette ), opacity ); } else if( mode == AnimationFocus ) { if( options & Hover ) glow = hoverColor( palette ); if( glow.isValid() ) glow = KColorUtils::mix( glow, focusColor( palette ), opacity ); } return glow; } //____________________________________________________________________________________ QColor StyleHelper::buttonGlowColor( QPalette::ColorGroup colorGroup, StyleOptions options, qreal opacity, AnimationMode mode ) const { QColor glow; if( mode == AnimationNone || opacity < 0 ) { if( options & Hover ) glow = hoverColor( colorGroup ); else if( options & Focus ) glow = focusColor( colorGroup ); } else if( mode == AnimationHover ) { // animated color, hover if( options & Focus ) glow = focusColor( colorGroup ); if( glow.isValid() ) glow = KColorUtils::mix( glow, hoverColor( colorGroup ), opacity ); else glow = alphaColor( hoverColor( colorGroup ), opacity ); } else if( mode == AnimationFocus ) { if( options & Hover ) glow = hoverColor( colorGroup ); if( glow.isValid() ) glow = KColorUtils::mix( glow, focusColor( colorGroup ), opacity ); else glow = alphaColor( focusColor( colorGroup ), opacity ); } return glow; } //____________________________________________________________________________________ QColor StyleHelper::frameGlowColor( QPalette::ColorGroup colorGroup, StyleOptions options, qreal opacity, AnimationMode mode ) const { QColor glow; if( mode == AnimationNone || opacity < 0 ) { if( options & Focus ) glow = focusColor( colorGroup ); else if( options & Hover ) glow = hoverColor( colorGroup ); } else if( mode == AnimationFocus ) { if( options & Hover ) glow = hoverColor( colorGroup ); if( glow.isValid() ) glow = KColorUtils::mix( glow, focusColor( colorGroup ), opacity ); else glow = alphaColor( focusColor( colorGroup ), opacity ); } else if( mode == AnimationHover ) { // animated color, hover if( options & Focus ) glow = focusColor( colorGroup ); if( glow.isValid() ) glow = KColorUtils::mix( glow, hoverColor( colorGroup ), opacity ); else glow = alphaColor( hoverColor( colorGroup ), opacity ); } return glow; } //______________________________________________________________________________ QPalette StyleHelper::disabledPalette( const QPalette& source, qreal ratio ) const { QPalette out( source ); out.setColor( QPalette::Window, KColorUtils::mix( source.color( QPalette::Active, QPalette::Background ), source.color( QPalette::Disabled, QPalette::Background ), 1.0-ratio ) ); out.setColor( QPalette::Highlight, KColorUtils::mix( source.color( QPalette::Active, QPalette::Highlight ), source.color( QPalette::Disabled, QPalette::Highlight ), 1.0-ratio ) ); out.setColor( QPalette::WindowText, KColorUtils::mix( source.color( QPalette::Active, QPalette::WindowText ), source.color( QPalette::Disabled, QPalette::WindowText ), 1.0-ratio ) ); out.setColor( QPalette::ButtonText, KColorUtils::mix( source.color( QPalette::Active, QPalette::ButtonText ), source.color( QPalette::Disabled, QPalette::ButtonText ), 1.0-ratio ) ); out.setColor( QPalette::Text, KColorUtils::mix( source.color( QPalette::Active, QPalette::Text ), source.color( QPalette::Disabled, QPalette::Text ), 1.0-ratio ) ); out.setColor( QPalette::Button, KColorUtils::mix( source.color( QPalette::Active, QPalette::Button ), source.color( QPalette::Disabled, QPalette::Button ), 1.0-ratio ) ); return out; } //______________________________________________________________________________ QPixmap StyleHelper::dockWidgetButton( const QColor& color, bool pressed, int size ) { const quint64 key( ( colorKey(color) << 32 ) | ( size << 1 ) | quint64( pressed ) ); if( QPixmap *cachedPixmap = _dockWidgetButtonCache.object( key ) ) { return *cachedPixmap; } QPixmap pixmap( highDpiPixmap( size, size ) ); pixmap.fill( Qt::transparent ); const QColor light( calcLightColor( color ) ); const QColor dark( calcDarkColor( color ) ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const qreal u( size/18.0 ); painter.translate( 0.5*u, ( 0.5-0.668 )*u ); { // outline circle qreal penWidth = 1.2; QLinearGradient linearGradient( 0, u*( 1.665-penWidth ), 0, u*( 12.33+1.665-penWidth ) ); linearGradient.setColorAt( 0, dark ); linearGradient.setColorAt( 1, light ); QRectF r( u*0.5*( 17-12.33+penWidth ), u*( 1.665+penWidth ), u*( 12.33-penWidth ), u*( 12.33-penWidth ) ); painter.setPen( QPen( linearGradient, penWidth*u ) ); painter.drawEllipse( r ); painter.end(); } _dockWidgetButtonCache.insert( key, new QPixmap( pixmap ) ); return pixmap; } //________________________________________________________________________________________________________ TileSet StyleHelper::roundCorner( const QColor& color, int size ) { const quint64 key( ( colorKey(color) << 32 )|size ); if( TileSet *cachedTileSet = _cornerCache.object( key ) ) { return *cachedTileSet; } QPixmap pixmap = QPixmap( size*2, size*2 ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHint( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); QLinearGradient linearGradient = QLinearGradient( 0.0, size-4.5, 0.0, size+4.5 ); linearGradient.setColorAt( 0.50, calcLightColor( backgroundTopColor( color ) ) ); linearGradient.setColorAt( 0.51, backgroundBottomColor( color ) ); // draw ellipse. painter.setBrush( linearGradient ); painter.drawEllipse( QRectF( size-4, size-4, 8, 8 ) ); // mask painter.setCompositionMode( QPainter::CompositionMode_DestinationOut ); painter.setBrush( Qt::black ); painter.drawEllipse( QRectF( size-3, size-3, 6, 6 ) ); TileSet tileSet( pixmap, size, size, 1, 1 ); _cornerCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //________________________________________________________________________________________________________ TileSet StyleHelper::slope( const QColor& color, qreal shade, int size ) { const quint64 key( ( colorKey(color) << 32 )|( quint64( 256.0*shade )<<24 )|size ); if( TileSet *cachedTileSet = _slopeCache.object( key ) ) { return *cachedTileSet; } QPixmap pixmap( highDpiPixmap( size*4 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setPen( Qt::NoPen ); // edges TileSet slabTileSet = slab( color, shade, size ); slabTileSet.render( QRect( 0, 0, size*4, size*5 ), &painter, TileSet::Left | TileSet::Right | TileSet::Top ); int fixedSize( 28*devicePixelRatio( pixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); // bottom QColor light = KColorUtils::shade( calcLightColor( color ), shade ); QLinearGradient fillGradient( 0, -28, 0, 28 ); light.setAlphaF( 0.4 ); fillGradient.setColorAt( 0.0, light ); light.setAlphaF( 0.0 ); fillGradient.setColorAt( 1.0, light ); painter.setBrush( fillGradient ); painter.setCompositionMode( QPainter::CompositionMode_DestinationOver ); painter.drawRect( 3, 9, 22, 17 ); // fade bottom QLinearGradient maskGradient( 0, 7, 0, 28 ); maskGradient.setColorAt( 0.0, Qt::black ); maskGradient.setColorAt( 1.0, Qt::transparent ); painter.setBrush( maskGradient ); painter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); painter.drawRect( 0, 9, 28, 19 ); painter.end(); TileSet tileSet( pixmap, size, size, size*2, 2 ); _slopeCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //________________________________________________________________________________________________________ void StyleHelper::drawInverseShadow( QPainter& painter, const QColor& color, int pad, int size, qreal fuzz ) const { const qreal m( qreal( size )*0.5 ); const qreal offset( 0.8 ); const qreal k0( ( m-2 ) / qreal( m+2.0 ) ); QRadialGradient shadowGradient( pad+m, pad+m+offset, m+2 ); for ( int i = 0; i < 8; i++ ) { // sinusoidal gradient const qreal k1( ( qreal( 8 - i ) + k0 * qreal( i ) ) * 0.125 ); const qreal a( ( cos( 3.14159 * i * 0.125 ) + 1.0 ) * 0.25 ); shadowGradient.setColorAt( k1, alphaColor( color, a * _shadowGain ) ); } shadowGradient.setColorAt( k0, alphaColor( color, 0.0 ) ); painter.setBrush( shadowGradient ); painter.drawEllipse( QRectF( pad-fuzz, pad-fuzz, size+fuzz*2.0, size+fuzz*2.0 ) ); } //________________________________________________________________________________________________________ void StyleHelper::fillSlab( QPainter& painter, const QRect& rect, int size ) const { const qreal s( qreal( size ) * ( 3.6 + ( 0.5 * _slabThickness ) ) / 7.0 ); const QRectF r( QRectF( rect ).adjusted( s, s, -s, -s ) ); if( !r.isValid() ) return; painter.drawRoundedRect( r, s/2, s/2 ); } //________________________________________________________________________________________________________ void StyleHelper::fillButtonSlab( QPainter& painter, const QRect& r, const QColor& color, bool sunken ) { painter.save(); painter.setRenderHint( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); if( sunken && calcShadowColor( color ).value() > color.value() ) { QLinearGradient innerGradient( 0, r.top(), 0, r.bottom() + r.height() ); innerGradient.setColorAt( 0.0, color ); innerGradient.setColorAt( 1.0, calcLightColor( color ) ); painter.setBrush( innerGradient ); } else if( sunken ) { QLinearGradient innerGradient( 0, r.top() - r.height(), 0, r.bottom() ); innerGradient.setColorAt( 0.0, calcLightColor( color ) ); innerGradient.setColorAt( 1.0, color ); painter.setBrush( innerGradient ); } else { QLinearGradient innerGradient( 0, r.top()-0.2*r.height(), 0, r.bottom()+ 0.4*r.height() ); innerGradient.setColorAt( 0.0, calcLightColor( color ) ); innerGradient.setColorAt( 0.6, color ); painter.setBrush( innerGradient ); } fillSlab( painter, r ); painter.restore(); } //________________________________________________________________________________________________________ TileSet StyleHelper::slab( const QColor& color, const QColor& glow, qreal shade, int size ) { Oxygen::Cache::Value cache( _slabCache.get( color ) ); const quint64 key( ( colorKey(glow) << 32 ) | ( quint64( 256.0 * shade ) << 24 ) | size ); if( TileSet *cachedTileSet = cache->object( key ) ) { return *cachedTileSet; } QPixmap pixmap( highDpiPixmap( size*2 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const int fixedSize( 14*devicePixelRatio( pixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); // draw all components if( color.isValid() ) drawShadow( painter, calcShadowColor( color ), 14 ); if( glow.isValid() ) drawOuterGlow( painter, glow, 14 ); if( color.isValid() ) drawSlab( painter, color, shade ); painter.end(); TileSet tileSet( pixmap, size, size, size, size, size-1, size, 2, 1 ); cache->insert( key, new TileSet( tileSet ) ); return tileSet; } //________________________________________________________________________________________________________ TileSet StyleHelper::slabSunken( const QColor& color, int size ) { const quint64 key( colorKey(color) << 32 | size ); if( TileSet *cachedTileSet = _slabSunkenCache.object( key ) ) { return *cachedTileSet; } QPixmap pixmap( highDpiPixmap( size*2 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const int fixedSize( 14*devicePixelRatio( pixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); // shadow painter.setCompositionMode( QPainter::CompositionMode_SourceOver ); drawInverseShadow( painter, calcShadowColor( color ), 3, 8, 0.0 ); // contrast pixel { QColor light( calcLightColor( color ) ); QLinearGradient blend( 0, 2, 0, 16 ); blend.setColorAt( 0.5, Qt::transparent ); blend.setColorAt( 1.0, light ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( blend, 1 ) ); painter.drawRoundedRect( QRectF( 2.5, 2.5, 9, 9 ), 4.0, 4.0 ); painter.setPen( Qt::NoPen ); } painter.end(); TileSet tileSet( pixmap, size, size, size, size, size-1, size, 2, 1 ); _slabSunkenCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //__________________________________________________________________________________________________________ TileSet StyleHelper::progressBarIndicator( const QPalette& pal, int dimension ) { const QColor highlight( pal.color( QPalette::Highlight ) ); const quint64 key( ( colorKey(highlight) << 32 ) | dimension ); if( TileSet *cachedTileSet = _progressBarCache.object( key ) ) { return *cachedTileSet; } QRect local( 0, 0, dimension, dimension ); QPixmap pixmap( highDpiPixmap( local.size() ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setBrush( Qt::NoBrush ); const QColor lhighlight( calcLightColor( highlight ) ); const QColor color( pal.color( QPalette::Active, QPalette::Window ) ); const QColor light( calcLightColor( color ) ); const QColor dark( calcDarkColor( color ) ); const QColor shadow( calcShadowColor( color ) ); // shadow { painter.setPen( QPen( alphaColor( shadow, 0.4 ),0.6 ) ); painter.drawRoundedRect( QRectF( local ).adjusted( 0.5, 0.5, -0.5, 0.5 ), 3.0, 3.0 ); } // fill local.adjust( 1, 1, -1, 0 ); { painter.setPen( Qt::NoPen ); painter.setBrush( KColorUtils::mix( highlight, dark, 0.2 ) ); painter.drawRoundedRect( local, 2.5, 2.5 ); } // fake radial gradient { QPixmap pixmap( highDpiPixmap( local.size() ) ); pixmap.fill( Qt::transparent ); { QRect pixmapRect( QPoint(0, 0), local.size() ); QLinearGradient mask( pixmapRect.topLeft(), pixmapRect.topRight() ); mask.setColorAt( 0.0, Qt::transparent ); mask.setColorAt( 0.4, Qt::black ); mask.setColorAt( 0.6, Qt::black ); mask.setColorAt( 1.0, Qt::transparent ); QLinearGradient radial( pixmapRect.topLeft(), pixmapRect.bottomLeft() ); radial.setColorAt( 0.0, KColorUtils::mix( lhighlight, light, 0.3 ) ); radial.setColorAt( 0.5, Qt::transparent ); radial.setColorAt( 0.6, Qt::transparent ); radial.setColorAt( 1.0, KColorUtils::mix( lhighlight, light, 0.3 ) ); QPainter painter( &pixmap ); painter.fillRect( pixmap.rect(), mask ); painter.setCompositionMode( QPainter::CompositionMode_SourceIn ); painter.fillRect( pixmapRect, radial ); painter.end(); } painter.drawPixmap( QPoint( 1,1 ), pixmap ); } // bevel { QLinearGradient bevel( QPointF( 0, 0.5 ) + local.topLeft(), QPointF( 0, -0.5 ) + local.bottomLeft() ); bevel.setColorAt( 0, lhighlight ); bevel.setColorAt( 0.5, highlight ); bevel.setColorAt( 1, calcDarkColor( highlight ) ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( bevel, 1 ) ); painter.drawRoundedRect( QRectF(local).adjusted( 0.5, 0.5, -0.5, -0.5 ), 2.5, 2.5 ); } // bright top edge { QLinearGradient lightHl( local.topLeft(),local.topRight() ); lightHl.setColorAt( 0, Qt::transparent ); lightHl.setColorAt( 0.5, KColorUtils::mix( highlight, light, 0.8 ) ); lightHl.setColorAt( 1, Qt::transparent ); painter.setPen( QPen( lightHl, 1 ) ); painter.drawLine( QPointF( 0.5, 0.5 ) + local.topLeft(), QPointF( 0.5, 0.5 ) + local.topRight() ); } painter.end(); // generate tileSet and save in cache const int radius = qMin( 3, dimension/2 ); TileSet tileSet( pixmap, radius, radius, dimension-2*radius, dimension-2*radius ); _progressBarCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //______________________________________________________________________________ QPixmap StyleHelper::dialSlab( const QColor& color, const QColor& glow, qreal shade, int size ) { Oxygen::Cache::Value cache = _dialSlabCache.get( color ); const quint64 key( ( colorKey(glow) << 32 ) | ( quint64( 256.0 * shade ) << 24 ) | size ); if( QPixmap* cachedPixmap = cache->object( key ) ) { return *cachedPixmap; } QPixmap pixmap( highDpiPixmap( size ) ); pixmap.fill( Qt::transparent ); QRectF rect( 0, 0, size, size ); QPainter painter( &pixmap ); painter.setPen( Qt::NoPen ); painter.setRenderHints( QPainter::Antialiasing ); // colors const QColor base( KColorUtils::shade( color, shade ) ); const QColor light( KColorUtils::shade( calcLightColor( color ), shade ) ); const QColor dark( KColorUtils::shade( calcDarkColor( color ), shade ) ); const QColor mid( KColorUtils::shade( calcMidColor( color ), shade ) ); const QColor shadow( calcShadowColor( color ) ); // shadow drawShadow( painter, shadow, rect.width() ); if( glow.isValid() ) { drawOuterGlow( painter, glow, rect.width() ); } const qreal baseOffset( 3.5 ); { //plain background QLinearGradient linearGradient( 0, baseOffset-0.5*rect.height(), 0, baseOffset+rect.height() ); linearGradient.setColorAt( 0, light ); linearGradient.setColorAt( 0.8, base ); painter.setBrush( linearGradient ); const qreal offset( baseOffset ); painter.drawEllipse( rect.adjusted( offset, offset, -offset, -offset ) ); } { // outline circle const qreal penWidth( 0.7 ); QLinearGradient linearGradient( 0, baseOffset, 0, baseOffset + 2*rect.height() ); linearGradient.setColorAt( 0, light ); linearGradient.setColorAt( 1, mid ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( linearGradient, penWidth ) ); const qreal offset( baseOffset+0.5*penWidth ); painter.drawEllipse( rect.adjusted( offset, offset, -offset, -offset ) ); } cache->insert( key, new QPixmap( pixmap ) ); return pixmap; } //__________________________________________________________________________________________________________ QPixmap StyleHelper::roundSlab( const QColor& color, const QColor& glow, qreal shade, int size ) { Oxygen::Cache::Value cache( _roundSlabCache.get( color ) ); const quint64 key( ( colorKey(glow) << 32 ) | ( quint64( 256.0 * shade ) << 24 ) | size ); if( QPixmap* cachedPixmap = cache->object( key ) ) { return *cachedPixmap; } QPixmap pixmap( highDpiPixmap( size*3 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const int fixedSize( 21*devicePixelRatio( pixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); // draw normal shadow drawShadow( painter, calcShadowColor( color ), 21 ); // draw glow. if( glow.isValid() ) { drawOuterGlow( painter, glow, 21 ); } drawRoundSlab( painter, color, shade ); painter.end(); cache->insert( key, new QPixmap( pixmap ) ); return pixmap; } //__________________________________________________________________________________________________________ QPixmap StyleHelper::sliderSlab( const QColor& color, const QColor& glow, bool sunken, qreal shade, int size ) { Oxygen::Cache::Value cache( _sliderSlabCache.get( color ) ); const quint64 key( ( colorKey(glow) << 32 ) | ( quint64( 256.0 * shade ) << 24 ) | (sunken << 23 ) | size ); if( QPixmap *cachedPixmap = cache->object( key ) ) { return *cachedPixmap; } QPixmap pixmap( highDpiPixmap( size*3 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); if( color.isValid() ) drawShadow( painter, alphaColor( calcShadowColor( color ), 0.8 ), 21 ); if( glow.isValid() ) drawOuterGlow( painter, glow, 21 ); // draw slab drawSliderSlab( painter, color, sunken, shade ); painter.end(); cache->insert( key, new QPixmap( pixmap ) ); return pixmap; } //______________________________________________________________________________ void StyleHelper::renderDebugFrame( QPainter* painter, const QRect& rect ) const { painter->save(); painter->setRenderHints( QPainter::Antialiasing ); painter->setBrush( Qt::NoBrush ); painter->setPen( Qt::red ); painter->drawRect( QRectF( rect ).adjusted( 0.5, 0.5, -0.5, -0.5 ) ); painter->restore(); } //________________________________________________________________________________________________________ void StyleHelper::fillHole( QPainter& painter, const QRect& rect, int offset ) const { painter.drawRoundedRect( rect.adjusted( offset, offset, -offset, -offset ), 4 - offset, 4 - offset ); } //____________________________________________________________________________________ void StyleHelper::renderHole( QPainter* painter, const QColor& base, const QRect& rect, StyleOptions options, qreal opacity, Oxygen::AnimationMode mode, TileSet::Tiles tiles ) { if( !rect.isValid() ) return; const QColor glow( frameGlowColor( QPalette::Active, options, opacity, mode ) ); hole( base, glow, TileSet::DefaultSize, options ).render( rect, painter, tiles ); } //________________________________________________________________________________________________________ TileSet StyleHelper::holeFlat( const QColor& color, qreal shade, bool fill, int size ) { const quint64 key( ( colorKey(color) << 32 ) | ( quint64( 256.0 * shade ) << 24 ) | size << 1 | fill ); if( TileSet *cachedTileSet = _holeFlatCache.object( key ) ) { return *cachedTileSet; } QPixmap pixmap( highDpiPixmap( size*2 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const int fixedSize( 14*devicePixelRatio( pixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); if( fill ) { // hole inside painter.setBrush( color ); painter.drawRoundedRect( QRectF( 1, 0, 12, 13 ), 3.0, 3.0 ); painter.setBrush( Qt::NoBrush ); { // shadow (top) const QColor dark( KColorUtils::shade( calcDarkColor( color ), shade ) ); QLinearGradient gradient( 0, -2, 0, 14 ); gradient.setColorAt( 0.0, dark ); gradient.setColorAt( 0.5, Qt::transparent ); painter.setPen( QPen( gradient, 1 ) ); painter.drawRoundedRect( QRectF( 1.5, 0.5, 11, 12 ), 2.5, 2.5 ); } { // contrast (bottom) const QColor light( KColorUtils::shade( calcLightColor( color ), shade ) ); QLinearGradient gradient( 0, 0, 0, 18 ); gradient.setColorAt( 0.5, Qt::transparent ); gradient.setColorAt( 1.0, light ); painter.setPen( QPen( gradient, 1 ) ); painter.drawRoundedRect( QRectF( 0.5, 0.5, 13, 13 ), 3.5, 3.5 ); } } else { // hole inside painter.setBrush( color ); painter.drawRoundedRect( QRectF( 2, 2, 10, 10 ), 3.0, 3.0 ); painter.setBrush( Qt::NoBrush ); { // shadow (top) const QColor dark( KColorUtils::shade( calcDarkColor( color ), shade ) ); QLinearGradient gradient( 0, 1, 0, 12 ); gradient.setColorAt( 0.0, dark ); gradient.setColorAt( 0.5, Qt::transparent ); painter.setPen( QPen( gradient, 1 ) ); painter.drawRoundedRect( QRectF( 2.5, 2.5, 10, 10 ), 2.5, 2.5 ); } { // contrast (bottom) const QColor light( KColorUtils::shade( calcLightColor( color ), shade ) ); QLinearGradient gradient( 0, 1, 0, 12 ); gradient.setColorAt( 0.5, Qt::transparent ); gradient.setColorAt( 1.0, light ); painter.setPen( QPen( gradient, 1 ) ); painter.drawRoundedRect( QRectF( 2, 1.5, 10, 11 ), 3.0, 2.5 ); } } painter.end(); TileSet tileSet( pixmap, size, size, size, size, size-1, size, 2, 1 ); _holeFlatCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //______________________________________________________________________________ TileSet StyleHelper::scrollHole( const QColor& color, Qt::Orientation orientation, bool smallShadow ) { const quint64 key( colorKey(color) << 32 | ( orientation == Qt::Horizontal ? 2 : 0 ) | ( smallShadow ? 1 : 0 ) ); if( TileSet *cachedTileSet = _scrollHoleCache.object( key ) ) { return *cachedTileSet; } QPixmap pixmap( highDpiPixmap( 15 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); const QColor dark( calcDarkColor( color ) ); const QColor light( calcLightColor( color ) ); const QColor shadow( calcShadowColor( color ) ); // use space for white border const QRect pixmapRect( 0, 0, 15, 15 ); const QRect rect( pixmapRect.adjusted( 1, 1, -1, -1 ) ); painter.setRenderHints( QPainter::Antialiasing ); painter.setBrush( dark ); painter.setPen( Qt::NoPen ); // base const qreal radius( smallShadow ? 2.5:3.0 ); painter.drawRoundedRect( rect, radius, radius ); { // slight shadow across the whole hole QLinearGradient shadowGradient( rect.topLeft(), orientation == Qt::Horizontal ? rect.bottomLeft():rect.topRight() ); shadowGradient.setColorAt( 0.0, alphaColor( shadow, 0.1 ) ); shadowGradient.setColorAt( 0.6, Qt::transparent ); painter.setBrush( shadowGradient ); painter.drawRoundedRect( rect, radius, radius ); } // first create shadow int shadowSize( 5 ); QPixmap shadowPixmap( highDpiPixmap( shadowSize*2 ) ); { shadowPixmap.fill( Qt::transparent ); QPainter painter( &shadowPixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); // fade-in shadow QColor shadowColor( calcShadowColor( color ) ); if( smallShadow ) shadowColor = alphaColor( shadowColor, 0.6 ); drawInverseShadow( painter, shadowColor, 1, 8, 0.0 ); painter.end(); } // render shadow TileSet( shadowPixmap, shadowSize, shadowSize, shadowSize, shadowSize, shadowSize-1, shadowSize, 2, 1 ). render( rect.adjusted( -1, -1, 1, 1 ), &painter, TileSet::Full ); // light border QLinearGradient borderGradient( 0, pixmapRect.top(), 0, pixmapRect.bottom() ); if( smallShadow && orientation == Qt::Vertical ) { borderGradient.setColorAt( 0.8, Qt::transparent ); borderGradient.setColorAt( 1.0, alphaColor( light, 0.5 ) ); } else { borderGradient.setColorAt( 0.5, Qt::transparent ); borderGradient.setColorAt( 1.0, alphaColor( light, 0.6 ) ); } painter.setPen( QPen( borderGradient, 1.0 ) ); painter.setBrush( Qt::NoBrush ); painter.drawRoundedRect( QRectF( pixmapRect ).adjusted( 0.5, 0.5, -0.5, -0.5 ), radius+0.5, radius+0.5 ); painter.end(); TileSet tileSet( pixmap, 7, 7, 1, 1 ); _scrollHoleCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //________________________________________________________________________________________________________ TileSet StyleHelper::scrollHandle( const QColor& color, const QColor& glow, int size) { // get key Oxygen::Cache::Value cache( _scrollHandleCache.get( glow ) ); const quint64 key( ( colorKey(color) << 32 ) | size ); if( TileSet *cachedTileSet = cache->object( key ) ) { return *cachedTileSet; } QPixmap pixmap( highDpiPixmap( 2*size ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const int fixedSize( 14*devicePixelRatio( pixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); QPixmap shadowPixmap( highDpiPixmap( 10 ) ); { shadowPixmap.fill( Qt::transparent ); QPainter painter( &shadowPixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); // shadow/glow drawOuterGlow( painter, glow, 10 ); painter.end(); } TileSet( shadowPixmap, 4, 4, 1, 1 ).render( QRect( 0, 0, 14, 14 ), &painter, TileSet::Full ); // outline { const QColor mid( calcMidColor( color ) ); QLinearGradient linearGradient( 0, 3, 0, 11 ); linearGradient.setColorAt( 0, color ); linearGradient.setColorAt( 1, mid ); painter.setPen( Qt::NoPen ); painter.setBrush( linearGradient ); painter.drawRoundedRect( QRectF( 3, 3, 8, 8 ), 2.5, 2.5 ); } // contrast { const QColor light( calcLightColor( color ) ); QLinearGradient linearGradient( 0, 3, 0, 11 ); linearGradient.setColorAt( 0., alphaColor( light, 0.9 ) ); linearGradient.setColorAt( 0.5, alphaColor( light, 0.44 ) ); painter.setBrush( linearGradient ); painter.drawRoundedRect( QRectF( 3, 3, 8, 8 ), 2.5, 2.5 ); } painter.end(); // create tileset and return TileSet tileSet( pixmap, size-1, size, 1, 1 ); cache->insert( key, new TileSet( tileSet ) ); return tileSet; } //________________________________________________________________________________________________________ TileSet StyleHelper::slitFocused( const QColor& glow ) { const quint64 key( ( colorKey(glow) << 32 ) ); if( TileSet* cachedTileSet = _slitCache.object( key ) ) { return *cachedTileSet; } QPixmap pixmap( highDpiPixmap( 9 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( glow ); painter.drawRoundedRect( QRectF( 1.5, 1.5, 6, 6 ), 2.5, 2.5 ); painter.end(); TileSet tileSet( pixmap, 4, 4, 1, 1 ); _slitCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //____________________________________________________________________ TileSet StyleHelper::dockFrame( const QColor& top, const QColor& bottom ) { const quint64 key( colorKey(top) << 32 | colorKey(bottom) ); if( TileSet *cachedTileSet = _dockFrameCache.object( key ) ) { return *cachedTileSet; } int size( 13 ); QPixmap pm( size, size ); pm.fill( Qt::transparent ); QPainter painter( &pm ); painter.setRenderHints( QPainter::Antialiasing ); painter.setBrush( Qt::NoBrush ); const QColor lightTop = alphaColor( calcLightColor( top ), 0.5 ); const QColor lightBottom = alphaColor( calcLightColor( bottom ), 0.5 ); const QColor darkTop = alphaColor( calcDarkColor( top ), 0.6 ); const QColor darkBottom = alphaColor( calcDarkColor( bottom ), 0.6 ); // dark frame { QLinearGradient linearGradient( 0, 0.5, 0, size-1.5 ); linearGradient.setColorAt( 0.0, darkTop ); linearGradient.setColorAt( 1.0, darkBottom ); painter.setPen( QPen( linearGradient, 1 ) ); painter.drawRoundedRect( QRectF( 1.5, 0.5, size-3, size-2 ), 4, 4 ); } // bottom contrast { QLinearGradient linearGradient( 0, 0.5, 0, size-0.5 ); linearGradient.setColorAt( 0.0, Qt::transparent ); linearGradient.setColorAt( 1.0, lightBottom ); painter.setPen( QPen( linearGradient, 1.0 ) ); painter.drawRoundedRect( QRectF( 0.5, 0.5, size-1, size-1 ), 4.5, 4.5 ); } // top contrast { QLinearGradient linearGradient( 0, 1.5, 0, size-2.5 ); linearGradient.setColorAt( 0.0, lightTop ); linearGradient.setColorAt( 1.0, Qt::transparent ); painter.setPen( QPen( linearGradient, 1.0 ) ); painter.drawRoundedRect( QRectF( 2.5, 1.5, size-5, size-4 ), 3.5, 3.5 ); } painter.end(); TileSet tileSet( pm, (size-1)/2, (size-1)/2, 1, 1 ); _dockFrameCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //____________________________________________________________________ TileSet StyleHelper::selection( const QColor& color, int height, bool custom ) { const quint64 key( ( colorKey(color) << 32 ) | ( height << 1 ) | custom ); if( TileSet* cachedTileSet = _selectionCache.object( key ) ) { return *cachedTileSet; } const qreal rounding( 2.5 ); QPixmap pixmap( highDpiPixmap( 32+16, height ) ); pixmap.fill( Qt::transparent ); QRectF r( 0, 0, 32+16, height ); QPainter painter( &pixmap ); painter.setRenderHint( QPainter::Antialiasing ); // items with custom background brushes always have their background drawn // regardless of whether they are hovered or selected or neither so // the gradient effect needs to be more subtle { // fill const int lightenAmount( custom ? 110 : 130 ); QLinearGradient gradient( 0, 0, 0, r.bottom() ); gradient.setColorAt( 0, color.lighter( lightenAmount ) ); gradient.setColorAt( 1, color ); painter.setPen( Qt::NoPen ); painter.setBrush( gradient ); painter.drawRoundedRect( r, rounding+0.5, rounding+0.5 ); } { // contrast QLinearGradient gradient( 0, 0, 0, r.bottom() ); gradient.setColorAt( 0, color ); gradient.setColorAt( 1, Qt::transparent ); r.adjust( 0.5, 0.5, -0.5, -0.5 ); painter.setPen( QPen( color, 1 ) ); painter.setBrush( Qt::NoBrush ); painter.drawRoundedRect( r, rounding, rounding ); } TileSet tileSet( pixmap, 8, 0, 32, height ); _selectionCache.insert( key, new TileSet( tileSet ) ); return tileSet; } //________________________________________________________________________________________________________ void StyleHelper::drawInverseGlow( QPainter& painter, const QColor& color, int pad, int size, int rsize ) const { const QRectF r( pad, pad, size, size ); const qreal m( qreal( size )*0.5 ); const qreal width( 3.5 ); const qreal bias( _glowBias*7.0/rsize ); const qreal k0( ( m-width )/( m-bias ) ); QRadialGradient glowGradient( pad+m, pad+m, m-bias ); for ( int i = 0; i < 8; i++ ) { // inverse parabolic gradient qreal k1 = ( k0 * qreal( i ) + qreal( 8 - i ) ) * 0.125; qreal a = 1.0 - sqrt( i * 0.125 ); glowGradient.setColorAt( k1, alphaColor( color, a ) ); } glowGradient.setColorAt( k0, alphaColor( color, 0.0 ) ); painter.setBrush( glowGradient ); painter.drawEllipse( r ); } //________________________________________________________________________________________________________ bool StyleHelper::compositingActive( void ) const { #if OXYGEN_HAVE_X11 if( isX11() ) { // direct call to X xcb_get_selection_owner_cookie_t cookie( xcb_get_selection_owner( connection(), _compositingManagerAtom ) ); ScopedPointer reply( xcb_get_selection_owner_reply( connection(), cookie, nullptr ) ); return reply && reply->owner; } else { // use KWindowSystem return KWindowSystem::compositingActive(); } #else // use KWindowSystem return KWindowSystem::compositingActive(); #endif } //________________________________________________________________________________________________________ bool StyleHelper::hasDecoration( const QWidget* widget ) const { if( !widget->isTopLevel() ) return false; if( widget->windowFlags() & (Qt::X11BypassWindowManagerHint|Qt::FramelessWindowHint) ) { return false; } return true; } //________________________________________________________________________________________________________ TileSet StyleHelper::hole( const QColor& color, const QColor& glow, int size, StyleOptions options ) { // get key Oxygen::Cache::Value cache( _holeCache.get( glow ) ); const quint64 key( ( colorKey(color) << 32 ) | (size << 4) | options ); if( TileSet *cachedTileSet = cache->object( key ) ) { return *cachedTileSet; } // first create shadow const int shadowSize( (size*5)/7 ); QPixmap shadowPixmap( highDpiPixmap( shadowSize*2 ) ); // calc alpha channel and fade const int alpha( glow.isValid() ? glow.alpha():0 ); { shadowPixmap.fill( Qt::transparent ); QPainter painter( &shadowPixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const int fixedSize( 10*devicePixelRatio( shadowPixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); // fade-in shadow if( alpha < 255 ) { QColor shadowColor( calcShadowColor( color ) ); shadowColor.setAlpha( 255-alpha ); drawInverseShadow( painter, shadowColor, 1, 8, 0.0 ); } // fade-out glow if( alpha > 0 ) { drawInverseGlow( painter, glow, 1, 8, shadowSize ); } painter.end(); } // create pixmap QPixmap pixmap( highDpiPixmap( size*2 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const int fixedSize( 14*devicePixelRatio( pixmap ) ); painter.setWindow( 0, 0, fixedSize, fixedSize ); // hole mask painter.setCompositionMode( QPainter::CompositionMode_DestinationOut ); painter.setBrush( Qt::black ); painter.drawRoundedRect( QRectF( 1, 1, 12, 12 ), 2.5, 2.5 ); painter.setCompositionMode( QPainter::CompositionMode_SourceOver ); // render shadow TileSet( shadowPixmap, shadowSize, shadowSize, shadowSize, shadowSize, shadowSize-1, shadowSize, 2, 1 ). render( QRect( QPoint(0, 0), pixmap.size()/devicePixelRatio( pixmap ) ), &painter ); if( (options&HoleOutline) && alpha < 255 ) { QColor dark( calcDarkColor( color ) ); dark.setAlpha( 255 - alpha ); QLinearGradient blend( 0, 0, 0, 14 ); blend.setColorAt( 0, Qt::transparent ); blend.setColorAt( 0.8, dark ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( blend, 1 ) ); painter.drawRoundedRect( QRectF( 1.5, 1.5, 11, 11 ), 3.0, 3.0 ); painter.setPen( Qt::NoPen ); } if( options&HoleContrast ) { QColor light( calcLightColor( color ) ); QLinearGradient blend( 0, 0, 0, 18 ); blend.setColorAt( 0.5, Qt::transparent ); blend.setColorAt( 1.0, light ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( blend, 1 ) ); painter.drawRoundedRect( QRectF( 0.5, 0.5, 13, 13 ), 4.0, 4.0 ); painter.setPen( Qt::NoPen ); } painter.end(); // create tileset and return TileSet tileSet( pixmap, size, size, size, size, size-1, size, 2, 1 ); cache->insert( key, new TileSet( tileSet ) ); return tileSet; } //______________________________________________________________________________________ void StyleHelper::drawSlab( QPainter& painter, const QColor& color, qreal shade ) { const QColor light( KColorUtils::shade( calcLightColor( color ), shade ) ); const QColor base( alphaColor( light, 0.85 ) ); const QColor dark( KColorUtils::shade( calcDarkColor( color ), shade ) ); // bevel, part 1 painter.save(); const qreal y( KColorUtils::luma( base ) ); const qreal yl( KColorUtils::luma( light ) ); const qreal yd( KColorUtils::luma( dark ) ); QLinearGradient bevelGradient1( 0, 7, 0, 11 ); bevelGradient1.setColorAt( 0.0, light ); if ( y < yl && y > yd ) { // no middle when color is very light/dark bevelGradient1.setColorAt( 0.5, base ); } bevelGradient1.setColorAt( 0.9, base ); painter.setBrush( bevelGradient1 ); painter.drawRoundedRect( QRectF( 3.0,3.0,8.0,8.0 ), 3.5, 3.5 ); // bevel, part 2 if ( _slabThickness > 0.0 ) { QLinearGradient bevelGradient2( 0, 6, 0, 19 ); bevelGradient2.setColorAt( 0.0, light ); bevelGradient2.setColorAt( 0.9, base ); painter.setBrush( bevelGradient2 ); painter.drawEllipse( QRectF( 3.6,3.6,6.8,6.8 ) ); } // inside mask painter.setCompositionMode( QPainter::CompositionMode_DestinationOut ); painter.setBrush( Qt::black ); const qreal ic( 3.6 + 0.5*_slabThickness ); const qreal is( 14.0 - 2.0*ic ); painter.drawEllipse( QRectF( ic, ic, is, is ) ); painter.restore(); } //__________________________________________________________________________________________________________ void StyleHelper::drawRoundSlab( QPainter& painter, const QColor& color, qreal shade ) { painter.save(); // colors const QColor base( KColorUtils::shade( color, shade ) ); const QColor light( KColorUtils::shade( calcLightColor( color ), shade ) ); // bevel, part 1 QLinearGradient bevelGradient1( 0, 10, 0, 18 ); bevelGradient1.setColorAt( 0.0, light ); bevelGradient1.setColorAt( 0.9, alphaColor( light, 0.85 ) ); painter.setBrush( bevelGradient1 ); painter.drawEllipse( QRectF( 3.0,3.0,15.0,15.0 ) ); // bevel, part 2 if ( _slabThickness > 0.0 ) { QLinearGradient bevelGradient2( 0, 7, 0, 28 ); bevelGradient2.setColorAt( 0.0, light ); bevelGradient2.setColorAt( 0.9, base ); painter.setBrush( bevelGradient2 ); painter.drawEllipse( QRectF( 3.6,3.6,13.8,13.8 ) ); } // inside QLinearGradient innerGradient( 0, -17, 0, 20 ); innerGradient.setColorAt( 0, light ); innerGradient.setColorAt( 1, base ); painter.setBrush( innerGradient ); const qreal ic( 3.6 + _slabThickness ); const qreal is( 21.0 - 2.0*ic ); painter.drawEllipse( QRectF( ic, ic, is, is ) ); painter.restore(); } //__________________________________________________________________________________________________________ void StyleHelper::drawSliderSlab( QPainter& painter, const QColor& color, bool sunken, qreal shade ) { painter.save(); const QColor light( KColorUtils::shade( calcLightColor(color), shade ) ); const QColor dark( KColorUtils::shade( calcDarkColor(color), shade ) ); painter.setPen(Qt::NoPen); { //plain background QLinearGradient linearGradient( 0, 3, 0, 21 ); linearGradient.setColorAt( 0, light ); linearGradient.setColorAt( 1, dark ); const QRectF r( 3, 3, 15, 15 ); painter.setBrush( linearGradient ); painter.drawEllipse( r ); } if( sunken ) { //plain background QLinearGradient linearGradient( 0, 3, 0, 21 ); linearGradient.setColorAt( 0, dark ); linearGradient.setColorAt( 1, light ); const QRectF r( 5, 5, 11, 11 ); painter.setBrush( linearGradient ); painter.drawEllipse( r ); } { // outline circle const qreal penWidth( 1 ); QLinearGradient linearGradient( 0, 3, 0, 30 ); linearGradient.setColorAt( 0, light ); linearGradient.setColorAt( 1, dark ); const QRectF r( 3.5, 3.5, 14, 14 ); painter.setPen( QPen( linearGradient, penWidth ) ); painter.setBrush( Qt::NoBrush ); painter.drawEllipse( r ); } painter.restore(); } //______________________________________________________________________________ void StyleHelper::init( void ) { _useBackgroundGradient = true; #if OXYGEN_HAVE_X11 if( isX11() ) { // create compositing screen const QString atomName( QStringLiteral( "_NET_WM_CM_S%1" ).arg( QX11Info::appScreen() ) ); _compositingManagerAtom = createAtom( atomName ); } #endif } } diff --git a/kstyle/oxygenstylehelper.h b/kstyle/oxygenstylehelper.h index 677e3707..286058b3 100644 --- a/kstyle/oxygenstylehelper.h +++ b/kstyle/oxygenstylehelper.h @@ -1,305 +1,300 @@ #ifndef oxygen_style_helper_h #define oxygen_style_helper_h /* * Copyright 2010 Hugo Pereira Da Costa * Copyright 2008 Long Huynh Huu * Copyright 2007 Matthew Woehlke * Copyright 2007 Casper Boemann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "oxygenhelper.h" #include "oxygen.h" #include #if OXYGEN_HAVE_X11 #include #endif //* helper class /** contains utility functions used at multiple places in oxygen style */ namespace Oxygen { class StyleHelper : public Helper { public: //* constructor explicit StyleHelper( KSharedConfigPtr config ); - #if OXYGEN_USE_KDE4 - //* constructor - explicit StyleHelper( const QByteArray& ); - #endif - //* destructor //* clear cache void invalidateCaches() override; //* update maximum cache size void setMaxCacheSize( int ) override; //* background gradient void setUseBackgroundGradient( bool value ) { _useBackgroundGradient = value; } //* render window background using a given color as a reference /** For the widget style, both the gradient and the background pixmap are rendered in the same method. All the actual rendering is performed by the base class */ using Helper::renderWindowBackground; void renderWindowBackground( QPainter*, const QRect&, const QWidget*, const QColor&, int y_shift=-23 ) override; //* set background gradient hint to widget void setHasBackgroundGradient( WId, bool ) const override; // render menu background void renderMenuBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QPalette& pal ) { renderMenuBackground( p, clipRect, widget, pal.color( widget->window()->backgroundRole() ) ); } // render menu background void renderMenuBackground( QPainter*, const QRect&, const QWidget*, const QColor& ); //*@name color utilities //@{ //* glow color for buttons (mouse-over takes precedence over focus) QColor buttonGlowColor( const QPalette& palette, StyleOptions options, qreal opacity, AnimationMode mode ) const { return buttonGlowColor( palette.currentColorGroup(), options, opacity, mode ); } //* glow color for frames (focus takes precedence over mouse-over) QColor frameGlowColor( const QPalette& palette, StyleOptions options, qreal opacity, AnimationMode mode ) const { return frameGlowColor( palette.currentColorGroup(), options, opacity, mode ); } //* glow color for arrows (mouse-over takes precedence over focus) QColor arrowColor( const QPalette& palette, StyleOptions options, qreal opacity, AnimationMode mode ) const; //* glow color for buttons (mouse-over takes precedence over focus) QColor buttonGlowColor( QPalette::ColorGroup, StyleOptions, qreal, AnimationMode ) const; //* glow color for frames (focus takes precedence over mouse-over) QColor frameGlowColor( QPalette::ColorGroup, StyleOptions, qreal, AnimationMode ) const; //* returns menu background color matching position in a given menu widget QColor menuBackgroundColor( const QColor& color, const QWidget* w, const QPoint& point ) { if( !( w && w->window() ) || checkAutoFillBackground( w ) ) return color; else return menuBackgroundColor( color, w->window()->height(), w->mapTo( w->window(), point ).y() ); } //* returns menu background color matching position in a menu widget of given height QColor menuBackgroundColor( const QColor& color, int height, int y ) { return backgroundColor( color, qMin( qreal( 1.0 ), qreal( y )/qMin( 200, 3*height/4 ) ) ); } //* color inline QColor calcMidColor( const QColor& color ); //* merge active and inactive palettes based on ratio, for smooth enable state change transition QPalette disabledPalette( const QPalette&, qreal ratio ) const; //@} //* overloaded window decoration buttons for MDI windows QPixmap dockWidgetButton( const QColor& color, bool pressed, int size = 21 ); //* round corners( used for Menus, combobox drop-down, detached toolbars and dockwidgets TileSet roundCorner( const QColor&, int size = 5 ); //* groupbox background TileSet slope( const QColor&, qreal shade, int size = TileSet::DefaultSize ); //*@name slabs //@{ //* inverse (inner-hole) shadow /** this method must be public because it is used directly by OxygenStyle to draw dials */ void drawInverseShadow( QPainter&, const QColor&, int pad, int size, qreal fuzz ) const; //* fill a slab of given size with brush set on painter void fillSlab( QPainter&, const QRect&, int size = TileSet::DefaultSize ) const; //* linear gradient used to fill buttons void fillButtonSlab( QPainter&, const QRect&, const QColor&, bool sunken ); //* default slab TileSet slab( const QColor& color, qreal shade, int size = TileSet::DefaultSize ) { return slab( color, QColor(), shade, size ); } //* default slab (with glow) TileSet slab( const QColor&, const QColor& glow, qreal shade, int size = TileSet::DefaultSize ); //* sunken slab TileSet slabSunken( const QColor&, int size = TileSet::DefaultSize ); //* progressbar TileSet progressBarIndicator( const QPalette&, int ); //* dial QPixmap dialSlab( const QColor& color, qreal shade, int size = TileSet::DefaultSize ) { return dialSlab( color, QColor(), shade, size ); } //* dial QPixmap dialSlab( const QColor&, const QColor&, qreal shade, int size = TileSet::DefaultSize ); // round slabs QPixmap roundSlab( const QColor& color, qreal shade, int size = TileSet::DefaultSize ) { return roundSlab( color, QColor(), shade, size ); } // round slab QPixmap roundSlab( const QColor&, const QColor& glow, qreal shade, int size = TileSet::DefaultSize ); //* slider slab QPixmap sliderSlab( const QColor&, const QColor& glow, bool sunken, qreal shade, int size = TileSet::DefaultSize ); //@} //* debug frame void renderDebugFrame( QPainter*, const QRect& ) const; //*@name holes //@{ void fillHole( QPainter&, const QRect&, int offset = 2 ) const; //* generic hole void renderHole( QPainter *painter, const QColor& color, const QRect &rect, StyleOptions options = {}, TileSet::Tiles tiles = TileSet::Ring ) { renderHole( painter, color, rect, options, -1, Oxygen::AnimationNone, tiles ); } //* generic hole (with animated glow) void renderHole( QPainter*, const QColor&, const QRect&, StyleOptions, qreal, Oxygen::AnimationMode, TileSet::Tiles = TileSet::Ring ); TileSet holeFlat( const QColor&, qreal shade, bool fill = true, int size = TileSet::DefaultSize ); //* scrollbar hole TileSet scrollHole( const QColor&, Qt::Orientation orientation, bool smallShadow = false ); //* scrollbar handle TileSet scrollHandle( const QColor&, const QColor&, int size = TileSet::DefaultSize ); //@} //* focus rect for flat toolbuttons TileSet slitFocused( const QColor& ); //* dock frame TileSet dockFrame( const QColor&, const QColor& ); //* selection TileSet selection( const QColor&, int height, bool custom ); //* inverse glow /** this method must be public because it is used directly by OxygenStyle to draw dials */ void drawInverseGlow( QPainter&, const QColor&, int pad, int size, int rsize ) const; //*@name utility functions //* returns true if compositing is active bool compositingActive( void ) const; //* returns true if a given widget supports alpha channel inline bool hasAlphaChannel( const QWidget* ) const; //* returns true if given widget will get a decoration bool hasDecoration( const QWidget* ) const; //@} private: //*@name holes //@{ //* holes TileSet hole( const QColor& color, int size = TileSet::DefaultSize, StyleOptions options = {} ) { return hole( color, QColor(), size, options ); } //* holes TileSet hole( const QColor&, const QColor& glow, int size = TileSet::DefaultSize, StyleOptions = {} ); //@} //* generic slab painting (to be stored in tilesets) void drawSlab( QPainter&, const QColor&, qreal shade ); // round slabs void drawRoundSlab( QPainter&, const QColor&, qreal ); // slider slabs void drawSliderSlab( QPainter&, const QColor&, bool sunken, qreal ); //* initialize void init( void ); //* background grandient bool _useBackgroundGradient; Cache _dialSlabCache; Cache _roundSlabCache; Cache _sliderSlabCache; Cache _holeCache; Cache _scrollHandleCache; Cache _slabCache; //* mid color cache ColorCache _midColorCache; //* dock button cache PixmapCache _dockWidgetButtonCache; using TileSetCache = BaseCache; TileSetCache _slabSunkenCache; TileSetCache _cornerCache; TileSetCache _holeFlatCache; TileSetCache _slopeCache; TileSetCache _slitCache; TileSetCache _dockFrameCache; TileSetCache _scrollHoleCache; TileSetCache _selectionCache; TileSetCache _progressBarCache; #if OXYGEN_HAVE_X11 //* atom used for compositing manager xcb_atom_t _compositingManagerAtom; #endif }; //____________________________________________________________________ QColor StyleHelper::calcMidColor( const QColor& color ) { const quint64 key( color.rgba() ); if( QColor* cachedColor = _midColorCache.object( key ) ) { return *cachedColor; } QColor out = KColorScheme::shade( color, KColorScheme::MidShade, _contrast - 1.0 ); _midColorCache.insert( key, new QColor( out ) ); return out; } //____________________________________________________________________ bool StyleHelper::hasAlphaChannel( const QWidget* widget ) const { return compositingActive() && widget && widget->testAttribute( Qt::WA_TranslucentBackground ); } } #endif diff --git a/kstyle/oxygenstyleplugin.cpp b/kstyle/oxygenstyleplugin.cpp index 015140bb..ec288f41 100644 --- a/kstyle/oxygenstyleplugin.cpp +++ b/kstyle/oxygenstyleplugin.cpp @@ -1,52 +1,48 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "oxygenstyleplugin.h" #include "oxygenstyle.h" #include -#if QT_VERSION < 0x050000 -Q_EXPORT_PLUGIN2( oxygen-qt, Oxygen::StylePlugin ) -#endif - namespace Oxygen { //_________________________________________________ QStyle* StylePlugin::create( const QString &key ) { if( key.toLower() == QStringLiteral( "oxygen" ) ) { return new Style; } return nullptr; } //_________________________________________________ StylePlugin::~StylePlugin() { } //_________________________________________________ QStringList StylePlugin::keys() const { return QStringList( QStringLiteral( "Oxygen" ) ); } } diff --git a/kstyle/oxygenstyleplugin.h b/kstyle/oxygenstyleplugin.h index d9cf8021..c2ba6998 100644 --- a/kstyle/oxygenstyleplugin.h +++ b/kstyle/oxygenstyleplugin.h @@ -1,57 +1,55 @@ #ifndef oxygenstyleplugin_h #define oxygenstyleplugin_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include namespace Oxygen { class StylePlugin : public QStylePlugin { Q_OBJECT - #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "oxygen.json" ) - #endif public: //* constructor explicit StylePlugin(QObject *parent = 0): QStylePlugin(parent) {} //* destructor ~StylePlugin(); //* returns list of valid keys QStringList keys() const; //* create style QStyle* create( const QString& ) override; }; } #endif diff --git a/kstyle/oxygenwindowmanager.cpp b/kstyle/oxygenwindowmanager.cpp index 1aa9ef05..234d6e9a 100644 --- a/kstyle/oxygenwindowmanager.cpp +++ b/kstyle/oxygenwindowmanager.cpp @@ -1,982 +1,922 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ ////////////////////////////////////////////////////////////////////////////// // oxygenwindowmanager.cpp // pass some window mouse press/release/move event actions to window manager // ------------------- // // Copyright (c) 2014 Hugo Pereira Da Costa // // Largely inspired from BeSpin style // Copyright (C) 2007 Thomas Luebking // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygenwindowmanager.h" #include "oxygenpropertynames.h" #include "oxygenstyleconfigdata.h" #include "oxygenhelper.h" #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include #include #include #include #include #include #include #include #include #include - -#if QT_VERSION >= 0x050300 // needed to deal with device pixel ratio #include -#endif #if OXYGEN_HAVE_X11 #include #include -#if OXYGEN_USE_KDE4 -#include -#else #include -#endif - -#endif -#if !OXYGEN_USE_KDE4 -#include -#include #endif #if OXYGEN_HAVE_KWAYLAND #include #include #include #include #include #endif namespace Oxygen { //* provide application-wise event filter /** it us used to unlock dragging and make sure event look is properly restored after a drag has occurred */ class AppEventFilter: public QObject { public: //* constructor explicit AppEventFilter( WindowManager* parent ): QObject( parent ), _parent( parent ) {} //* event filter bool eventFilter( QObject* object, QEvent* event ) override { if( event->type() == QEvent::MouseButtonRelease ) { // stop drag timer if( _parent->_dragTimer.isActive() ) { _parent->resetDrag(); } // unlock if( _parent->isLocked() ) { _parent->setLocked( false ); } } if( !_parent->enabled() ) return false; /* if a drag is in progress, the widget will not receive any event we trigger on the first MouseMove or MousePress events that are received by any widget in the application to detect that the drag is finished */ if( _parent->useWMMoveResize() && _parent->_dragInProgress && _parent->_target && ( event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress ) ) { return appMouseEvent( object, event ); } return false; } protected: //* application-wise event. /** needed to catch end of XMoveResize events */ bool appMouseEvent( QObject*, QEvent* event ) { - #if OXYGEN_USE_KDE4 - // store target window (see later) - QWidget* window( _parent->_target.data()->window() ); - #else Q_UNUSED( event ); - #endif /* post some mouseRelease event to the target, in order to counter balance the mouse press that triggered the drag. Note that it triggers a resetDrag */ QMouseEvent mouseEvent( QEvent::MouseButtonRelease, _parent->_dragPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier ); qApp->sendEvent( _parent->_target.data(), &mouseEvent ); - #if OXYGEN_USE_KDE4 - if( event->type() == QEvent::MouseMove ) - { - /* - HACK: quickly move the main cursor out of the window and back - this is needed to get the focus right for the window children - the origin of this issue is unknown at the moment. - This apparently got fixed with qt5 - */ - const QPoint cursor = QCursor::pos(); - QCursor::setPos(window->mapToGlobal( window->rect().topRight() ) + QPoint(1, 0) ); - QCursor::setPos(cursor); - - } - #endif - return false; } private: //* parent WindowManager* _parent; }; //_____________________________________________________________ WindowManager::WindowManager( QObject* parent ): QObject( parent ), _enabled( true ), _useWMMoveResize( true ), _dragMode( StyleConfigData::WD_FULL ), _dragDistance( QApplication::startDragDistance() ), _dragDelay( QApplication::startDragTime() ), _dragAboutToStart( false ), _dragInProgress( false ), _locked( false ), _cursorOverride( false ) #if OXYGEN_HAVE_KWAYLAND , _seat( Q_NULLPTR ) , _pointer( Q_NULLPTR ) , _waylandSerial( 0 ) #endif { // install application wise event filter _appEventFilter = new AppEventFilter( this ); qApp->installEventFilter( _appEventFilter ); } //_____________________________________________________________ void WindowManager::initialize( void ) { setEnabled( StyleConfigData::windowDragMode() != StyleConfigData::WD_NONE ); setDragMode( StyleConfigData::windowDragMode() ); setUseWMMoveResize( StyleConfigData::useWMMoveResize() ); setDragDistance( QApplication::startDragDistance() ); setDragDelay( QApplication::startDragTime() ); initializeWhiteList(); initializeBlackList(); initializeWayland(); } //_______________________________________________________ void WindowManager::initializeWayland() { #if OXYGEN_HAVE_KWAYLAND if( !Helper::isWayland() ) return; if( _seat ) { // already initialized return; } using namespace KWayland::Client; auto connection = ConnectionThread::fromApplication( this ); if( !connection ) { return; } Registry *registry = new Registry( this ); registry->create( connection ); connect(registry, &Registry::interfacesAnnounced, this, [registry, this] { const auto interface = registry->interface( Registry::Interface::Seat ); if( interface.name != 0 ) { _seat = registry->createSeat( interface.name, interface.version, this ); connect(_seat, &Seat::hasPointerChanged, this, &WindowManager::waylandHasPointerChanged); } } ); registry->setup(); connection->roundtrip(); #endif } //_______________________________________________________ void WindowManager::waylandHasPointerChanged(bool hasPointer) { #if OXYGEN_HAVE_KWAYLAND Q_ASSERT( _seat ); if( hasPointer ) { if( !_pointer ) { _pointer = _seat->createPointer(this); connect(_pointer, &KWayland::Client::Pointer::buttonStateChanged, this, [this] (quint32 serial) { _waylandSerial = serial; } ); } } else { delete _pointer; _pointer = nullptr; } #else Q_UNUSED( hasPointer ); #endif } //_____________________________________________________________ void WindowManager::registerWidget( QWidget* widget ) { if( isBlackListed( widget ) || isDragable( widget ) ) { /* install filter for dragable widgets. also install filter for blacklisted widgets to be able to catch the relevant events and prevent the drag to happen */ widget->removeEventFilter( this ); widget->installEventFilter( this ); } } -#if !OXYGEN_USE_KDE4 void WindowManager::registerQuickItem( QQuickItem* item ) { if ( !item ) return; QQuickWindow *window = item->window(); if (window) { QQuickItem *contentItem = window->contentItem(); contentItem->setAcceptedMouseButtons( Qt::LeftButton ); contentItem->removeEventFilter( this ); contentItem->installEventFilter( this ); } } -#endif //_____________________________________________________________ void WindowManager::unregisterWidget( QWidget* widget ) { if( widget ) { widget->removeEventFilter( this ); } } //_____________________________________________________________ void WindowManager::initializeWhiteList( void ) { _whiteList.clear(); // add user specified whitelisted classnames _whiteList.insert( ExceptionId( QStringLiteral( "MplayerWindow" ) ) ); _whiteList.insert( ExceptionId( QStringLiteral( "ViewSliders@kmix" ) ) ); _whiteList.insert( ExceptionId( QStringLiteral( "Sidebar_Widget@konqueror" ) ) ); foreach( const QString& exception, StyleConfigData::windowDragWhiteList() ) { ExceptionId id( exception ); if( !id.className().isEmpty() ) { _whiteList.insert( ExceptionId( exception ) ); } } } //_____________________________________________________________ void WindowManager::initializeBlackList( void ) { _blackList.clear(); _blackList.insert( ExceptionId( QStringLiteral( "CustomTrackView@kdenlive" ) ) ); _blackList.insert( ExceptionId( QStringLiteral( "MuseScore" ) ) ); _blackList.insert( ExceptionId( QStringLiteral( "KGameCanvasWidget" ) ) ); foreach( const QString& exception, StyleConfigData::windowDragBlackList() ) { ExceptionId id( exception ); if( !id.className().isEmpty() ) { _blackList.insert( ExceptionId( exception ) ); } } } //_____________________________________________________________ bool WindowManager::eventFilter( QObject* object, QEvent* event ) { if( !enabled() ) return false; switch ( event->type() ) { case QEvent::MouseButtonPress: return mousePressEvent( object, event ); break; case QEvent::MouseMove: if ( object == _target.data() -#if !OXYGEN_USE_KDE4 || object == _quickTarget.data() -#endif ) return mouseMoveEvent( object, event ); break; case QEvent::MouseButtonRelease: if ( _target -#if !OXYGEN_USE_KDE4 || _quickTarget -#endif ) return mouseReleaseEvent( object, event ); break; default: break; } return false; } //_____________________________________________________________ void WindowManager::timerEvent( QTimerEvent* event ) { if( event->timerId() == _dragTimer.timerId() ) { _dragTimer.stop(); -#if OXYGEN_USE_KDE4 - if( _target ) - { startDrag( _target.data()->window(), _globalDragPoint ); } -#else if( _target ) { startDrag( _target.data()->window()->windowHandle(), _globalDragPoint ); } else if( _quickTarget ) { startDrag( _quickTarget.data()->window(), _globalDragPoint ); } -#endif } else { return QObject::timerEvent( event ); } } //_____________________________________________________________ bool WindowManager::mousePressEvent( QObject* object, QEvent* event ) { // cast event and check buttons/modifiers QMouseEvent *mouseEvent = static_cast( event ); if( !( mouseEvent->modifiers() == Qt::NoModifier && mouseEvent->button() == Qt::LeftButton ) ) { return false; } -#if !OXYGEN_USE_KDE4 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { return false; } -#endif // check lock if( isLocked() ) return false; else setLocked( true ); -#if !OXYGEN_USE_KDE4 // check QQuickItem - we can immediately start drag, because QQuickWindow's contentItem // only receives mouse events that weren't handled by children if ( QQuickItem *item = qobject_cast( object ) ) { _quickTarget = item; _dragPoint = mouseEvent->pos(); _globalDragPoint = mouseEvent->globalPos(); if( _dragTimer.isActive() ) _dragTimer.stop(); _dragTimer.start( _dragDelay, this ); return true; } -#endif // cast to widget QWidget *widget = static_cast( object ); // check if widget can be dragged from current position if( isBlackListed( widget ) || !canDrag( widget ) ) return false; // retrieve widget's child at event position QPoint position( mouseEvent->pos() ); QWidget* child = widget->childAt( position ); if( !canDrag( widget, child, position ) ) return false; // save target and drag point _target = widget; _dragPoint = position; _globalDragPoint = mouseEvent->globalPos(); _dragAboutToStart = true; // send a move event to the current child with same position // if received, it is caught to actually start the drag QPoint localPoint( _dragPoint ); if( child ) localPoint = child->mapFrom( widget, localPoint ); else child = widget; QMouseEvent localMouseEvent( QEvent::MouseMove, localPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier ); qApp->sendEvent( child, &localMouseEvent ); // never eat event return false; } //_____________________________________________________________ bool WindowManager::mouseMoveEvent( QObject* object, QEvent* event ) { Q_UNUSED( object ); QMouseEvent *mouseEvent = static_cast( event ); -#if !OXYGEN_USE_KDE4 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { return false; } -#endif // stop timer if( _dragTimer.isActive() ) _dragTimer.stop(); // cast event and check drag distance if( !_dragInProgress ) { if( _dragAboutToStart ) { if( mouseEvent->pos() == _dragPoint ) { // start timer, _dragAboutToStart = false; if( _dragTimer.isActive() ) _dragTimer.stop(); _dragTimer.start( _dragDelay, this ); } else resetDrag(); } else if( QPoint( mouseEvent->globalPos() - _globalDragPoint ).manhattanLength() >= _dragDistance ) { _dragTimer.start( 0, this ); } return true; } else if( !useWMMoveResize() && _target ) { // use QWidget::move for the grabbing /* this works only if the sending object and the target are identical */ QWidget* window( _target.data()->window() ); window->move( window->pos() + mouseEvent->pos() - _dragPoint ); return true; } else return false; } //_____________________________________________________________ bool WindowManager::mouseReleaseEvent( QObject* object, QEvent* event ) { Q_UNUSED( object ); Q_UNUSED( event ); resetDrag(); return false; } //_____________________________________________________________ bool WindowManager::isDragable( QWidget* widget ) { // check widget if( !widget ) return false; // accepted default types if( ( qobject_cast( widget ) && widget->isWindow() ) || ( qobject_cast( widget ) && widget->isWindow() ) || qobject_cast( widget ) ) { return true; } // more accepted types, provided they are not dock widget titles if( ( qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) ) && !isDockWidgetTitle( widget ) ) { return true; } if( widget->inherits( "KScreenSaver" ) && widget->inherits( "KCModule" ) ) { return true; } if( isWhiteListed( widget ) ) { return true; } // flat toolbuttons if( QToolButton* toolButton = qobject_cast( widget ) ) { if( toolButton->autoRaise() ) return true; } // viewports /* one needs to check that 1/ the widget parent is a scrollarea 2/ it matches its parent viewport 3/ the parent is not blacklisted */ if( QListView* listView = qobject_cast( widget->parentWidget() ) ) { if( listView->viewport() == widget && !isBlackListed( listView ) ) return true; } if( QTreeView* treeView = qobject_cast( widget->parentWidget() ) ) { if( treeView->viewport() == widget && !isBlackListed( treeView ) ) return true; } /* catch labels in status bars. this is because of kstatusbar who captures buttonPress/release events */ if( QLabel* label = qobject_cast( widget ) ) { if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false; QWidget* parent = label->parentWidget(); while( parent ) { if( qobject_cast( parent ) ) return true; parent = parent->parentWidget(); } } return false; } //_____________________________________________________________ bool WindowManager::isBlackListed( QWidget* widget ) { // check against noAnimations propery QVariant propertyValue( widget->property( PropertyNames::noWindowGrab ) ); if( propertyValue.isValid() && propertyValue.toBool() ) return true; // list-based blacklisted widgets QString appName( qApp->applicationName() ); foreach( const ExceptionId& id, _blackList ) { if( !id.appName().isEmpty() && id.appName() != appName ) continue; if( id.className() == QStringLiteral( "*" ) && !id.appName().isEmpty() ) { // if application name matches and all classes are selected // disable the grabbing entirely setEnabled( false ); return true; } if( widget->inherits( id.className().toLatin1().data() ) ) return true; } return false; } //_____________________________________________________________ bool WindowManager::isWhiteListed( QWidget* widget ) const { QString appName( qApp->applicationName() ); foreach( const ExceptionId& id, _whiteList ) { if( !id.appName().isEmpty() && id.appName() != appName ) continue; if( widget->inherits( id.className().toLatin1().data() ) ) return true; } return false; } //_____________________________________________________________ bool WindowManager::canDrag( QWidget* widget ) { // check if enabled if( !enabled() ) return false; // assume isDragable widget is already passed // check some special cases where drag should not be effective // check mouse grabber if( QWidget::mouseGrabber() ) return false; /* check cursor shape. Assume that a changed cursor means that some action is in progress and should prevent the drag */ if( widget->cursor().shape() != Qt::ArrowCursor ) return false; // accept return true; } //_____________________________________________________________ bool WindowManager::canDrag( QWidget* widget, QWidget* child, const QPoint& position ) { // retrieve child at given position and check cursor again if( child && child->cursor().shape() != Qt::ArrowCursor ) return false; /* check against children from which drag should never be enabled, even if mousePress/Move has been passed to the parent */ if( child && ( qobject_cast(child ) || qobject_cast( child ) || qobject_cast( child ) ) ) { return false; } // tool buttons if( QToolButton* toolButton = qobject_cast( widget ) ) { if( dragMode() == StyleConfigData::WD_MINIMAL && !qobject_cast(widget->parentWidget() ) ) return false; return toolButton->autoRaise() && !toolButton->isEnabled(); } // check menubar if( QMenuBar* menuBar = qobject_cast( widget ) ) { // do not drag from menubars embedded in Mdi windows if( findParent( widget ) ) return false; // check if there is an active action if( menuBar->activeAction() && menuBar->activeAction()->isEnabled() ) return false; // check if action at position exists and is enabled if( QAction* action = menuBar->actionAt( position ) ) { if( action->isSeparator() ) return true; if( action->isEnabled() ) return false; } // return true in all other cases return true; } /* in MINIMAL mode, anything that has not been already accepted and does not come from a toolbar is rejected */ if( dragMode() == StyleConfigData::WD_MINIMAL ) { if( qobject_cast( widget ) ) return true; else return false; } /* following checks are relevant only for WD_FULL mode */ // tabbar. Make sure no tab is under the cursor if( QTabBar* tabBar = qobject_cast( widget ) ) { return tabBar->tabAt( position ) == -1; } /* check groupboxes prevent drag if unchecking grouboxes */ if( QGroupBox *groupBox = qobject_cast( widget ) ) { // non checkable group boxes are always ok if( !groupBox->isCheckable() ) return true; // gather options to retrieve checkbox subcontrol rect QStyleOptionGroupBox opt; opt.initFrom( groupBox ); if( groupBox->isFlat() ) opt.features |= QStyleOptionFrameV2::Flat; opt.lineWidth = 1; opt.midLineWidth = 0; opt.text = groupBox->title(); opt.textAlignment = groupBox->alignment(); opt.subControls = (QStyle::SC_GroupBoxFrame | QStyle::SC_GroupBoxCheckBox); if (!groupBox->title().isEmpty()) opt.subControls |= QStyle::SC_GroupBoxLabel; opt.state |= (groupBox->isChecked() ? QStyle::State_On : QStyle::State_Off); // check against groupbox checkbox if( groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, groupBox ).contains( position ) ) { return false; } // check against groupbox label if( !groupBox->title().isEmpty() && groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, groupBox ).contains( position ) ) { return false; } return true; } // labels if( QLabel* label = qobject_cast( widget ) ) { if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false; } // abstract item views QAbstractItemView* itemView( nullptr ); if( ( itemView = qobject_cast( widget->parentWidget() ) ) || ( itemView = qobject_cast( widget->parentWidget() ) ) ) { if( widget == itemView->viewport() ) { // QListView if( itemView->frameShape() != QFrame::NoFrame ) return false; else if( itemView->selectionMode() != QAbstractItemView::NoSelection && itemView->selectionMode() != QAbstractItemView::SingleSelection && itemView->model() && itemView->model()->rowCount() ) return false; else if( itemView->model() && itemView->indexAt( position ).isValid() ) return false; } } else if( ( itemView = qobject_cast( widget->parentWidget() ) ) ) { if( widget == itemView->viewport() ) { // QAbstractItemView if( itemView->frameShape() != QFrame::NoFrame ) return false; else if( itemView->indexAt( position ).isValid() ) return false; } } else if( QGraphicsView* graphicsView = qobject_cast( widget->parentWidget() ) ) { if( widget == graphicsView->viewport() ) { // QGraphicsView if( graphicsView->frameShape() != QFrame::NoFrame ) return false; else if( graphicsView->dragMode() != QGraphicsView::NoDrag ) return false; else if( graphicsView->itemAt( position ) ) return false; } } return true; } //____________________________________________________________ void WindowManager::resetDrag( void ) { if( (!useWMMoveResize() ) && _target && _cursorOverride ) { qApp->restoreOverrideCursor(); _cursorOverride = false; } _target.clear(); -#if !OXYGEN_USE_KDE4 _quickTarget.clear(); -#endif if( _dragTimer.isActive() ) _dragTimer.stop(); _dragPoint = QPoint(); _globalDragPoint = QPoint(); _dragAboutToStart = false; _dragInProgress = false; } //____________________________________________________________ - void WindowManager::startDrag( Window* window, const QPoint& position ) + void WindowManager::startDrag( QWindow* window, const QPoint& position ) { if( !( enabled() && window ) ) return; if( QWidget::mouseGrabber() ) return; // ungrab pointer if( useWMMoveResize() ) { if( Helper::isX11() ) { startDragX11( window, position ); } else if( Helper::isWayland() ) { startDragWayland( window, position ); } } else if( !_cursorOverride ) { qApp->setOverrideCursor( Qt::SizeAllCursor ); _cursorOverride = true; } _dragInProgress = true; return; } //_______________________________________________________ - void WindowManager::startDragX11( Window* window, const QPoint& position ) + void WindowManager::startDragX11( QWindow* window, const QPoint& position ) { #if OXYGEN_HAVE_X11 // connection xcb_connection_t* connection( Helper::connection() ); - #if QT_VERSION >= 0x050300 const qreal dpiRatio = qApp->devicePixelRatio(); - #else - const qreal dpiRatio = 1; - #endif - - #if OXYGEN_USE_KDE4 - Display* net_connection = QX11Info::display(); - #else - xcb_connection_t* net_connection = connection; - #endif xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME ); - NETRootInfo( net_connection, NET::WMMoveResize ).moveResizeRequest( + NETRootInfo( connection, NET::WMMoveResize ).moveResizeRequest( window->winId(), position.x() * dpiRatio, position.y() * dpiRatio, NET::Move ); #else Q_UNUSED( window ); Q_UNUSED( position ); #endif } //_______________________________________________________ - void WindowManager::startDragWayland( Window* window, const QPoint& ) + void WindowManager::startDragWayland( QWindow* window, const QPoint& ) { #if OXYGEN_HAVE_KWAYLAND if( !_seat ) { return; } auto shellSurface = KWayland::Client::ShellSurface::fromWindow(window); if( !shellSurface ) { // TODO: also check for xdg-shell in future return; } shellSurface->requestMove( _seat, _waylandSerial ); #else Q_UNUSED( window ); #endif } //____________________________________________________________ bool WindowManager::supportWMMoveResize( void ) const { #if OXYGEN_HAVE_KWAYLAND if( Helper::isWayland() ) { return true; } #endif #if OXYGEN_HAVE_X11 return Helper::isX11(); #else return false; #endif } //____________________________________________________________ bool WindowManager::isDockWidgetTitle( const QWidget* widget ) const { if( !widget ) return false; if( const QDockWidget* dockWidget = qobject_cast( widget->parent() ) ) { return widget == dockWidget->titleBarWidget(); } else return false; } } diff --git a/kstyle/oxygenwindowmanager.h b/kstyle/oxygenwindowmanager.h index aea4ebfc..1dcef217 100644 --- a/kstyle/oxygenwindowmanager.h +++ b/kstyle/oxygenwindowmanager.h @@ -1,325 +1,312 @@ #ifndef oxygenwindowmanager_h #define oxygenwindowmanager_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "oxygen.h" #include "config-liboxygen.h" #include #include #include +#include #include #include #include -#if !OXYGEN_USE_KDE4 -#include -#endif - #if OXYGEN_HAVE_KWAYLAND namespace KWayland { namespace Client { class Pointer; class Seat; } } #endif namespace Oxygen { class WindowManager: public QObject { Q_OBJECT public: //* constructor explicit WindowManager( QObject* ); //* initialize /** read relevant options from config */ void initialize( void ); //* register widget void registerWidget( QWidget* ); -#if !OXYGEN_USE_KDE4 //* register quick item void registerQuickItem( QQuickItem* ); -#endif //* unregister widget void unregisterWidget( QWidget* ); //* event filter [reimplemented] bool eventFilter( QObject*, QEvent* ) override; protected: //* timer event, /** used to start drag if button is pressed for a long enough time */ void timerEvent( QTimerEvent* ) override; private: //* mouse press event bool mousePressEvent( QObject*, QEvent* ); //* mouse move event bool mouseMoveEvent( QObject*, QEvent* ); //* mouse release event bool mouseReleaseEvent( QObject*, QEvent* ); //*@name configuration //@{ //* enable state bool enabled( void ) const { return _enabled; } //* enable state void setEnabled( bool value ) { _enabled = value; } //* returns true if window manager is used for moving bool useWMMoveResize( void ) const { return supportWMMoveResize() && _useWMMoveResize; } //* use window manager for moving, when available void setUseWMMoveResize( bool value ) { _useWMMoveResize = value; } //* drag mode int dragMode( void ) const { return _dragMode; } //* drag mode void setDragMode( int value ) { _dragMode = value; } //* drag distance (pixels) void setDragDistance( int value ) { _dragDistance = value; } //* drag delay (msec) void setDragDelay( int value ) { _dragDelay = value; } //* set list of whiteListed widgets /** white list is read from options and is used to adjust per-app window dragging issues */ void initializeWhiteList(); //* set list of blackListed widgets /** black list is read from options and is used to adjust per-app window dragging issues */ void initializeBlackList( void ); //* initializes the Wayland specific parts void initializeWayland(); //* The Wayland Seat's hasPointer property changed void waylandHasPointerChanged( bool hasPointer ); //@} //* returns true if widget is dragable bool isDragable( QWidget* ); //* returns true if widget is dragable bool isBlackListed( QWidget* ); //* returns true if widget is dragable bool isWhiteListed( QWidget* ) const; //* returns true if drag can be started from current widget bool canDrag( QWidget* ); //* returns true if drag can be started from current widget and position /** child at given position is passed as second argument */ bool canDrag( QWidget*, QWidget*, const QPoint& ); //* reset drag void resetDrag( void ); -#if QT_VERSION >= 0x050000 - using Window = QWindow; -#else - using Window = QWidget; -#endif - //* start drag - void startDrag( Window*, const QPoint& ); + void startDrag( QWindow*, const QPoint& ); //* X11 specific implementation for startDrag - void startDragX11( Window*, const QPoint& ); + void startDragX11( QWindow*, const QPoint& ); //* Wayland specific implementation for startDrag - void startDragWayland( Window*, const QPoint& ); + void startDragWayland( QWindow*, const QPoint& ); //* returns true if window manager is used for moving /** right now this is true only for X11 */ bool supportWMMoveResize( void ) const; //* utility function bool isDockWidgetTitle( const QWidget* ) const; //*@name lock //@{ void setLocked( bool value ) { _locked = value; } //* lock bool isLocked( void ) const { return _locked; } //@} //* returns first widget matching given class, or 0L if none template T findParent( const QWidget* ) const; //* enability bool _enabled; //* use WM moveResize bool _useWMMoveResize; //* drag mode int _dragMode; //* drag distance /** this is copied from kwin::geometry */ int _dragDistance; //* drag delay /** this is copied from kwin::geometry */ int _dragDelay; //* wrapper for exception id class ExceptionId: public QPair { public: //* constructor explicit ExceptionId( const QString& value ) { const QStringList args( value.split( QChar::fromLatin1( '@' ) ) ); if( args.isEmpty() ) return; second = args[0].trimmed(); if( args.size()>1 ) first = args[1].trimmed(); } const QString& appName( void ) const { return first; } const QString& className( void ) const { return second; } }; //* exception set using ExceptionSet = QSet; //* list of white listed special widgets /** it is read from options and is used to adjust per-app window dragging issues */ ExceptionSet _whiteList; //* list of black listed special widgets /** it is read from options and is used to adjust per-app window dragging issues */ ExceptionSet _blackList; //* drag point QPoint _dragPoint; QPoint _globalDragPoint; //* drag timer QBasicTimer _dragTimer; //* target being dragged /** Weak pointer is used in case the target gets deleted while drag is in progress */ WeakPointer _target; -#if !OXYGEN_USE_KDE4 WeakPointer _quickTarget; -#endif //* true if drag is about to start bool _dragAboutToStart; //* true if drag is in progress bool _dragInProgress; //* true if drag is locked bool _locked; //* cursor override /** used to keep track of application cursor being overridden when dragging in non-WM mode */ bool _cursorOverride; //* application event filter QObject* _appEventFilter; #if OXYGEN_HAVE_KWAYLAND //* The Wayland seat object which needs to be passed to move requests. KWayland::Client::Seat* _seat; //* The Wayland pointer object where we get pointer events on. KWayland::Client::Pointer* _pointer; //* latest searial which needs to be passed to the move requests. quint32 _waylandSerial; #endif //* allow access of all private members to the app event filter friend class AppEventFilter; }; //____________________________________________________________________ template T WindowManager::findParent( const QWidget* widget ) const { if( !widget ) return 0L; for( QWidget* parent = widget->parentWidget(); parent; parent = parent->parentWidget() ) { if( T cast = qobject_cast(parent) ) return cast; } return 0L; } } #endif diff --git a/kstyle/transitions/oxygentransitionwidget.cpp b/kstyle/transitions/oxygentransitionwidget.cpp index ea11d7cf..c40b6f2f 100644 --- a/kstyle/transitions/oxygentransitionwidget.cpp +++ b/kstyle/transitions/oxygentransitionwidget.cpp @@ -1,309 +1,305 @@ ////////////////////////////////////////////////////////////////////////////// // oxygentransitionwidget.cpp // stores event filters and maps widgets to transitions for transitions // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygentransitionwidget.h" #include #include #include #include namespace Oxygen { //________________________________________________ bool TransitionWidget::_paintEnabled = true; bool TransitionWidget::paintEnabled( void ) { return _paintEnabled; } int TransitionWidget::_steps = 0; //________________________________________________ TransitionWidget::TransitionWidget( QWidget* parent, int duration ): QWidget( parent ), _animation( new Animation( duration, this ) ) { // background flags setAttribute( Qt::WA_NoSystemBackground ); setAutoFillBackground( false ); // setup animation _animation.data()->setStartValue( 0 ); _animation.data()->setEndValue( 1.0 ); _animation.data()->setTargetObject( this ); _animation.data()->setPropertyName( "opacity" ); // hide when animation is finished connect( _animation.data(), SIGNAL(finished()), SLOT(hide()) ); } //________________________________________________ QPixmap TransitionWidget::grab( QWidget* widget, QRect rect ) { // change rect if( !rect.isValid() ) rect = widget->rect(); if( !rect.isValid() ) return QPixmap(); // initialize pixmap QPixmap out( rect.size() ); out.fill( Qt::transparent ); _paintEnabled = false; if( testFlag( GrabFromWindow ) ) { rect = rect.translated( widget->mapTo( widget->window(), widget->rect().topLeft() ) ); widget = widget->window(); - #if QT_VERSION < 0x050000 - out = QPixmap::grabWidget( widget, rect ); - #else out = widget->grab( rect ); - #endif } else { if( !testFlag( Transparent ) ) { grabBackground( out, widget, rect ); } grabWidget( out, widget, rect ); } _paintEnabled = true; return out; } //________________________________________________ bool TransitionWidget::event( QEvent* event ) { switch( event->type() ) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::KeyPress: case QEvent::KeyRelease: endAnimation(); hide(); event->ignore(); return false; default: return QWidget::event( event ); } } //________________________________________________ void TransitionWidget::paintEvent( QPaintEvent* event ) { // fully transparent case if( opacity() >= 1.0 && endPixmap().isNull() ) return; if( !_paintEnabled ) return; // get rect QRect rect = event->rect(); if( !rect.isValid() ) rect = this->rect(); // local pixmap const bool paintOnWidget( testFlag( PaintOnWidget ) && !testFlag( Transparent ) ); if( !paintOnWidget ) { if( _currentPixmap.isNull() || _currentPixmap.size() != size() ) { _currentPixmap = QPixmap( size() ); } } // fill _currentPixmap.fill( Qt::transparent ); // copy local pixmap to current { QPainter p; // draw end pixmap first, provided that opacity is small enough if( opacity() >= 0.004 && !_endPixmap.isNull() ) { // faded endPixmap if parent target is transparent and opacity is if( opacity() <= 0.996 && testFlag( Transparent ) ) { fade( _endPixmap, _currentPixmap, opacity(), rect ); p.begin( &_currentPixmap ); p.setClipRect( event->rect() ); } else { if( paintOnWidget ) p.begin( this ); else p.begin( &_currentPixmap ); p.setClipRect( event->rect() ); p.drawPixmap( QPoint(), _endPixmap ); } } else { if( paintOnWidget ) p.begin( this ); else p.begin( &_currentPixmap ); p.setClipRect( event->rect() ); } // draw fading start pixmap if( opacity() <= 0.996 && !_startPixmap.isNull() ) { if( opacity() >= 0.004 ) { fade( _startPixmap, _localStartPixmap, 1.0-opacity(), rect ); p.drawPixmap( QPoint(), _localStartPixmap ); } else p.drawPixmap( QPoint(), _startPixmap ); } p.end(); } // copy current pixmap on widget if( !paintOnWidget ) { QPainter p( this ); p.setClipRect( event->rect() ); p.drawPixmap( QPoint(0,0), _currentPixmap ); p.end(); } } //________________________________________________ void TransitionWidget::grabBackground( QPixmap& pixmap, QWidget* widget, QRect& rect ) const { if( !widget ) return; QWidgetList widgets; if( widget->autoFillBackground() ) { widgets.append( widget ); } QWidget *parent(0); // get highest level parent for( parent = widget->parentWidget(); parent; parent = parent->parentWidget() ) { if( !( parent->isVisible() && parent->rect().isValid() ) ) continue; // store in list widgets.append( parent ); // stop at topLevel if( parent->isTopLevel() || parent->autoFillBackground() ) break; } if( !parent ) parent = widget; // painting QPainter p(&pixmap); p.setClipRect( rect ); const QBrush backgroundBrush = parent->palette().brush( parent->backgroundRole()); if( backgroundBrush.style() == Qt::TexturePattern) { p.drawTiledPixmap( rect, backgroundBrush.texture(), widget->mapTo( parent, rect.topLeft() ) ); } else { p.fillRect( pixmap.rect(), backgroundBrush ); } if( parent->isTopLevel() && parent->testAttribute(Qt::WA_StyledBackground)) { QStyleOption option; option.initFrom(parent); option.rect = rect; option.rect.translate( widget->mapTo( parent, rect.topLeft() ) ); p.translate(-option.rect.topLeft()); parent->style()->drawPrimitive ( QStyle::PE_Widget, &option, &p, parent ); p.translate(option.rect.topLeft()); } // draw all widgets in parent list // backward QPaintEvent event(rect); for( int i = widgets.size() - 1; i>=0; i-- ) { QWidget* w = widgets.at(i); w->render( &p, -widget->mapTo( w, rect.topLeft() ), rect, 0 ); } // end p.end(); } //________________________________________________ void TransitionWidget::grabWidget( QPixmap& pixmap, QWidget* widget, QRect& rect ) const { widget->render( &pixmap, pixmap.rect().topLeft(), rect, QWidget::DrawChildren ); } //________________________________________________ void TransitionWidget::fade( const QPixmap& source, QPixmap& target, qreal opacity, const QRect& rect ) const { if( target.isNull() || target.size() != size() ) { target = QPixmap( size() ); } // erase target target.fill( Qt::transparent ); // check opacity if( opacity*255 < 1 ) return; QPainter p( &target ); p.setClipRect( rect ); // draw pixmap p.drawPixmap( QPoint(0,0), source ); // opacity mask (0.996 corresponds to 254/255) if( opacity <= 0.996 ) { p.setCompositionMode(QPainter::CompositionMode_DestinationIn); QColor color( Qt::black ); color.setAlphaF( opacity ); p.fillRect(rect, color ); } p.end(); return; } } diff --git a/liboxygen/CMakeLists.txt b/liboxygen/CMakeLists.txt index 2f68efe5..786cfadf 100644 --- a/liboxygen/CMakeLists.txt +++ b/liboxygen/CMakeLists.txt @@ -1,151 +1,93 @@ add_definitions(-DTRANSLATION_DOMAIN=\"liboxygenstyleconfig\") ################# configuration ################# configure_file(config-liboxygen.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-liboxygen.h) ################# liboxygenstyle ################# set(oxygenstyle_LIB_SRCS oxygenanimation.cpp oxygenhelper.cpp oxygenitemmodel.cpp oxygenshadowcache.cpp oxygentileset.cpp) -if(OXYGEN_USE_KDE4) - - kde4_add_kcfg_files(oxygenstyle_LIB_SRCS +kconfig_add_kcfg_files(oxygenstyle_LIB_SRCS oxygenactiveshadowconfiguration.kcfgc oxygeninactiveshadowconfiguration.kcfgc - ) - - kde4_add_library(oxygenstyle SHARED ${oxygenstyle_LIB_SRCS}) - - generate_export_header(oxygenstyle BASE_NAME oxygen EXPORT_FILE_NAME oxygen_export.h) - - target_link_libraries(oxygenstyle ${KDE4_KDEUI_LIBS}) - - if(OXYGEN_HAVE_X11) - target_link_libraries(oxygenstyle ${X11_XCB_LIBRARIES}) - target_link_libraries(oxygenstyle ${XCB_LIBRARIES}) - endif() - - set_target_properties(oxygenstyle PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) +) - if(WIN32) - # As stated in http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx M_PI only gets defined - # when using MSVC if _USE_MATH_DEFINES is defined (this is needed for angle.cpp) - target_compile_definitions(oxygenstyle PRIVATE _USE_MATH_DEFINES _GNU_SOURCE) - endif() - install(TARGETS oxygenstyle ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) +add_library(oxygenstyle5 ${oxygenstyle_LIB_SRCS}) + +generate_export_header(oxygenstyle5 BASE_NAME oxygen EXPORT_FILE_NAME oxygen_export.h) + +# NB: although we install no headers, we still need to have a link +# interface, since other Oxygen targets link to this library +target_link_libraries(oxygenstyle5 + PUBLIC + Qt5::Core + Qt5::Gui + Qt5::Widgets + KF5::ConfigCore + KF5::ConfigWidgets + KF5::WindowSystem + PRIVATE + KF5::GuiAddons +) -else() +target_include_directories(oxygenstyle5 PUBLIC "$") - kconfig_add_kcfg_files(oxygenstyle_LIB_SRCS - oxygenactiveshadowconfiguration.kcfgc - oxygeninactiveshadowconfiguration.kcfgc - ) - - add_library(oxygenstyle5 ${oxygenstyle_LIB_SRCS}) - - generate_export_header(oxygenstyle5 BASE_NAME oxygen EXPORT_FILE_NAME oxygen_export.h) - - # NB: although we install no headers, we still need to have a link - # interface, since other Oxygen targets link to this library - target_link_libraries(oxygenstyle5 - PUBLIC - Qt5::Core - Qt5::Gui - Qt5::Widgets - KF5::ConfigCore - KF5::ConfigWidgets - KF5::WindowSystem - PRIVATE - KF5::GuiAddons - ) - - target_include_directories(oxygenstyle5 PUBLIC "$") - - if(OXYGEN_HAVE_X11) - target_link_libraries(oxygenstyle5 PRIVATE XCB::XCB Qt5::X11Extras) - endif() - - set_target_properties(oxygenstyle5 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) - if(WIN32) - # As stated in http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx M_PI only gets defined - # when using MSVC if _USE_MATH_DEFINES is defined (this is needed for angle.cpp) - target_compile_definitions(oxygenstyle5 PRIVATE _USE_MATH_DEFINES _GNU_SOURCE) - endif() - install(TARGETS oxygenstyle5 ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) +if(OXYGEN_HAVE_X11) + target_link_libraries(oxygenstyle5 PRIVATE XCB::XCB Qt5::X11Extras) +endif() +set_target_properties(oxygenstyle5 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) +if(WIN32) + # As stated in http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx M_PI only gets defined + # when using MSVC if _USE_MATH_DEFINES is defined (this is needed for angle.cpp) + target_compile_definitions(oxygenstyle5 PRIVATE _USE_MATH_DEFINES _GNU_SOURCE) endif() +install(TARGETS oxygenstyle5 ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) ################# liboxygenstyleconfig ################# set(oxygenstyleconfig_LIB_SRCS oxygenanimationconfigitem.cpp oxygenbaseanimationconfigwidget.cpp oxygengenericanimationconfigitem.cpp oxygenshadowconfigwidget.cpp ) set(oxygenstyleconfig_LIB_FORMS ui/oxygenanimationconfigitem.ui ui/oxygenanimationconfigwidget.ui ui/oxygengenericanimationconfigbox.ui ui/oxygenshadowconfigurationui.ui ) -if(OXYGEN_USE_KDE4) - - kde4_add_ui_files(oxygenstyleconfig_LIB_FORMS_HEADERS ${oxygenstyleconfig_LIB_FORMS}) - kde4_add_kcfg_files(oxygenstyleconfig_LIB_SRCS - oxygenactiveshadowconfiguration.kcfgc - oxygeninactiveshadowconfiguration.kcfgc - ) - - kde4_add_library(oxygenstyleconfig SHARED - ${oxygenstyleconfig_LIB_SRCS} - ${oxygenstyleconfig_LIB_FORMS_HEADERS}) - - generate_export_header(oxygenstyleconfig BASE_NAME oxygen_config EXPORT_FILE_NAME oxygen_config_export.h) +ki18n_wrap_ui(oxygenstyleconfig_LIB_FORMS_HEADERS ${oxygenstyleconfig_LIB_FORMS}) - target_link_libraries(oxygenstyleconfig ${KDE4_KDEUI_LIBS}) - - set_target_properties(oxygenstyleconfig PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) - install(TARGETS oxygenstyleconfig ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) - - # NB: although we install no headers, we still need to have a link - # interface, since other Oxygen targets link to this library - target_link_libraries(oxygenstyleconfig oxygenstyle) - -else() - - ki18n_wrap_ui(oxygenstyleconfig_LIB_FORMS_HEADERS ${oxygenstyleconfig_LIB_FORMS}) - - kconfig_add_kcfg_files(oxygenstyleconfig_LIB_SRCS - oxygenactiveshadowconfiguration.kcfgc - oxygeninactiveshadowconfiguration.kcfgc - ) - - add_library(oxygenstyleconfig5 SHARED - ${oxygenstyleconfig_LIB_SRCS} - ${oxygenstyleconfig_LIB_FORMS_HEADERS}) - - generate_export_header(oxygenstyleconfig5 BASE_NAME oxygen_config EXPORT_FILE_NAME oxygen_config_export.h) - - # NB: although we install no headers, we still need to have a link - # interface, since other Oxygen targets link to this library - target_link_libraries(oxygenstyleconfig5 - PUBLIC - oxygenstyle5 - Qt5::Core - Qt5::Gui - Qt5::Widgets - PRIVATE - KF5::I18n - ) +kconfig_add_kcfg_files(oxygenstyleconfig_LIB_SRCS + oxygenactiveshadowconfiguration.kcfgc + oxygeninactiveshadowconfiguration.kcfgc +) - set_target_properties(oxygenstyleconfig5 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) - install(TARGETS oxygenstyleconfig5 ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) - # Note: no headers installed +add_library(oxygenstyleconfig5 SHARED + ${oxygenstyleconfig_LIB_SRCS} + ${oxygenstyleconfig_LIB_FORMS_HEADERS}) + +generate_export_header(oxygenstyleconfig5 BASE_NAME oxygen_config EXPORT_FILE_NAME oxygen_config_export.h) + +# NB: although we install no headers, we still need to have a link +# interface, since other Oxygen targets link to this library +target_link_libraries(oxygenstyleconfig5 + PUBLIC + oxygenstyle5 + Qt5::Core + Qt5::Gui + Qt5::Widgets + PRIVATE + KF5::I18n +) -endif() +set_target_properties(oxygenstyleconfig5 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) +install(TARGETS oxygenstyleconfig5 ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) +# Note: no headers installed diff --git a/liboxygen/config-liboxygen.h.cmake b/liboxygen/config-liboxygen.h.cmake index aa7ea2ee..da0d55d2 100644 --- a/liboxygen/config-liboxygen.h.cmake +++ b/liboxygen/config-liboxygen.h.cmake @@ -1,33 +1,30 @@ #ifndef config_liboxygen_h #define config_liboxygen_h /* config-liboxygen.h. Generated by cmake from config-liboxygen.h.cmake */ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ -/* Define to 1 if you compile against KDE4*/ -#cmakedefine01 OXYGEN_USE_KDE4 - /* Define to 1 if you have XCB libraries */ #cmakedefine01 OXYGEN_HAVE_X11 #cmakedefine01 OXYGEN_HAVE_KWAYLAND #endif diff --git a/liboxygen/liboxygen.h b/liboxygen/liboxygen.h index 20d1b86b..73591a95 100644 --- a/liboxygen/liboxygen.h +++ b/liboxygen/liboxygen.h @@ -1,61 +1,51 @@ #ifndef liboxygen_h #define liboxygen_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include #include namespace Oxygen { - #if QT_VERSION >= 0x050000 //* scoped pointer convenience typedef template using WeakPointer = QPointer; - #else - //* scoped pointer convenience typedef - template using WeakPointer = QWeakPointer; - #endif - - //* disable QStringLiteral for older Qt version - #if QT_VERSION < 0x050000 - using QStringLiteral = QString; - #endif //* corners enum Corner { CornerTopLeft = 0x1, CornerTopRight = 0x2, CornerBottomLeft = 0x4, CornerBottomRight = 0x8, CornersTop = CornerTopLeft|CornerTopRight, CornersBottom = CornerBottomLeft|CornerBottomRight, CornersLeft = CornerTopLeft|CornerBottomLeft, CornersRight = CornerTopRight|CornerBottomRight, AllCorners = CornerTopLeft|CornerTopRight|CornerBottomLeft|CornerBottomRight }; Q_DECLARE_FLAGS( Corners, Corner ); } Q_DECLARE_OPERATORS_FOR_FLAGS( Oxygen::Corners ); #endif diff --git a/liboxygen/oxygenhelper.cpp b/liboxygen/oxygenhelper.cpp index 11dc1710..e864303e 100644 --- a/liboxygen/oxygenhelper.cpp +++ b/liboxygen/oxygenhelper.cpp @@ -1,1009 +1,958 @@ /* * Copyright 2009-2010 Hugo Pereira Da Costa * Copyright 2008 Long Huynh Huu * Copyright 2007 Matthew Woehlke * Copyright 2007 Casper Boemann * Copyright 2007 Fredrik H?glund * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "oxygenhelper.h" #include "liboxygen.h" #include #include #include -#if OXYGEN_USE_KDE4 -#include -#endif - #include #include #include #include #include #if OXYGEN_HAVE_X11 #include #endif -#if OXYGEN_HAVE_X11 && QT_VERSION < 0x050000 -#include -#endif - namespace Oxygen { const qreal Helper::_slabThickness = 0.45; const qreal Helper::_shadowGain = 1.5; const qreal Helper::_glowBias = 0.6; //____________________________________________________________________ Helper::Helper( KSharedConfig::Ptr config ): _config( config ) { init(); } - //____________________________________________________________________ - #if OXYGEN_USE_KDE4 - Helper::Helper( const QByteArray& name ): - _componentData( name, 0, KComponentData::SkipMainComponentRegistration ), - _config( _componentData.config() ) - { init(); } - #endif - //____________________________________________________________________ KSharedConfig::Ptr Helper::config() const { return _config; } //____________________________________________________________________ void Helper::loadConfig() { - #if OXYGEN_USE_KDE4 - _contrast = KGlobalSettings::contrastF( _config ); - #else _contrast = KColorScheme::contrastF( _config ); - #endif _bgcontrast = qMin( 1.0, 0.9*_contrast/0.7 ); _viewFocusBrush = KStatefulBrush( KColorScheme::View, KColorScheme::FocusColor, _config ); _viewHoverBrush = KStatefulBrush( KColorScheme::View, KColorScheme::HoverColor, _config ); _viewNegativeTextBrush = KStatefulBrush( KColorScheme::View, KColorScheme::NegativeText, _config ); } //____________________________________________________________________ void Helper::invalidateCaches() { _decoColorCache.clear(); _lightColorCache.clear(); _darkColorCache.clear(); _shadowColorCache.clear(); _backgroundTopColorCache.clear(); _backgroundBottomColorCache.clear(); _backgroundRadialColorCache.clear(); _backgroundColorCache.clear(); _backgroundCache.clear(); _dotCache.clear(); } //____________________________________________________________________ void Helper::setMaxCacheSize( int value ) { // assign value _backgroundCache.setMaxCost( value ); _dotCache.setMaxCost( value ); /* note: we do not limit the size of the color caches on purpose, since they should be small anyway */ } //____________________________________________________________________ void Helper::renderWindowBackground(QPainter* p, const QRect& clipRect, const QRect& windowRect, const QColor& color, int yShift) { if ( clipRect.isValid() ) { p->save(); p->setClipRegion( clipRect,Qt::IntersectClip ); } // draw upper linear gradient const int splitY( qMin( 300, ( 3*windowRect.height() )/4 ) ); QRect upperRect = windowRect; if( splitY+yShift>0 ) { upperRect.setHeight(splitY+yShift); QPixmap tile( verticalGradient( color, splitY+yShift, yShift ) ); p->drawTiledPixmap( upperRect, tile ); } // draw lower flat part const QRect lowerRect = windowRect.adjusted(0, splitY+yShift, 0, 0); if( lowerRect.isValid() ) { p->fillRect( lowerRect, backgroundBottomColor( color ) ); } // draw upper radial gradient const int radialW( qMin( 600, windowRect.width() ) ); const QRect radialRect( ( windowRect.width() - radialW ) / 2 + windowRect.x(), windowRect.y(), radialW, 64 + yShift ); if( clipRect.intersects( radialRect ) ) { QPixmap tile = radialGradient( color, radialW, 64 + yShift ); p->drawPixmap( radialRect, tile ); } if ( clipRect.isValid() ) { p->restore(); } } //____________________________________________________________________ void Helper::renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, const QColor& color, int yShift ) { // get coordinates relative to the client area // this is stupid. One could use mapTo if this was taking const QWidget* and not // QWidget* as argument. const QWidget* w( widget ); int x( 0 ); int y( 0 ); while ( w != window && !w->isWindow() && w != w->parentWidget() ) { x += w->geometry().x(); y += w->geometry().y(); w = w->parentWidget(); } // translate and call the base method const QRect r = window->rect().translated( -x, -y ); renderWindowBackground( p, clipRect, r, color, yShift ); } //_____________________________________________________________ void Helper::renderDot( QPainter* p, const QPoint& point, const QColor& baseColor ) { const quint64 key( colorKey(baseColor) ); QPixmap pixmap; if( QPixmap* cachedPixmap = _dotCache.object( key ) ) { pixmap = *cachedPixmap; } else { pixmap = highDpiPixmap( 4 ); pixmap.fill( Qt::transparent ); const qreal diameter( 1.8 ); QPainter painter( &pixmap ); painter.setRenderHint( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); const QPoint center( QRect( 0, 0, 4, 4 ).center() ); // light ellipse painter.setBrush( calcLightColor( baseColor ) ); painter.drawEllipse( QRectF( center.x()-diameter/2+1.0, center.y()-diameter/2+1.0, diameter, diameter ) ); // dark ellipse painter.setBrush( calcDarkColor( baseColor ).darker( 130 ) ); painter.drawEllipse( QRectF( center.x()-diameter/2+0.5, center.y()-diameter/2+0.5, diameter, diameter ) ); painter.end(); // store in cache _dotCache.insert( key, new QPixmap( pixmap ) ); } p->save(); p->translate( point - QPoint( 1,1 ) ); p->setRenderHint( QPainter::Antialiasing ); p->drawPixmap( QPoint( 0,0 ), pixmap ); p->restore(); } //____________________________________________________________________ bool Helper::lowThreshold( const QColor& color ) { const quint32 key( colorKey(color) ); ColorMap::iterator iter( _lowThreshold.find( key ) ); if( iter != _lowThreshold.end() ) return iter.value(); else { const QColor darker( KColorScheme::shade( color, KColorScheme::MidShade, 0.5 ) ); const bool result( KColorUtils::luma( darker ) > KColorUtils::luma( color ) ); _lowThreshold.insert( key, result ); return result; } } //____________________________________________________________________ bool Helper::highThreshold( const QColor& color ) { const quint32 key( colorKey(color) ); ColorMap::iterator iter( _highThreshold.find( key ) ); if( iter != _highThreshold.end() ) return iter.value(); else { const QColor lighter( KColorScheme::shade( color, KColorScheme::LightShade, 0.5 ) ); const bool result( KColorUtils::luma( lighter ) < KColorUtils::luma( color ) ); _highThreshold.insert( key, result ); return result; } } //____________________________________________________________________ QColor Helper::alphaColor( QColor color, qreal alpha ) { if( alpha >= 0 && alpha < 1.0 ) { color.setAlphaF( alpha*color.alphaF() ); } return color; } //____________________________________________________________________ QColor Helper::backgroundRadialColor( const QColor& color ) { const quint64 key( colorKey(color) ); if( QColor* cachedColor = _backgroundRadialColorCache.object( key ) ) { return *cachedColor; } QColor out; if( lowThreshold( color ) ) out = KColorScheme::shade( color, KColorScheme::LightShade, 0.0 ); else if( highThreshold( color ) ) out = color; else out = KColorScheme::shade( color, KColorScheme::LightShade, _bgcontrast ); _backgroundRadialColorCache.insert( key, new QColor( out ) ); return out; } //_________________________________________________________________________ QColor Helper::backgroundTopColor( const QColor& color ) { const quint64 key( colorKey(color) ); if( QColor* cachedColor = _backgroundTopColorCache.object( key ) ) { return *cachedColor; } QColor out; if( lowThreshold( color ) ) out = KColorScheme::shade( color, KColorScheme::MidlightShade, 0.0 ); else { const qreal my( KColorUtils::luma( KColorScheme::shade( color, KColorScheme::LightShade, 0.0 ) ) ); const qreal by( KColorUtils::luma( color ) ); out = KColorUtils::shade( color, ( my - by ) * _bgcontrast ); } _backgroundTopColorCache.insert( key, new QColor( out ) ); return out; } //_________________________________________________________________________ QColor Helper::backgroundBottomColor( const QColor& color ) { const quint64 key( colorKey(color) ); if( QColor* cachedColor = _backgroundBottomColorCache.object( key ) ) { return *cachedColor; } QColor out; const QColor midColor( KColorScheme::shade( color, KColorScheme::MidShade, 0.0 ) ); if( lowThreshold( color ) ) out = midColor; else { const qreal by( KColorUtils::luma( color ) ); const qreal my( KColorUtils::luma( midColor ) ); out = KColorUtils::shade( color, ( my - by ) * _bgcontrast ); } _backgroundBottomColorCache.insert( key, new QColor( out ) ); return out; } //____________________________________________________________________ QColor Helper::calcLightColor( const QColor& color ) { const quint64 key( colorKey(color) ); if( QColor* cachedColor = _lightColorCache.object( key ) ) { return *cachedColor; } QColor out = highThreshold( color ) ? color: KColorScheme::shade( color, KColorScheme::LightShade, _contrast ); _lightColorCache.insert( key, new QColor( out ) ); return out; } //____________________________________________________________________ QColor Helper::calcDarkColor( const QColor& color ) { const quint64 key( colorKey(color) ); if( QColor* cachedColor = _darkColorCache.object( key ) ) { return *cachedColor; } QColor out = ( lowThreshold( color ) ) ? KColorUtils::mix( calcLightColor( color ), color, 0.3 + 0.7 * _contrast ): KColorScheme::shade( color, KColorScheme::MidShade, _contrast ); _darkColorCache.insert( key, new QColor( out ) ); return out; } //____________________________________________________________________ QColor Helper::calcShadowColor( const QColor& color ) { const quint64 key( colorKey(color) ); if( QColor* cachedColor = _shadowColorCache.object( key ) ) { return *cachedColor; } QColor out = ( lowThreshold( color ) ) ? KColorUtils::mix( Qt::black, color, color.alphaF() ) : KColorScheme::shade( KColorUtils::mix( Qt::black, color, color.alphaF() ), KColorScheme::ShadowShade, _contrast ); // make sure shadow color has the same alpha channel as the input out.setAlpha( color.alpha() ); // insert in cache _shadowColorCache.insert( key, new QColor( out ) ); return out; } //____________________________________________________________________ QColor Helper::backgroundColor( const QColor& color, qreal ratio ) { const quint64 key( ( colorKey(color) << 32 ) | int( ratio*512 ) ); if( QColor* cachedColor = _backgroundColorCache.object( key ) ) { return *cachedColor; } QColor out; if( ratio < 0.5 ) { const qreal a( 2.0*ratio ); out = KColorUtils::mix( backgroundTopColor( color ), color, a ); } else { const qreal a( 2.0*ratio-1 ); out = KColorUtils::mix( color, backgroundBottomColor( color ), a ); } _backgroundColorCache.insert( key, new QColor( out ) ); return out; } //____________________________________________________________________ QPixmap Helper::verticalGradient( const QColor& color, int height, int offset ) { const quint64 key( ( colorKey(color) << 32 ) | height | 0x8000 ); if( QPixmap* cachedPixmap = _backgroundCache.object( key ) ) { return *cachedPixmap; } QPixmap pixmap( 1, height ); pixmap.fill( Qt::transparent ); QLinearGradient gradient( 0, offset, 0, height ); gradient.setColorAt( 0.0, backgroundTopColor( color ) ); gradient.setColorAt( 0.5, color ); gradient.setColorAt( 1.0, backgroundBottomColor( color ) ); QPainter painter( &pixmap ); painter.fillRect( pixmap.rect(), gradient ); painter.end(); _backgroundCache.insert( key, new QPixmap( pixmap ) ); return pixmap; } //____________________________________________________________________ QPixmap Helper::radialGradient( const QColor& color, int width, int height ) { const quint64 key( ( colorKey(color) << 32 ) | width | 0xb000 ); if( QPixmap* cachedPixmap = _backgroundCache.object( key ) ) { return *cachedPixmap; } QPixmap pixmap( width, height ); pixmap.fill( Qt::transparent ); QRadialGradient gradient( 64, height-64, 64 ); QColor radialColor = backgroundRadialColor( color ); radialColor.setAlpha( 255 ); gradient.setColorAt( 0, radialColor ); radialColor.setAlpha( 101 ); gradient.setColorAt( 0.5, radialColor ); radialColor.setAlpha( 37 ); gradient.setColorAt( 0.75, radialColor ); radialColor.setAlpha( 0 ); gradient.setColorAt( 1, radialColor ); QPainter painter( &pixmap ); painter.setWindow( 0, 0, 128, height ); painter.fillRect( QRect( 0,0,128,height ), gradient ); painter.end(); _backgroundCache.insert( key, new QPixmap( pixmap ) ); return pixmap; } //____________________________________________________________________________________ QColor Helper::decoColor( const QColor& background, const QColor& color ) { const quint64 key( ( colorKey(background) << 32 ) | colorKey(color) ); if( QColor* cachedColor = _decoColorCache.object( key ) ) { return *cachedColor; } QColor out = KColorUtils::mix( background, color, 0.8*( 1.0 + _contrast ) ); _decoColorCache.insert( key, new QColor( out ) ); return out; } //_______________________________________________________________________ QRegion Helper::roundedMask( const QRect& rect, int left, int right, int top, int bottom ) const { // get rect geometry int x, y, w, h; rect.getRect( &x, &y, &w, &h ); QRegion mask( x + 4*left, y + 0*top, w-4*( left+right ), h-0*( top+bottom ) ); mask += QRegion( x + 0*left, y + 4*top, w-0*( left+right ), h-4*( top+bottom ) ); mask += QRegion( x + 2*left, y + 1*top, w-2*( left+right ), h-1*( top+bottom ) ); mask += QRegion( x + 1*left, y + 2*top, w-1*( left+right ), h-2*( top+bottom ) ); return mask; } //______________________________________________________________________________ QBitmap Helper::roundedMask( const QSize& size, Corners corners, qreal radius ) const { QBitmap bitmap( highDpiPixmap( size ) ); if( corners == 0 ) { bitmap.fill( Qt::color1 ); } else { // initialize bitmap bitmap.fill( Qt::color0 ); // setup painter QPainter painter( &bitmap ); painter.setPen( Qt::NoPen ); painter.setBrush( Qt::color1 ); // get path const QPainterPath path( roundedPath( bitmap.rect(), corners, radius ) ); painter.drawPath( path ); } return bitmap; } //______________________________________________________________________________ QPainterPath Helper::roundedPath( const QRect& rect, Corners corners, qreal radius ) const { QPainterPath path; // simple cases if( corners == 0 ) { path.addRect( rect ); return path; } if( corners == AllCorners ) { path.addRoundedRect( rect, radius, radius ); return path; } const QSizeF cornerSize( 2*radius, 2*radius ); // rotate counterclockwise // top left corner if( corners & CornerTopLeft ) { path.moveTo( rect.topLeft() + QPointF( radius, 0 ) ); path.arcTo( QRectF( rect.topLeft(), cornerSize ), 90, 90 ); } else path.moveTo( rect.topLeft() ); // bottom left corner if( corners & CornerBottomLeft ) { path.lineTo( rect.bottomLeft() - QPointF( 0, radius ) ); path.arcTo( QRectF( rect.bottomLeft() - QPointF( 0, 2*radius ), cornerSize ), 180, 90 ); } else path.lineTo( rect.bottomLeft() ); // bottom right corner if( corners & CornerBottomRight ) { path.lineTo( rect.bottomRight() - QPointF( radius, 0 ) ); path.arcTo( QRectF( rect.bottomRight() - QPointF( 2*radius, 2*radius ), cornerSize ), 270, 90 ); } else path.lineTo( rect.bottomRight() ); // top right corner if( corners & CornerTopRight ) { path.lineTo( rect.topRight() + QPointF( 0, radius ) ); path.arcTo( QRectF( rect.topRight() - QPointF( 2*radius, 0 ), cornerSize ), 0, 90 ); } else path.lineTo( rect.topRight() ); path.closeSubpath(); return path; } //______________________________________________________________________ void Helper::drawFloatFrame( QPainter* p, const QRect r, const QColor& color, bool drawUglyShadow, bool isActive, const QColor& frameColor, TileSet::Tiles tiles ) { p->save(); p->setRenderHint( QPainter::Antialiasing ); const QRect frame( r.adjusted( 1,1,-1,-1 ) ); int x,y,w,h; frame.getRect( &x, &y, &w, &h ); QColor light( calcLightColor( backgroundTopColor( color ) ) ); QColor dark( calcLightColor( backgroundBottomColor( color ) ) ); p->setBrush( Qt::NoBrush ); if ( drawUglyShadow ) { if( isActive ) { //window active - it's a glow - not a shadow const QColor glow( KColorUtils::mix( QColor( 128,128,128 ), frameColor, 0.7 ) ); p->setPen( glow ); if( tiles & TileSet::Top ) { p->drawLine( QPointF( x+4, y-0.5 ), QPointF( x+w-4, y-0.5 ) ); p->drawArc( QRectF( x-0.5, y-0.5, 11, 11 ),90*16, 90*16 ); p->drawArc( QRectF( x+w-11+0.5, y-0.5, 11, 11 ), 0, 90*16 ); } if( tiles & TileSet::Left ) p->drawLine( QPointF( x-0.5, y+4 ), QPointF( x-0.5, y+h-4 ) ); if( tiles & TileSet::Right ) p->drawLine( QPointF( x+w+0.5, y+4 ), QPointF( x+w+0.5, y+h-4 ) ); if( tiles & TileSet::Bottom ) { if( tiles & TileSet::Left ) p->drawArc( QRectF( x-0.5, y+h-11+0.5, 11, 11 ),180*16, 90*16 ); if( tiles & TileSet::Right ) p->drawArc( QRectF( x+w-11+0.5, y+h-11+0.5, 11, 11 ),270*16, 90*16 ); p->drawLine( QPointF( x+4, y+h+0.5 ), QPointF( x+w-4, y+h+0.5 ) ); } light = KColorUtils::mix( light, frameColor ); dark = KColorUtils::mix( dark, frameColor ); } else { // window inactive - draw something resembling shadow // fully desaturate const QColor shadow( KColorUtils::darken( color, 0.0, 0.0 ) ); if( tiles & TileSet::Top ) { p->setPen( KColorUtils::darken( shadow, 0.2 ) ); p->drawLine( QPointF( x+4, y-0.5 ), QPointF( x+w-4, y-0.5 ) ); if( tiles & TileSet::Left ) p->drawArc( QRectF( x-0.5, y-0.5, 11, 11 ),90*16, 90*16 ); if( tiles & TileSet::Right ) p->drawArc( QRectF( x+w-11+0.5, y-0.5, 11, 11 ), 0, 90*16 ); } p->setPen( KColorUtils::darken( shadow, 0.35 ) ); if( tiles & TileSet::Left ) p->drawLine( QPointF( x-0.5, y+4 ), QPointF( x-0.5, y+h-4 ) ); if( tiles & TileSet::Right ) p->drawLine( QPointF( x+w+0.5, y+4 ), QPointF( x+w+0.5, y+h-4 ) ); if( tiles & TileSet::Bottom ) { p->setPen( KColorUtils::darken( shadow, 0.45 ) ); if( tiles & TileSet::Left ) p->drawArc( QRectF( x-0.5, y+h-11+0.5, 11, 11 ),180*16, 90*16 ); if( tiles & TileSet::Right ) p->drawArc( QRectF( x+w-11+0.5, y+h-11+0.5, 11, 11 ),270*16, 90*16 ); p->setPen( KColorUtils::darken( shadow, 0.6 ) ); p->drawLine( QPointF( x+4, y+h+0.5 ), QPointF( x+w-4, y+h+0.5 ) ); } } } // top frame if( tiles & TileSet::Top ) { p->setPen( QPen( light, 0.8 ) ); p->drawLine( QPointF( x+4, y+0.6 ), QPointF( x+w-4, y+0.6 ) ); } // corner and side frames // sides are drawn even if Top only is selected, but with a different gradient if( h >= 4+1.5 ) { QLinearGradient lg( 0.0, y+1.5, 0.0, y+h-4 ); lg.setColorAt( 0, light ); lg.setColorAt( 1, alphaColor( light, 0 ) ); if( h > 20.5 ) lg.setColorAt( qMax( 0.0, 1.0 - 12.0/( h-5.5 ) ), alphaColor( light, 0.5 ) ); else if( h > 8.5 ) lg.setColorAt( qMax( 0.0, 3.0/( h-5.5 ) ), alphaColor( light, 0.5 ) ); p->setPen( QPen( lg, 0.8 ) ); if( tiles & TileSet::Left ) p->drawLine( QPointF( x+0.6, y+4 ), QPointF( x+0.6, y+h-4 ) ); if( tiles & TileSet::Right ) p->drawLine( QPointF( x+w-0.6, y+4 ), QPointF( x+w-0.6, y+h-4 ) ); } if( tiles & TileSet::Top ) { const qreal offset = 0.5; const qreal arc( 7.0 ); p->drawArc( QRectF( x+offset, y+offset, arc, arc ),90*16, 90*16 ); p->drawArc( QRectF( x+w-arc-offset, y+offset, arc, arc ), 0, 90*16 ); } p->restore(); } //______________________________________________________________________________________ void Helper::drawSeparator( QPainter* p, const QRect& rect, const QColor& color, Qt::Orientation orientation ) { QColor light( calcLightColor( color ) ); QColor dark( calcDarkColor( color ) ); p->save(); p->setRenderHint( QPainter::Antialiasing,false ); QPoint start,end,offset; if ( orientation == Qt::Horizontal ) { start = QPoint( rect.x(),rect.y()+rect.height()/2-1 ); end = QPoint( rect.right(),rect.y()+rect.height()/2-1 ); offset = QPoint( 0,1 ); } else { start = QPoint( rect.x()+rect.width()/2-1,rect.y() ); end = QPoint( rect.x()+rect.width()/2-1,rect.bottom() ); offset = QPoint( 1,0 ); light.setAlpha( 150 ); } QLinearGradient lg( start,end ); lg.setColorAt( 0.3, dark ); lg.setColorAt( 0.7, dark ); dark.setAlpha( 0 ); lg.setColorAt( 0.0, dark ); lg.setColorAt( 1.0, dark ); p->setPen( QPen( lg,1 ) ); if ( orientation == Qt::Horizontal ) p->drawLine( start,end ); else p->drawLine( start+offset,end+offset ); lg = QLinearGradient( start,end ); lg.setColorAt( 0.3, light ); lg.setColorAt( 0.7, light ); light.setAlpha( 0 ); lg.setColorAt( 0.0, light ); lg.setColorAt( 1.0, light ); p->setPen( QPen( lg,1 ) ); if ( orientation == Qt::Horizontal ) p->drawLine( start+offset,end+offset ); else { p->drawLine( start,end ); p->drawLine( start+offset*2,end+offset*2 ); } p->restore(); } //____________________________________________________________________ const QWidget* Helper::checkAutoFillBackground( const QWidget* w ) const { if( !w ) return nullptr; if( w->autoFillBackground() ) return w; if( w->isWindow() ) return 0; for( const QWidget* parent = w->parentWidget(); parent!=0; parent = parent->parentWidget() ) { if( parent->autoFillBackground() ) return parent; if( parent == w->window() ) break; } return nullptr; } //____________________________________________________________________ void Helper::setHasBackgroundGradient( WId id, bool value ) const { #if OXYGEN_HAVE_X11 setHasHint( id, _backgroundGradientAtom, value ); #else Q_UNUSED( id ); Q_UNUSED( value ); #endif return; } //____________________________________________________________________ bool Helper::hasBackgroundGradient( WId id ) const { #if OXYGEN_HAVE_X11 return hasHint( id, _backgroundGradientAtom ); #else Q_UNUSED( id ); return false; #endif } //______________________________________________________________________________________ QPixmap Helper::highDpiPixmap( int width, int height ) const { - #if QT_VERSION >= 0x050300 const qreal dpiRatio( qApp->devicePixelRatio() ); QPixmap pixmap( width*dpiRatio, height*dpiRatio ); pixmap.setDevicePixelRatio( dpiRatio ); return pixmap; - #else - return QPixmap( width, height ); - #endif } //______________________________________________________________________________________ qreal Helper::devicePixelRatio( const QPixmap& pixmap ) const { - #if QT_VERSION >= 0x050300 return pixmap.devicePixelRatio(); - #else - Q_UNUSED(pixmap); - return 1; - #endif } //______________________________________________________________________________ bool Helper::isX11( void ) { #if OXYGEN_HAVE_X11 - #if QT_VERSION >= 0x050000 static const bool s_isX11 = KWindowSystem::isPlatformX11(); return s_isX11; - #else - return true; - #endif #endif return false; } bool Helper::isWayland( void ) { - #if QT_VERSION >= 0x050000 static const bool s_isWayland = KWindowSystem::isPlatformWayland(); return s_isWayland; - #else - return false; - #endif } #if OXYGEN_HAVE_X11 //____________________________________________________________________ xcb_connection_t* Helper::connection( void ) { - #if QT_VERSION >= 0x050000 return QX11Info::connection(); - #else - static xcb_connection_t* connection = nullptr; - if( !connection ) - { - Display* display = QX11Info::display(); - if( display ) connection = XGetXCBConnection( display ); - } - return connection; - #endif } //____________________________________________________________________ xcb_atom_t Helper::createAtom( const QString& name ) const { if( !isX11() ) return 0; xcb_intern_atom_cookie_t cookie( xcb_intern_atom( connection(), false, name.size(), qPrintable( name ) ) ); ScopedPointer reply( xcb_intern_atom_reply( connection(), cookie, nullptr) ); return reply ? reply->atom:0; } #endif //___________________________________________________________________________________________ void Helper::drawShadow( QPainter& painter, const QColor& color, int size ) { const qreal m( qreal( size-2 )*0.5 ); const qreal offset( 0.8 ); const qreal k0( ( m-4.0 ) / m ); QRadialGradient shadowGradient( m+1.0, m+offset+1.0, m ); for ( int i = 0; i < 8; i++ ) { // sinusoidal gradient const qreal k1( ( k0 * qreal( 8 - i ) + qreal( i ) ) * 0.125 ); const qreal a( ( cos( M_PI * i * 0.125 ) + 1.0 ) * 0.30 ); shadowGradient.setColorAt( k1, alphaColor( color, a * _shadowGain ) ); } shadowGradient.setColorAt( 1.0, alphaColor( color, 0.0 ) ); painter.save(); painter.setBrush( shadowGradient ); painter.drawEllipse( QRectF( 0, 0, size, size ) ); painter.restore(); } //_______________________________________________________________________ void Helper::drawOuterGlow( QPainter& painter, const QColor& color, int size ) { const QRectF r( 0, 0, size, size ); const qreal m( qreal( size )*0.5 ); const qreal width( 3 ); const qreal bias( _glowBias * qreal( 14 )/size ); // k0 is located at width - bias from the outer edge const qreal gm( m + bias - 0.9 ); const qreal k0( ( m-width+bias ) / gm ); QRadialGradient glowGradient( m, m, gm ); for ( int i = 0; i < 8; i++ ) { // k1 grows linearly from k0 to 1.0 const qreal k1( k0 + qreal( i )*( 1.0-k0 )/8.0 ); // a folows sqrt curve const qreal a( 1.0 - sqrt( qreal( i )/8 ) ); glowGradient.setColorAt( k1, alphaColor( color, a ) ); } // glow painter.save(); painter.setBrush( glowGradient ); painter.drawEllipse( r ); // inside mask painter.setCompositionMode( QPainter::CompositionMode_DestinationOut ); painter.setBrush( Qt::black ); painter.drawEllipse( r.adjusted( width+0.5, width+0.5, -width-1, -width-1 ) ); painter.restore(); } #if OXYGEN_HAVE_X11 //____________________________________________________________________ void Helper::setHasHint( xcb_window_t id, xcb_atom_t atom, bool value ) const { if( !isX11() ) return; // check window id if( !id ) return; quint32 uLongValue( value ); xcb_change_property( connection(), XCB_PROP_MODE_REPLACE, id, atom, XCB_ATOM_CARDINAL, 32, 1, &uLongValue ); xcb_flush( connection() ); return; } //____________________________________________________________________ bool Helper::hasHint( xcb_window_t id, xcb_atom_t atom ) const { if( !isX11() ) return false; // check window id if( !id ) return false; xcb_get_property_cookie_t cookie( xcb_get_property( connection(), 0, id, atom, XCB_ATOM_CARDINAL, 0, 1) ); ScopedPointer reply( xcb_get_property_reply( connection(), cookie, nullptr ) ); return reply && xcb_get_property_value_length( reply.data() ) && reinterpret_cast(xcb_get_property_value( reply.data() ) )[0]; } #endif //____________________________________________________________________ void Helper::init( void ) { - #if OXYGEN_USE_KDE4 - _contrast = KGlobalSettings::contrastF( _config ); - #else _contrast = KColorScheme::contrastF( _config ); - #endif // background contrast is calculated so that it is 0.9 // when KGlobalSettings contrast value of 0.7 _bgcontrast = qMin( 1.0, 0.9*_contrast/0.7 ); _backgroundCache.setMaxCost( 64 ); #if OXYGEN_HAVE_X11 if( isX11() ) { _backgroundGradientAtom = createAtom( QStringLiteral( "_KDE_OXYGEN_BACKGROUND_GRADIENT" ) ); } else { _backgroundGradientAtom = 0; } #endif } } diff --git a/liboxygen/oxygenhelper.h b/liboxygen/oxygenhelper.h index 37c36fe7..65eb9a45 100644 --- a/liboxygen/oxygenhelper.h +++ b/liboxygen/oxygenhelper.h @@ -1,530 +1,516 @@ #ifndef oxygen_helper_h #define oxygen_helper_h /* * Copyright 2016 Michael Pyne * Copyright 2009 Hugo Pereira Da Costa * Copyright 2008 Long Huynh Huu * Copyright 2007 Matthew Woehlke * Copyright 2007 Casper Boemann * Copyright 2007 Fredrik H?glund * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "oxygentileset.h" #include "config-liboxygen.h" #include "liboxygen.h" #include #include -#if OXYGEN_USE_KDE4 -#include -#endif - #include #include #include #include #include #include #include #include #if OXYGEN_HAVE_X11 #include #endif namespace Oxygen { template class BaseCache: public QCache { public: //* constructor BaseCache( int maxCost ): QCache( maxCost ), _enabled( true ) {} //* constructor explicit BaseCache( void ): _enabled( true ) {} //* destructor ~BaseCache( void ) {} //* enable void setEnabled( bool value ) { _enabled = value; } //* enable state bool enabled( void ) const { return _enabled; } //* access T* object( const quint64& key ) { return _enabled ? QCache::object( key ) : 0; } //* max cost void setMaxCost( int cost ) { if( cost <= 0 ) { QCache::clear(); QCache::setMaxCost( 1 ); setEnabled( false ); } else { setEnabled( true ); QCache::setMaxCost( cost ); } } private: //* enable flag bool _enabled; }; /** * Holds up to a limited number of items keyed by quint64. If items must be * removed to fall within limit, removes those added the earliest. */ template class FIFOCache { using CachePair = QPair; public: //* constructor FIFOCache(size_t _limit = 256) : m_limit(_limit) {} //* insert void insert(quint64 key, T value) { if (static_cast(m_queue.size()) > m_limit) { (void) m_queue.dequeue(); } m_queue.enqueue( CachePair( key, value) ); } //* find T find(quint64 key) const { for(const auto &item : m_queue) { if (item.first == key) return item.second; } return T(); } //* for_each template void for_each(F f) { for(auto &item : m_queue) { f(item.second); } } //* maxCost void setMaxCost( size_t max ) { m_limit = max; while (static_cast(m_queue.size()) > m_limit) { (void) m_queue.dequeue(); } } //* maxCost size_t maxCost() const { return m_limit; } //* clear void clear() { m_queue.clear(); } private: //* queue QQueue m_queue; //* max size size_t m_limit; }; template class Cache { public: //* constructor Cache() {} //* destructor ~Cache() {} using Value = QSharedPointer>; //* return cache matching a given key Value get( const QColor& color ) { const quint64 key = ( color.isValid() ? color.rgba():0 ); Value retValue = data_.find( key ); if ( !retValue ) { retValue = Value( new BaseCache( data_.maxCost() ) ); data_.insert( key, retValue ); } return retValue; } //* clear void clear( void ) { data_.clear(); } //* max cache size void setMaxCacheSize( int value ) { data_.setMaxCost( value ); data_.for_each( [value] (Value item) { item->setMaxCost( value );} ); } private: //* data FIFOCache data_; }; //* oxygen style helper class. /** contains utility functions used at multiple places in both oxygen style and oxygen window decoration */ class OXYGEN_EXPORT Helper { public: //* constructor explicit Helper( KSharedConfig::Ptr config ); - #if OXYGEN_USE_KDE4 - //* constructor - explicit Helper( const QByteArray& ); - #endif - //* destructor virtual ~Helper() {} //* load configuration virtual void loadConfig(); //* pointer to shared config KSharedConfig::Ptr config() const; //* reset all caches virtual void invalidateCaches(); //* update maximum cache size virtual void setMaxCacheSize( int ); //*@name window background gradients //@{ /** \par y_shift: shift the background gradient upwards, to fit with the windec \par gradientHeight: the height of the generated gradient. for different heights, the gradient is translated so that it is always at the same position from the bottom */ virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QPalette& pal, int y_shift=-23 ) { renderWindowBackground( p, clipRect, widget, pal.color( widget->window()->backgroundRole() ), y_shift ); } /** y_shift: shift the background gradient upwards, to fit with the windec gradientHeight: the height of the generated gradient. for different heights, the gradient is translated so that it is always at the same position from the bottom */ virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, const QPalette& pal, int y_shift=-23 ) { renderWindowBackground( p, clipRect, widget, window, pal.color( window->backgroundRole() ), y_shift ); } //* render window background using a given color as a reference virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QColor& color, int y_shift=-23 ) { renderWindowBackground( p, clipRect, widget, widget->window(), color, y_shift ); } //* render window background using a given color as a reference virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, const QColor& color, int y_shift=-23 ); virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QRect& windowRect, const QColor& color, int y_shift ); //@} //* dots void renderDot( QPainter*, const QPoint&, const QColor& ); //* returns true for too 'dark' colors bool lowThreshold( const QColor& color ); //* returns true for too 'light' colors bool highThreshold( const QColor& color ); //* add alpha channel multiplier to color static QColor alphaColor( QColor color, qreal alpha ); //* calculated light color from argument virtual QColor calcLightColor( const QColor& color ); //* calculated dark color from argument virtual QColor calcDarkColor( const QColor& color ); //* calculated shadow color from argument virtual QColor calcShadowColor( const QColor& color ); //* returns menu background color matching position in a given top level widget virtual QColor backgroundColor( const QColor& color, const QWidget* w, const QPoint& point ) { if( !( w && w->window() ) || checkAutoFillBackground( w ) ) return color; else return backgroundColor( color, w->window()->height(), w->mapTo( w->window(), point ).y() ); } //* returns menu background color matching position in a top level widget of given height virtual QColor backgroundColor( const QColor& color, int height, int y ) { return backgroundColor( color, qMin( qreal( 1.0 ), qreal( y )/qMin( 300, 3*height/4 ) ) ); } //* color used for background radial gradient virtual QColor backgroundRadialColor( const QColor& color ); //* color used at the top of window background virtual QColor backgroundTopColor( const QColor& color ); //* color used at the bottom of window background virtual QColor backgroundBottomColor( const QColor& color ); //* vertical gradient for window background virtual QPixmap verticalGradient( const QColor& color, int height, int offset = 0 ); //* radial gradient for window background virtual QPixmap radialGradient( const QColor& color, int width, int height = 20 ); //* merge background and front color for check marks, arrows, etc. using _contrast virtual QColor decoColor( const QColor& background, const QColor& color ); //* returns a region matching given rect, with rounded corners, based on the multipliers /** setting any of the multipliers to zero will result in no corners shown on the corresponding side */ virtual QRegion roundedMask( const QRect&, int left = 1, int right = 1, int top = 1, int bottom = 1 ) const; //* returns a region matching given rect, with rounded corners virtual QBitmap roundedMask( const QSize&, Corners corners = AllCorners, qreal radius = 4 ) const; //* return rounded path in a given rect, with only selected corners rounded, and for a given radius QPainterPath roundedPath( const QRect&, Corners = AllCorners, qreal = 4 ) const; //* draw frame that mimics some sort of shadows around a panel /** it is used for menus, detached dock panels and toolbar, as well as window decoration when compositing is disabled */ virtual void drawFloatFrame( QPainter* p, const QRect r, const QColor& color, bool drawUglyShadow=true, bool isActive=false, const QColor& frameColor=QColor(), TileSet::Tiles tiles = TileSet::Ring ); //* draw dividing line virtual void drawSeparator( QPainter*, const QRect&, const QColor&, Qt::Orientation ); //* focus color QColor focusColor( const QPalette& palette ) const { return _viewFocusBrush.brush( palette ).color(); } //* hover color QColor hoverColor( const QPalette& palette ) const { return _viewHoverBrush.brush( palette ).color(); } //* negative text color QColor negativeTextColor( const QPalette& palette ) const { return _viewNegativeTextBrush.brush( palette ).color(); } //* focus color QColor focusColor( QPalette::ColorGroup group ) const { return _viewFocusBrush.brush( group ).color(); } //* hover color QColor hoverColor( QPalette::ColorGroup group ) const { return _viewHoverBrush.brush( group ).color(); } //* negative text color QColor negativeTextColor( QPalette::ColorGroup group ) const { return _viewNegativeTextBrush.brush( group ).color(); } /** returns first widget in parent chain that sets autoFillBackground to true, or nullptr if none */ const QWidget* checkAutoFillBackground( const QWidget* ) const; //*@name background gradient XProperty //@{ //* set background gradient hint to widget virtual void setHasBackgroundGradient( WId, bool ) const; //* true if background gradient hint is set virtual bool hasBackgroundGradient( WId ) const; //@} //@name high dpi utility functions //@{ //* return dpi-aware pixmap of given size virtual QPixmap highDpiPixmap( const QSize& size ) const { return highDpiPixmap( size.width(), size.height() ); } //* return dpi-aware pixmap of given size virtual QPixmap highDpiPixmap( int width ) const { return highDpiPixmap( width, width ); } //* return dpi-aware pixmap of given size virtual QPixmap highDpiPixmap( int width, int height ) const; //* return device pixel ratio for a given pixmap virtual qreal devicePixelRatio( const QPixmap& ) const; //@} //*@name compositing utilities //@{ //* true if style was compiled for and is running on X11 static bool isX11( void ); //* true if running on platform Wayland static bool isWayland( void ); //@} #if OXYGEN_HAVE_X11 //* xcb connection static xcb_connection_t* connection( void ); //* create xcb atom xcb_atom_t createAtom( const QString& ) const; #endif //* scoped pointer convenience typedef template using ScopedPointer = QScopedPointer; protected: //* return color key for a given color, properly accounting for invalid colors quint64 colorKey( const QColor& color ) const { return color.isValid() ? color.rgba():0; } //* generic outer shadow (to be stored in tilesets) virtual void drawShadow( QPainter&, const QColor&, int size ); //* generic outer glow (to be stored in tilesets) virtual void drawOuterGlow( QPainter&, const QColor&, int size ); //* return background adjusted color matching relative vertical position in window QColor backgroundColor( const QColor&, qreal ratio ); //*@name global configuration parameters //@{ static const qreal _glowBias; static const qreal _slabThickness; static const qreal _shadowGain; qreal _contrast; //@} //* shortcut to color caches /** it is made protected because it is also used in the style helper */ using ColorCache = BaseCache; //* shortcut to pixmap cache using PixmapCache = BaseCache; private: //* initialize void init( void ); - #if OXYGEN_USE_KDE4 - //* component data - KComponentData _componentData; - #endif - //* configuration KSharedConfig::Ptr _config; qreal _bgcontrast; //*@name brushes //@{ KStatefulBrush _viewFocusBrush; KStatefulBrush _viewHoverBrush; KStatefulBrush _viewNegativeTextBrush; //@} //*@name color caches //@{ ColorCache _decoColorCache; ColorCache _lightColorCache; ColorCache _darkColorCache; ColorCache _shadowColorCache; ColorCache _backgroundTopColorCache; ColorCache _backgroundBottomColorCache; ColorCache _backgroundRadialColorCache; ColorCache _backgroundColorCache; //@} PixmapCache _backgroundCache; PixmapCache _dotCache; //* high threshold colors using ColorMap = QMap; ColorMap _highThreshold; ColorMap _lowThreshold; #if OXYGEN_HAVE_X11 //* set value for given hint void setHasHint( xcb_window_t, xcb_atom_t, bool ) const; //* value for given hint bool hasHint( xcb_window_t, xcb_atom_t ) const; //* background gradient hint atom xcb_atom_t _backgroundGradientAtom; #endif bool _isX11; }; } #endif diff --git a/liboxygen/oxygenshadowcache.cpp b/liboxygen/oxygenshadowcache.cpp index b95f47ce..88da9494 100644 --- a/liboxygen/oxygenshadowcache.cpp +++ b/liboxygen/oxygenshadowcache.cpp @@ -1,547 +1,542 @@ ////////////////////////////////////////////////////////////////////////////// // oxygenshadowcache.cpp // handles caching of TileSet objects to draw shadows // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygenshadowcache.h" #include "oxygenactiveshadowconfiguration.h" #include "oxygeninactiveshadowconfiguration.h" #include #include #include #include namespace Oxygen { //* square utility function static qreal square( qreal x ) { return x*x; } //* functions used to draw shadows class Parabolic { public: //* constructor Parabolic( qreal amplitude, qreal width ): amplitude_( amplitude ), width_( width ) {} //* destructor virtual ~Parabolic( void ) {} //* value virtual qreal operator() ( qreal x ) const { return qMax( 0.0, amplitude_*(1.0 - square(x/width_) ) ); } private: qreal amplitude_; qreal width_; }; //* functions used to draw shadows class Gaussian { public: //* constructor Gaussian( qreal amplitude, qreal width ): amplitude_( amplitude ), width_( width ) {} //* destructor virtual ~Gaussian( void ) {} //* value virtual qreal operator() ( qreal x ) const { return qMax( 0.0, amplitude_*(std::exp( -square(x/width_) -0.05 ) ) ); } private: qreal amplitude_; qreal width_; }; //_______________________________________________________ ShadowCache::ShadowCache( Helper& helper ): _helper( helper ), _enabled( true ), _activeShadowSize( 40 ), _inactiveShadowSize( 40 ) { setMaxIndex( 256 ); } //_______________________________________________________ void ShadowCache::readConfig( void ) { if( !_enabled ) setEnabled( true ); // shadows - #if OXYGEN_USE_KDE4 - ActiveShadowConfiguration::self()->readConfig(); - InactiveShadowConfiguration::self()->readConfig(); - #else ActiveShadowConfiguration::self()->load(); InactiveShadowConfiguration::self()->load(); - #endif // copy sizes to local _activeShadowSize = ActiveShadowConfiguration::shadowSize(); _inactiveShadowSize = InactiveShadowConfiguration::shadowSize(); // invalidate caches invalidateCaches(); } //_______________________________________________________ void ShadowCache::setAnimationsDuration( int value ) { setMaxIndex( qMin( 256, int( (120*value)/1000 ) ) ); invalidateCaches(); } //_______________________________________________________ bool ShadowCache::isEnabled( QPalette::ColorGroup group ) const { if( group == QPalette::Active ) return ActiveShadowConfiguration::enabled(); else if( group == QPalette::Inactive ) return InactiveShadowConfiguration::enabled(); else return false; } //_______________________________________________________ void ShadowCache::setShadowSize( QPalette::ColorGroup group, int size ) { if( group == QPalette::Active && _activeShadowSize != size ) { _activeShadowSize = size; invalidateCaches(); } else if( group == QPalette::Inactive && _inactiveShadowSize != size ) { _inactiveShadowSize = size; invalidateCaches(); } } //_______________________________________________________ int ShadowCache::shadowSize( void ) const { int activeSize( ActiveShadowConfiguration::enabled() ? _activeShadowSize:0 ); int inactiveSize( InactiveShadowConfiguration::enabled() ? _inactiveShadowSize:0 ); // even if shadows are disabled, return qMax( activeSize, inactiveSize ); } //_______________________________________________________ TileSet ShadowCache::tileSet( const Key& key ) { // check if tileSet already in cache int hash( key.hash() ); if( _enabled ) { if( TileSet* cachedTileSet = _shadowCache.object( hash ) ) { return *cachedTileSet; } } // create tileSet otherwise const qreal size( shadowSize() + overlap ); TileSet tileSet( pixmap( key ), size, size, size, size, size, size, 1, 1); _shadowCache.insert( hash, new TileSet( tileSet ) ); return tileSet; } //_______________________________________________________ TileSet ShadowCache::tileSet( Key key, qreal opacity ) { int index( opacity*_maxIndex ); Q_ASSERT( index <= _maxIndex ); // construct key key.index = index; // check if tileSet already in cache int hash( key.hash() ); if( _enabled ) { if( TileSet* cachedTileSet = _animatedShadowCache.object(hash) ) { return *cachedTileSet; } } // create shadow and tileset otherwise const qreal size( shadowSize() + overlap ); TileSet tileSet( animatedPixmap( key, opacity ), size, size, 1, 1); _animatedShadowCache.insert( hash, new TileSet( tileSet ) ); return tileSet; } //_______________________________________________________ QPixmap ShadowCache::animatedPixmap( const Key& key, qreal opacity ) { // create shadow and tileset otherwise const qreal size( shadowSize() + overlap ); QPixmap shadow( _helper.highDpiPixmap( size*2 ) ); shadow.fill( Qt::transparent ); QPainter painter( &shadow ); painter.setRenderHint( QPainter::Antialiasing ); QPixmap inactiveShadow( pixmap( key, false ) ); if( !inactiveShadow.isNull() ) { QPainter local( &inactiveShadow ); local.setRenderHint( QPainter::Antialiasing ); local.setCompositionMode(QPainter::CompositionMode_DestinationIn); local.fillRect( inactiveShadow.rect(), QColor( 0, 0, 0, 255*(1.0-opacity ) ) ); } QPixmap activeShadow( pixmap( key, true ) ); if( !activeShadow.isNull() ) { QPainter local( &activeShadow ); local.setRenderHint( QPainter::Antialiasing ); local.setCompositionMode(QPainter::CompositionMode_DestinationIn); local.fillRect( activeShadow.rect(), QColor( 0, 0, 0, 255*( opacity ) ) ); } painter.drawPixmap( QPointF(0,0), inactiveShadow ); painter.drawPixmap( QPointF(0,0), activeShadow ); painter.end(); return shadow; } //_______________________________________________________ QPixmap ShadowCache::pixmap( const Key& key, bool active ) const { static const qreal fixedSize = 25.5; qreal size( shadowSize() ); qreal shadowSize( 0 ); if( active && ActiveShadowConfiguration::enabled() ) shadowSize = _activeShadowSize; else if( !active && InactiveShadowConfiguration::enabled() ) shadowSize = _inactiveShadowSize; if( !shadowSize ) return QPixmap(); // add overlap size += overlap; shadowSize += overlap; QPixmap shadow( _helper.highDpiPixmap( size*2 ) ); shadow.fill( Qt::transparent ); QPainter painter( &shadow ); painter.setRenderHint( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); // some gradients rendering are different at bottom corners if client has no border bool hasBorder( key.hasBorder || key.isShade ); if( active ) { { // inner (sharp) gradient const qreal gradientSize = qMin( shadowSize, (shadowSize+fixedSize)/2 ); const qreal voffset = qMin( 12.0*(gradientSize*ActiveShadowConfiguration::verticalOffset())/fixedSize, 4.0 ); QRadialGradient radialGradient = QRadialGradient( size, size + voffset, gradientSize ); radialGradient.setColorAt(1, Qt::transparent ); // gaussian shadow is used int nPoints( (10*gradientSize)/fixedSize ); Gaussian f( 0.85, 0.17 ); QColor c = ActiveShadowConfiguration::innerColor(); for( int i = 0; i < nPoints; i++ ) { qreal x = qreal(i)/nPoints; c.setAlphaF( f(x) ); radialGradient.setColorAt( x, c ); } painter.setBrush( radialGradient ); renderGradient( painter, shadow.rect(), radialGradient, hasBorder ); } { // outer (spread) gradient const qreal gradientSize = shadowSize; const qreal voffset = qMin( 12.0*(gradientSize*ActiveShadowConfiguration::verticalOffset())/fixedSize, 4.0 ); QRadialGradient radialGradient = QRadialGradient( size, size+voffset, gradientSize ); radialGradient.setColorAt(1, Qt::transparent ); // gaussian shadow is used int nPoints( (10*gradientSize)/fixedSize ); Gaussian f( 0.46, 0.34 ); QColor c = ActiveShadowConfiguration::useOuterColor() ? ActiveShadowConfiguration::outerColor():ActiveShadowConfiguration::innerColor(); for( int i = 0; i < nPoints; i++ ) { qreal x = qreal(i)/nPoints; c.setAlphaF( f(x) ); radialGradient.setColorAt( x, c ); } painter.setBrush( radialGradient ); painter.drawRect( shadow.rect() ); } } else { { // inner (sharp gradient) const qreal gradientSize = qMin( shadowSize, fixedSize ); const qreal voffset( 0.2 ); QRadialGradient radialGradient = QRadialGradient( size, size+voffset, gradientSize ); radialGradient.setColorAt(1, Qt::transparent ); // parabolic shadow is used int nPoints( (10*gradientSize)/fixedSize ); Parabolic f( 1.0, 0.22 ); QColor c = InactiveShadowConfiguration::useOuterColor() ? InactiveShadowConfiguration::outerColor():InactiveShadowConfiguration::innerColor(); for( int i = 0; i < nPoints; i++ ) { qreal x = qreal(i)/nPoints; c.setAlphaF( f(x) ); radialGradient.setColorAt( x, c ); } painter.setBrush( radialGradient ); renderGradient( painter, shadow.rect(), radialGradient, hasBorder ); } { // mid gradient const qreal gradientSize = qMin( shadowSize, (shadowSize+2*fixedSize)/3 ); const qreal voffset = qMin( 8.0*(gradientSize*InactiveShadowConfiguration::verticalOffset())/fixedSize, 4.0 ); // gaussian shadow is used QRadialGradient radialGradient = QRadialGradient( size, size+voffset, gradientSize ); radialGradient.setColorAt(1, Qt::transparent ); int nPoints( (10*gradientSize)/fixedSize ); Gaussian f( 0.54, 0.21); QColor c = InactiveShadowConfiguration::useOuterColor() ? InactiveShadowConfiguration::outerColor():InactiveShadowConfiguration::innerColor(); for( int i = 0; i < nPoints; i++ ) { qreal x = qreal(i)/nPoints; c.setAlphaF( f(x) ); radialGradient.setColorAt( x, c ); } painter.setBrush( radialGradient ); painter.drawRect( shadow.rect() ); } { // outer (spread) gradient const qreal gradientSize = shadowSize; const qreal voffset = qMin( 20.0*(gradientSize*InactiveShadowConfiguration::verticalOffset())/fixedSize, 4.0 ); // gaussian shadow is used QRadialGradient radialGradient = QRadialGradient( size, size+voffset, gradientSize ); radialGradient.setColorAt(1, Qt::transparent ); int nPoints( (20*gradientSize)/fixedSize ); Gaussian f( 0.155, 0.445); QColor c = InactiveShadowConfiguration::useOuterColor() ? InactiveShadowConfiguration::outerColor():InactiveShadowConfiguration::innerColor(); for( int i = 0; i < nPoints; i++ ) { qreal x = qreal(i)/nPoints; c.setAlphaF( f(x) ); radialGradient.setColorAt( x, c ); } painter.setBrush( radialGradient ); painter.drawRect( shadow.rect() ); } } // mask painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); painter.setBrush( Qt::black ); painter.drawEllipse( QRectF( size-3, size-3, 6, 6 ) ); painter.end(); return shadow; } //_______________________________________________________ void ShadowCache::renderGradient( QPainter& painter, const QRectF& rect, const QRadialGradient& radialGradient, bool hasBorder ) const { if( hasBorder ) { painter.setBrush( radialGradient ); painter.drawRect( rect ); return; } const qreal size( rect.width()/2.0 ); const qreal hoffset( radialGradient.center().x() - size ); const qreal voffset( radialGradient.center().y() - size ); const qreal radius( radialGradient.radius() ); // load gradient stops QGradientStops stops( radialGradient.stops() ); // draw ellipse for the upper rect { QRectF rect( hoffset, voffset, 2*size-hoffset, size ); painter.setBrush( radialGradient ); painter.drawRect( rect ); } // draw square gradients for the lower rect { // vertical lines const QRectF rect( hoffset, size+voffset, 2*size-hoffset, 4 ); QLinearGradient lg( hoffset, 0.0, 2*size+hoffset, 0.0 ); for( int i = 0; icpp // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygenshadowconfigwidget.h" #include "oxygenactiveshadowconfiguration.h" #include "oxygeninactiveshadowconfiguration.h" #include "ui_oxygenshadowconfigurationui.h" #include "config-liboxygen.h" #include #include #include namespace Oxygen { //_________________________________________________________ ShadowConfigWidget::ShadowConfigWidget( QWidget* parent ): QGroupBox( parent ), ui( new Ui_ShadowConfiguraionUI() ) { setCheckable( true ); ui->setupUi( this ); // connections connect( ui->shadowSize, SIGNAL(valueChanged(int)), SLOT(updateChanged()) ); connect( ui->verticalOffset, SIGNAL(valueChanged(int)), SLOT(updateChanged()) ); connect( ui->innerColor, SIGNAL(changed(QColor)), SLOT(updateChanged()) ); connect( ui->outerColor, SIGNAL(changed(QColor)), SLOT(updateChanged()) ); connect( ui->useOuterColor, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); connect( this, SIGNAL(toggled(bool)), SLOT(updateChanged()) ); } //_________________________________________________________ ShadowConfigWidget::~ShadowConfigWidget( void ) { delete ui; } //_________________________________________________________ void ShadowConfigWidget::save( void ) const { if( _group == QPalette::Active ) { ActiveShadowConfiguration::setShadowSize( ui->shadowSize->value() ); ActiveShadowConfiguration::setVerticalOffset( 0.1*ui->verticalOffset->value() ); ActiveShadowConfiguration::setInnerColor( ui->innerColor->color() ); ActiveShadowConfiguration::setOuterColor( ui->outerColor->color() ); ActiveShadowConfiguration::setUseOuterColor( ui->useOuterColor->isChecked() ); ActiveShadowConfiguration::setEnabled( isChecked() ); - #if OXYGEN_USE_KDE4 - ActiveShadowConfiguration::self()->writeConfig(); - #else ActiveShadowConfiguration::self()->save(); - #endif } else if( _group == QPalette::Inactive ) { InactiveShadowConfiguration::setShadowSize( ui->shadowSize->value() ); InactiveShadowConfiguration::setVerticalOffset( 0.1*ui->verticalOffset->value() ); InactiveShadowConfiguration::setInnerColor( ui->innerColor->color() ); InactiveShadowConfiguration::setOuterColor( ui->outerColor->color() ); InactiveShadowConfiguration::setUseOuterColor( ui->useOuterColor->isChecked() ); InactiveShadowConfiguration::setEnabled( isChecked() ); - #if OXYGEN_USE_KDE4 - InactiveShadowConfiguration::self()->writeConfig(); - #else InactiveShadowConfiguration::self()->save(); - #endif } } //_________________________________________________________ void ShadowConfigWidget::updateChanged( void ) { if( _group == QPalette::Active ) { setChanged( ( ui->shadowSize->value() != ActiveShadowConfiguration::shadowSize() ) || ( ui->verticalOffset->value() != 10*ActiveShadowConfiguration::verticalOffset() ) || ( ui->innerColor->color() != ActiveShadowConfiguration::innerColor() ) || ( ui->useOuterColor->isChecked() != ActiveShadowConfiguration::useOuterColor() ) || ( ui->outerColor->color() != ActiveShadowConfiguration::outerColor() ) || ( isChecked() != ActiveShadowConfiguration::enabled() ) ); } else if( _group == QPalette::Inactive ) { setChanged( ( ui->shadowSize->value() != InactiveShadowConfiguration::shadowSize() ) || ( ui->verticalOffset->value() != 10*InactiveShadowConfiguration::verticalOffset() ) || ( ui->innerColor->color() != InactiveShadowConfiguration::innerColor() ) || ( ui->useOuterColor->isChecked() != InactiveShadowConfiguration::useOuterColor() ) || ( ui->outerColor->color() != InactiveShadowConfiguration::outerColor() ) || ( isChecked() != InactiveShadowConfiguration::enabled() ) ); } } //_________________________________________________________ void ShadowConfigWidget::load( bool defaults ) { if( _group == QPalette::Active ) { if( defaults ) ActiveShadowConfiguration::self()->setDefaults(); else { - #if OXYGEN_USE_KDE4 - ActiveShadowConfiguration::self()->readConfig(); - #else ActiveShadowConfiguration::self()->load(); - #endif } ui->shadowSize->setValue( ActiveShadowConfiguration::shadowSize() ); ui->verticalOffset->setValue( 10*ActiveShadowConfiguration::verticalOffset() ); ui->innerColor->setColor( ActiveShadowConfiguration::innerColor() ); ui->outerColor->setColor( ActiveShadowConfiguration::outerColor() ); ui->useOuterColor->setChecked( ActiveShadowConfiguration::useOuterColor() ); setChecked( ActiveShadowConfiguration::enabled() ); } else if( _group == QPalette::Inactive ) { if( defaults ) InactiveShadowConfiguration::self()->setDefaults(); else { - #if OXYGEN_USE_KDE4 - InactiveShadowConfiguration::self()->readConfig(); - #else InactiveShadowConfiguration::self()->load(); - #endif } ui->shadowSize->setValue( InactiveShadowConfiguration::shadowSize() ); ui->verticalOffset->setValue( 10*InactiveShadowConfiguration::verticalOffset() ); ui->innerColor->setColor( InactiveShadowConfiguration::innerColor() ); ui->outerColor->setColor( InactiveShadowConfiguration::outerColor() ); ui->useOuterColor->setChecked( InactiveShadowConfiguration::useOuterColor() ); setChecked( InactiveShadowConfiguration::enabled() ); } } } diff --git a/liboxygen/oxygentileset.cpp b/liboxygen/oxygentileset.cpp index 3d558987..e4093019 100644 --- a/liboxygen/oxygentileset.cpp +++ b/liboxygen/oxygentileset.cpp @@ -1,245 +1,235 @@ /* * Copyright 2009-2010 Hugo Pereira Da Costa * Copyright 2008 Long Huynh Huu * Copyright 2007 Matthew Woehlke * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "oxygentileset.h" #include namespace Oxygen { //___________________________________________________________ inline bool bits(TileSet::Tiles flags, TileSet::Tiles testFlags) { return (flags & testFlags) == testFlags; } //______________________________________________________________________________________ inline qreal devicePixelRatio( const QPixmap& pixmap ) { - #if QT_VERSION >= 0x050300 return pixmap.devicePixelRatio(); - #else - Q_UNUSED( pixmap ); - return 1; - #endif } //______________________________________________________________________________________ inline void setDevicePixelRatio( QPixmap& pixmap, qreal value ) { - #if QT_VERSION >= 0x050300 return pixmap.setDevicePixelRatio( value ); - #else - Q_UNUSED( pixmap ); - Q_UNUSED( value ); - #endif } //______________________________________________________________ int TileSet::_sideExtent = 32; //______________________________________________________________ void TileSet::initPixmap( PixmapList& pixmaps, const QPixmap &source, int width, int height, const QRect &rect) { QSize size( width, height ); if( !( size.isValid() && rect.isValid() ) ) { pixmaps.append( QPixmap() ); } else if( size != rect.size() ) { const qreal dpiRatio( devicePixelRatio( source ) ); const QRect scaledRect( rect.topLeft()*dpiRatio, rect.size()*dpiRatio ); const QSize scaledSize( size*dpiRatio ); const QPixmap tile( source.copy(scaledRect) ); QPixmap pixmap( scaledSize ); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.drawTiledPixmap(0, 0, scaledSize.width(), scaledSize.height(), tile); setDevicePixelRatio( pixmap, dpiRatio ); pixmaps.append( pixmap ); } else { const qreal dpiRatio( devicePixelRatio( source ) ); const QRect scaledRect( rect.topLeft()*dpiRatio, rect.size()*dpiRatio ); QPixmap pixmap( source.copy( scaledRect ) ); setDevicePixelRatio( pixmap, dpiRatio ); pixmaps.append( pixmap ); } } //______________________________________________________________ TileSet::TileSet( void ): _w1(0), _h1(0), _w3(0), _h3(0) { _pixmaps.reserve(9); } //______________________________________________________________ TileSet::TileSet(const QPixmap &source, int w1, int h1, int w2, int h2 ): _w1(w1), _h1(h1), _w3(0), _h3(0) { _pixmaps.reserve(9); if( source.isNull() ) return; _w3 = source.width()/devicePixelRatio( source ) - (w1 + w2); _h3 = source.height()/devicePixelRatio( source ) - (h1 + h2); int w = w2; int h = h2; // initialise pixmap array initPixmap( _pixmaps, source, _w1, _h1, QRect(0, 0, _w1, _h1) ); initPixmap( _pixmaps, source, w, _h1, QRect(_w1, 0, w2, _h1) ); initPixmap( _pixmaps, source, _w3, _h1, QRect(_w1+w2, 0, _w3, _h1) ); initPixmap( _pixmaps, source, _w1, h, QRect(0, _h1, _w1, h2) ); initPixmap( _pixmaps, source, w, h, QRect(_w1, _h1, w2, h2) ); initPixmap( _pixmaps, source, _w3, h, QRect(_w1+w2, _h1, _w3, h2) ); initPixmap( _pixmaps, source, _w1, _h3, QRect(0, _h1+h2, _w1, _h3) ); initPixmap( _pixmaps, source, w, _h3, QRect(_w1, _h1+h2, w2, _h3) ); initPixmap( _pixmaps, source, _w3, _h3, QRect(_w1+w2, _h1+h2, _w3, _h3) ); } //______________________________________________________________ TileSet::TileSet(const QPixmap &source, int w1, int h1, int w3, int h3, int x1, int y1, int w2, int h2 ): _w1(w1), _h1(h1), _w3(w3), _h3(h3) { _pixmaps.reserve(9); if( source.isNull() ) return; int x2 = source.width()/devicePixelRatio( source ) - _w3; int y2 = source.height()/devicePixelRatio( source ) - _h3; int w = w2; int h = h2; // initialise pixmap array initPixmap( _pixmaps, source, _w1, _h1, QRect(0, 0, _w1, _h1) ); initPixmap( _pixmaps, source, w, _h1, QRect(x1, 0, w2, _h1) ); initPixmap( _pixmaps, source, _w3, _h1, QRect(x2, 0, _w3, _h1) ); initPixmap( _pixmaps, source, _w1, h, QRect(0, y1, _w1, h2) ); initPixmap( _pixmaps, source, w, h, QRect(x1, y1, w2, h2) ); initPixmap( _pixmaps, source, _w3, h, QRect(x2, y1, _w3, h2) ); initPixmap( _pixmaps, source, _w1, _h3, QRect(0, y2, _w1, _h3) ); initPixmap( _pixmaps, source, w, _h3, QRect(x1, y2, w2, _h3) ); initPixmap( _pixmaps, source, _w3, _h3, QRect(x2, y2, _w3, _h3) ); } //___________________________________________________________ QRect TileSet::adjust(const QRect &constRect, Tiles tiles ) const { // adjust rect to deal with missing edges QRect rect( constRect ); if( !(tiles&Left) ) rect.adjust( -_w1, 0, 0, 0 ); if( !(tiles&Right) ) rect.adjust( 0, 0, _w3, 0 ); if( !(tiles&Top) ) rect.adjust( 0, -_h1, 0, 0 ); if( !(tiles&Bottom) ) rect.adjust( 0, 0, 0, _h3 ); return rect; } //___________________________________________________________ void TileSet::render(const QRect &constRect, QPainter *painter, Tiles tiles) const { const bool oldHint( painter->testRenderHint( QPainter::SmoothPixmapTransform ) ); painter->setRenderHint( QPainter::SmoothPixmapTransform, true ); // check initialization if( _pixmaps.size() < 9 ) return; // copy source rect QRect rect( constRect ); // get rect dimensions int x0, y0, w, h; rect.getRect(&x0, &y0, &w, &h); // calculate pixmaps widths int wLeft(0); int wRight(0); if( _w1+_w3 > 0 ) { qreal wRatio( qreal( _w1 )/qreal( _w1 + _w3 ) ); wLeft = (tiles&Right) ? qMin( _w1, int(w*wRatio) ):_w1; wRight = (tiles&Left) ? qMin( _w3, int(w*(1.0-wRatio)) ):_w3; } // calculate pixmap heights int hTop(0); int hBottom(0); if( _h1+_h3 > 0 ) { qreal hRatio( qreal( _h1 )/qreal( _h1 + _h3 ) ); hTop = (tiles&Bottom) ? qMin( _h1, int(h*hRatio) ):_h1; hBottom = (tiles&Top) ? qMin( _h3, int(h*(1.0-hRatio)) ):_h3; } // calculate corner locations w -= wLeft + wRight; h -= hTop + hBottom; const int x1 = x0 + wLeft; const int x2 = x1 + w; const int y1 = y0 + hTop; const int y2 = y1 + h; const int w2 = _pixmaps.at(7).width()/devicePixelRatio( _pixmaps.at(7) ); const int h2 = _pixmaps.at(5).height()/devicePixelRatio( _pixmaps.at(5) ); // corner if( bits( tiles, Top|Left) ) painter->drawPixmap(x0, y0, _pixmaps.at(0), 0, 0, wLeft*devicePixelRatio( _pixmaps.at(0) ), hTop*devicePixelRatio( _pixmaps.at(0) )); if( bits( tiles, Top|Right) ) painter->drawPixmap(x2, y0, _pixmaps.at(2), (_w3-wRight)*devicePixelRatio( _pixmaps.at(2) ), 0, wRight*devicePixelRatio( _pixmaps.at(2) ), hTop*devicePixelRatio( _pixmaps.at(2) ) ); if( bits( tiles, Bottom|Left) ) painter->drawPixmap(x0, y2, _pixmaps.at(6), 0, (_h3-hBottom)*devicePixelRatio( _pixmaps.at(6) ), wLeft*devicePixelRatio( _pixmaps.at(6) ), hBottom*devicePixelRatio( _pixmaps.at(6) )); if( bits( tiles, Bottom|Right) ) painter->drawPixmap(x2, y2, _pixmaps.at(8), (_w3-wRight)*devicePixelRatio( _pixmaps.at(8) ), (_h3-hBottom)*devicePixelRatio( _pixmaps.at(8) ), wRight*devicePixelRatio( _pixmaps.at(8) ), hBottom*devicePixelRatio( _pixmaps.at(8) ) ); // top and bottom if( w > 0 ) { if( tiles&Top ) painter->drawPixmap(x1, y0, w, hTop, _pixmaps.at(1), 0, 0, w2*devicePixelRatio( _pixmaps.at(1) ), hTop*devicePixelRatio( _pixmaps.at(1) ) ); if( tiles&Bottom ) painter->drawPixmap(x1, y2, w, hBottom, _pixmaps.at(7), 0, (_h3-hBottom)*devicePixelRatio( _pixmaps.at(7) ), w2*devicePixelRatio( _pixmaps.at(7) ), hBottom*devicePixelRatio( _pixmaps.at(7) ) ); } // left and right if( h > 0 ) { if( tiles&Left ) painter->drawPixmap(x0, y1, wLeft, h, _pixmaps.at(3), 0, 0, wLeft*devicePixelRatio( _pixmaps.at(3) ), h2*devicePixelRatio( _pixmaps.at(3) ) ); if( tiles&Right ) painter->drawPixmap(x2, y1, wRight, h, _pixmaps.at(5), (_w3-wRight)*devicePixelRatio( _pixmaps.at(5) ), 0, wRight*devicePixelRatio( _pixmaps.at(5) ), h2*devicePixelRatio( _pixmaps.at(5) ) ); } // center if( (tiles&Center) && h > 0 && w > 0 ) painter->drawPixmap(x1, y1, w, h, _pixmaps.at(4)); // restore painter->setRenderHint( QPainter::SmoothPixmapTransform, oldHint ); } }