diff --git a/kstyle/demo/oxygendemodialog.cpp b/kstyle/demo/oxygendemodialog.cpp index 6e0149fc..528173b1 100644 --- a/kstyle/demo/oxygendemodialog.cpp +++ b/kstyle/demo/oxygendemodialog.cpp @@ -1,253 +1,258 @@ ////////////////////////////////////////////////////////////////////////////// // 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 + #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 + #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/oxygenstyle.cpp b/kstyle/oxygenstyle.cpp index 0e78ff13..9b407239 100644 --- a/kstyle/oxygenstyle.cpp +++ b/kstyle/oxygenstyle.cpp @@ -1,8802 +1,8896 @@ // 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 ); } //_______________________________________________________________ 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 ); } //______________________________________________________________ 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 ); } } //______________________________________________________________ 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 ); } } //______________________________________________________________ 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 ); } } //______________________________________________________________ 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 ); } } //______________________________________________________________ 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 ); } } //______________________________________________________________ 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 ); } } //______________________________________________________________ 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 ); } 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 ); } 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 ); } 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 ); } } // fallback return ParentStyleClass::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 ); } //_________________________________________________________ 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 } } //_____________________________________________________________________ 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 ); - const QStyleOptionProgressBarV2 *progressBarOption2( qstyleoption_cast( option ) ); + + #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 - const QStyleOptionProgressBarV2* progressBarOption2( qstyleoption_cast( option ) ); + #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 - const QStyleOptionTabV3 *tabOptionV3( qstyleoption_cast( option ) ); + #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 - const QStyleOptionTabV3 *tabOptionV3( qstyleoption_cast( option ) ); + #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 ); // 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 ); } //___________________________________________________________________________________________________________________ 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 ); 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 ); 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 ); } //___________________________________________________________________________________________________________________ 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 ); 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 ); } //___________________________________________________________________________________________________________________ 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 ); // 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 );; } } //___________________________________________________________________________________________________________________ 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 ); 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 ) ); 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 ) ); handleRect = centerRect( handleRect, Metrics::Slider_ControlThickness, Metrics::Slider_ControlThickness ); return handleRect; } default: return ParentStyleClass::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 QStyleOptionTab *tabOption( qstyleoption_cast( option ) ); - const QStyleOptionTabV3 *tabOptionV3( qstyleoption_cast( option ) ); + 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 ) ); // 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 QStyleOptionFrame *frameOption( qstyleoption_cast( option ) ); + 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 - const QStyleOptionViewItemV4 *viewItemOption = qstyleoption_cast( option ); + #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 QAbstractItemView *view = qobject_cast( widget ); + const auto view = qobject_cast( widget ); // store palette and rect - const QPalette& palette( option->palette ); + 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 - const QStyleOptionTabV3* tabOptionV3( qstyleoption_cast( option ) ); + #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 - const QStyleOptionProgressBarV2* progressBarOption2 = qstyleoption_cast( option ); + #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 { - const QStyleOptionProgressBarV2 *progressBarOption = qstyleoption_cast( option ); + #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 - const QStyleOptionProgressBarV2* progressBarOption2 = qstyleoption_cast( option ); + #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 - const QStyleOptionFrameV3* frameOption = qstyleoption_cast( option ); + #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 ); // 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 - const QStyleOptionTabV3 *tabOptionV3 = qstyleoption_cast( option ); + #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 - const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast( option ); + #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 - const QStyleOptionToolBoxV2 *v2 = qstyleoption_cast( option ); + #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 - const QStyleOptionDockWidgetV2 *v2 = qstyleoption_cast( option ); + #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 ); 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 ); } // 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 - const QStyleOptionTabV3 *tabOptionV3 = qstyleoption_cast( tabOption ); + #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 d6738ea1..dbef412f 100644 --- a/kstyle/oxygenstyle.h +++ b/kstyle/oxygenstyle.h @@ -1,773 +1,778 @@ #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 #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 { 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; //* 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 = 0 ) 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 = 0, 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 = 0 ) const { renderSlab( painter, slab.rect, color, options, slab.tiles ); } //* generic slab void renderSlab( QPainter* painter, QRect rect, const QColor& color, StyleOptions options = 0, 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; QRect visualRect(const QStyleOption* opt, const QRect& subRect) const { return ParentStyleClass::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