// 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 "moc_oxygenstyle.cpp" #include "oxygenframeshadow.h" #include "oxygenmdiwindowshadow.h" #include "oxygenmnemonics.h" #include "oxygenshadowhelper.h" #include "oxygenstyleconfigdata.h" #include "oxygenwidgetexplorer.h" #include "oxygenwindowmanager.h" #include "oxygenpropertynames.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 #include #include #include #include #include #include #include //_____________________________________________ // style plugin namespace Oxygen { //! style plugin class StylePlugin : public QStylePlugin { public: //! returns list of valid keys QStringList keys() const { return QStringList( QLatin1String( "Oxygen" ) ); } //! create style QStyle *create( const QString &key ) { if( key.toLower() == QLatin1String( "oxygen" ) ) return new Style; else return NULL; } }; } Q_EXPORT_PLUGIN2( oxygen-qt, Oxygen::StylePlugin ) namespace Oxygen { // hardcoded index offsets for custom widgets // copied from e.g. kstyle.cxx static const QStyle::StyleHint SH_KCustomStyleElement = ( QStyle::StyleHint )0xff000001; static const int X_KdeBase = 0xff000000; //_____________________________________________________________________ bool TopLevelManager::eventFilter( QObject *object, QEvent *event ) { // cast to QWidget QWidget *widget = static_cast( object ); if( event->type() == QEvent::Show && _helper.hasDecoration( widget ) ) { _helper.setHasBackgroundGradient( widget->winId(), true ); _helper.setHasBackgroundPixmap( widget->winId(), _helper.hasBackgroundPixmap() ); } return false; } //______________________________________________________________ Style::Style( void ): _kGlobalSettingsInitialized( false ), _addLineButtons( DoubleButton ), _subLineButtons( SingleButton ), _singleButtonHeight( 14 ), _doubleButtonHeight( 28 ), _helper( new StyleHelper( "oxygen" ) ), _shadowHelper( new ShadowHelper( this, *_helper ) ), _windowManager( new WindowManager( this ) ), _topLevelManager( new TopLevelManager( this, *_helper ) ), _frameShadowFactory( new FrameShadowFactory( this ) ), _mdiWindowShadowFactory( new MdiWindowShadowFactory( this, *_helper ) ), _mnemonics( new Mnemonics( this ) ), _widgetExplorer( new WidgetExplorer( this ) ), _tabBarData( new TabBarData( this ) ), _frameFocusPrimitive( 0 ), _tabBarTabShapeControl( 0 ), _hintCounter( X_KdeBase+1 ), _controlCounter( X_KdeBase ), _subElementCounter( X_KdeBase ), SH_ArgbDndWindow( newStyleHint( "SH_ArgbDndWindow" ) ), CE_CapacityBar( newControlElement( "CE_CapacityBar" ) ) { // use DBus connection to update on oxygen configuration change QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.connect( QString(), "/OxygenStyle", "org.kde.Oxygen.Style", "reparseConfiguration", this, SLOT(oxygenConfigurationChanged()) ); // call the slot directly; this initial call will set up things that also // need to be reset when the system palette changes oxygenConfigurationChanged(); } //______________________________________________________________ Style::~Style( void ) { delete _helper; } //______________________________________________________________ void Style::polish( QWidget* widget ) { if( !widget ) return; // register widget to animations windowManager().registerWidget( widget ); frameShadowFactory().registerWidget( widget, helper() ); mdiWindowShadowFactory().registerWidget( widget ); shadowHelper().registerWidget( widget ); // scroll areas if( QAbstractScrollArea* scrollArea = qobject_cast( widget ) ) { polishScrollArea( scrollArea ); } // KTextEdit frames // static cast is safe here, since isKTextEdit already checks that widget inherits from QFrame if( isKTextEditFrame( widget ) && static_cast( widget )->frameStyle() == ( QFrame::StyledPanel | QFrame::Sunken ) ) { widget->setAttribute( Qt::WA_Hover ); } // 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 ); // initialize connections to kGlobalSettings /* this musts be done in ::polish and not before, in order to be able to detect Qt-KDE vs Qt-only applications */ if( !_kGlobalSettingsInitialized ) initializeKGlobalSettings(); 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->setAttribute( Qt::WA_Hover ); } // transparent tooltips if( widget->inherits( "QTipLabel" ) ) { widget->setAttribute( Qt::WA_TranslucentBackground ); } 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 ); } /* add extra margins for widgets in toolbars this allows to preserve alignment with respect to actions */ if( qobject_cast( widget->parent() ) ) { widget->setContentsMargins( 0,0,0,1 ); } 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 ); } 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 ); } 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 ); } else if( widget->inherits( "QComboBoxPrivateContainer" ) ) { addEventFilter( widget ); widget->setAttribute( Qt::WA_TranslucentBackground ); } else if( qobject_cast( widget ) && widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ) { widget->setAutoFillBackground( false ); widget->setBackgroundRole( QPalette::Window ); } else if( qobject_cast( widget ) ) { addEventFilter( widget ); } // base class polishing QCommonStyle::polish( widget ); } //_______________________________________________________________ void Style::unpolish( QWidget* widget ) { // register widget to animations windowManager().unregisterWidget( widget ); frameShadowFactory().unregisterWidget( widget ); mdiWindowShadowFactory().unregisterWidget( widget ); shadowHelper().unregisterWidget( widget ); if( isKTextEditFrame( widget ) ) { widget->setAttribute( Qt::WA_Hover, false ); } // 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_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_NoSystemBackground, false ); widget->clearMask(); } else if( widget->inherits( "QComboBoxPrivateContainer" ) ) { widget->removeEventFilter( this ); } else if( qobject_cast( widget ) ) { widget->removeEventFilter( this ); } QCommonStyle::unpolish( widget ); } //______________________________________________________________ int Style::pixelMetric( PixelMetric metric, const QStyleOption* option, const QWidget* widget ) const { // handle special cases switch( metric ) { // rely on QCommonStyle here case PM_SmallIconSize: case PM_ButtonIconSize: return KIconLoader::global()->currentSize( KIconLoader::Small ); case PM_ToolBarIconSize: return KIconLoader::global()->currentSize( KIconLoader::Toolbar ); case PM_LargeIconSize: return KIconLoader::global()->currentSize( KIconLoader::Dialog ); case PM_MessageBoxIconSize: return KIconLoader::SizeHuge; case PM_DefaultFrameWidth: { if( qobject_cast( widget ) ) return LineEdit_FrameWidth; else if( qobject_cast( widget ) ) return ComboBox_FrameWidth; else if( qobject_cast( widget ) ) { // special case for KTitleWidget: frameWidth is set to zero, since // no frame, nor background is painted for these if( widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ) return 0; else return Frame_FrameWidth; } else if( qstyleoption_cast( option ) ) return GroupBox_FrameWidth; else return 1; } 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 pixelMetric( PM_DefaultTopLevelMargin, option, widget ); } else { return pixelMetric( PM_DefaultChildMargin, option, widget ); } } // push buttons /* HACK: needs special case for kcalc buttons, to prevent the application to set too small margins */ case PM_ButtonMargin: return ( widget && widget->inherits( "KCalcButton" ) ) ? 8:5; case PM_MenuButtonIndicator: { if( qstyleoption_cast( option ) ) return ToolButton_MenuIndicatorSize; else return PushButton_MenuIndicatorSize; } case PM_ScrollBarExtent: return StyleConfigData::scrollBarWidth() + 2; case PM_ScrollBarSliderMin: return ScrollBar_MinimumSliderHeight; // tooltip label case PM_ToolTipLabelFrameWidth: { if( StyleConfigData::toolTipDrawStyledFrames() ) return 3; else break; } case PM_DefaultChildMargin: return 4; case PM_DefaultTopLevelMargin: return 11; case PM_DefaultLayoutSpacing: return 4; case PM_LayoutHorizontalSpacing: return -1; case PM_LayoutVerticalSpacing: return -1; // buttons case PM_ButtonDefaultIndicator: return 0; case PM_ButtonShiftHorizontal: return 0; case PM_ButtonShiftVertical: return 0; // checkboxes: return radiobutton sizes case PM_IndicatorWidth: return CheckBox_Size; case PM_IndicatorHeight: return CheckBox_Size; case PM_ExclusiveIndicatorWidth: return CheckBox_Size; case PM_ExclusiveIndicatorHeight: return CheckBox_Size; #ifndef QT_KATIE case PM_CheckListControllerSize: return CheckBox_Size; case PM_CheckListButtonSize: return CheckBox_Size; #endif // splitters and dock widgets case PM_SplitterWidth: return Splitter_Width; case PM_DockWidgetFrameWidth: return DockWidget_FrameWidth; case PM_DockWidgetSeparatorExtent: return DockWidget_SeparatorExtend; case PM_DockWidgetTitleMargin: return DockWidget_TitleMargin; // progress bar case PM_ProgressBarChunkWidth: return 1; // menu bars 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; case PM_MenuPanelWidth: return 5; case PM_MenuScrollerHeight: return 10; case PM_MenuTearoffHeight: return 10; // tabbars case PM_TabBarTabHSpace: return 0; case PM_TabBarTabVSpace: return 0; case PM_TabBarBaseHeight: return TabBar_BaseHeight; case PM_TabBarBaseOverlap: return TabBar_BaseOverlap; case PM_TabBarTabOverlap: return 0; case PM_TabBarScrollButtonWidth: return TabBar_ScrollButtonWidth; /* disable shifts: return because last time I checked it did not work well for South and East tabs. Instead the shifts are added directly in drawTabBarTabLabel. ( Hugo ) */ case PM_TabBarTabShiftVertical: return 0; case PM_TabBarTabShiftHorizontal: return 0; // sliders case PM_SliderThickness: return 23; case PM_SliderControlThickness: return 23; case PM_SliderLength: return 21; // spinboxes case PM_SpinBoxFrameWidth: return SpinBox_FrameWidth; // comboboxes case PM_ComboBoxFrameWidth: return ComboBox_FrameWidth; // tree view header case PM_HeaderMarkSize: return 9; case PM_HeaderMargin: return 3; // toolbars case PM_ToolBarFrameWidth: return 0; case PM_ToolBarHandleExtent: return 6; case PM_ToolBarSeparatorExtent: return 6; case PM_ToolBarExtensionExtent: return 16; case PM_ToolBarItemMargin: return 0; case PM_ToolBarItemSpacing: return 1; // MDI windows titlebars case PM_TitleBarHeight: return 20; // 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 ? -2:0; } else return -2; default: break; } // fallback return QCommonStyle::pixelMetric( metric, option, widget ); } //______________________________________________________________ int Style::styleHint( StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData ) const { // handles SH_KCustomStyleElement out of switch statement, // to avoid warning at compilation if( hint == SH_KCustomStyleElement ) { if( widget ) return _styleElements.value( widget->objectName(), 0 ); else return 0; } /* special cases, that cannot be registered in styleHint map, because of conditional statements */ switch( hint ) { case SH_DialogButtonBox_ButtonsHaveIcons: return KGlobalSettings::showIconsOnPushButtons(); case SH_GroupBox_TextLabelColor: if( option ) return option->palette.color( QPalette::WindowText ).rgba(); else return qApp->palette().color( QPalette::WindowText ).rgba(); case SH_ItemView_ActivateItemOnSingleClick: return helper().config()->group( "KDE" ).readEntry( "SingleClick", KDE_DEFAULT_SINGLECLICK ); case SH_RubberBand_Mask: { const QStyleOptionRubberBand *opt = qstyleoption_cast( option ); if( !opt ) return false; 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 -= option->rect.adjusted( 1,1,-1,-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_TitleBar_NoBorder: return 0; case SH_GroupBox_TextLabelVerticalAlignment: return Qt::AlignVCenter; #ifndef QT_KATIE case SH_DialogButtonLayout: return QDialogButtonBox::KdeLayout; #endif case SH_ScrollBar_MiddleClickAbsolutePosition: return true; case SH_ItemView_ShowDecorationSelected: return false; case SH_ItemView_ArrowKeysNavigateIntoChildren: 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_WindowFrame_Mask: return false; case SH_RequestSoftwareInputPanel: return RSIP_OnMouseClick; case SH_ProgressDialog_CenterCancelButton: case SH_MessageBox_CenterButtons: return false; default: return QCommonStyle::styleHint( hint, option, widget, returnData ); } } //______________________________________________________________ QRect Style::subElementRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const { switch( element ) { // push buttons case SE_PushButtonContents: return pushButtonContentsRect( option, widget ); case SE_PushButtonFocusRect: return defaultSubElementRect( option, widget ); // checkboxes case SE_CheckBoxContents: return checkBoxContentsRect( option, widget ); case SE_CheckBoxFocusRect: return defaultSubElementRect( option, widget ); // progress bars case SE_ProgressBarGroove: return defaultSubElementRect( option, widget ); case SE_ProgressBarContents: return progressBarContentsRect( option, widget ); case SE_ProgressBarLabel: return defaultSubElementRect( option, widget ); // radio buttons case SE_RadioButtonContents: return checkBoxContentsRect( option, widget ); case SE_RadioButtonFocusRect: return defaultSubElementRect( option, widget ); // tab widget case SE_TabBarTabLeftButton: return tabBarTabLeftButtonRect( option, widget ); case SE_TabBarTabRightButton: return tabBarTabRightButtonRect( option, widget ); case SE_TabBarTabText: return tabBarTabTextRect( option, widget ); case SE_TabWidgetTabContents: return tabWidgetTabContentsRect( option, widget ); case SE_TabWidgetTabPane: return tabWidgetTabPaneRect( option, widget ); case SE_TabWidgetLeftCorner: return tabWidgetLeftCornerRect( option, widget ); case SE_TabWidgetRightCorner: return tabWidgetRightCornerRect( option, widget ); // toolboxes case SE_ToolBoxTabContents: return toolBoxTabContentsRect( option, widget ); default: return QCommonStyle::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_ComboBox: return comboBoxSubControlRect( option, subControl, widget ); case CC_ScrollBar: return scrollBarSubControlRect( option, subControl, widget ); case CC_SpinBox: return spinBoxSubControlRect( option, subControl, widget ); default: return QCommonStyle::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_ComboBox: return comboBoxSizeFromContents( option, size, widget ); case CT_HeaderSection: return headerSectionSizeFromContents( option, size, widget ); case CT_PushButton: return pushButtonSizeFromContents( option, size, widget ); case CT_MenuBar: return menuBarSizeFromContents( option, size, widget ); case CT_MenuBarItem: return menuBarItemSizeFromContents( option, size, widget ); case CT_MenuItem: return menuItemSizeFromContents( option, size, widget ); case CT_RadioButton: return checkBoxSizeFromContents( option, size, widget ); case CT_TabBarTab: return tabBarTabSizeFromContents( option, size, widget ); case CT_TabWidget: return tabWidgetSizeFromContents( option, size, widget ); case CT_ToolButton: return toolButtonSizeFromContents( option, size, widget ); default: return QCommonStyle::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 groove = scrollBarSubControlRect( option, SC_ScrollBarGroove, widget ); if ( groove.contains( point ) ) { //Must be either page up/page down, or just click on the slider. //Grab the slider to compare QRect slider = scrollBarSubControlRect( option, SC_ScrollBarSlider, widget ); if( slider.contains( point ) ) return SC_ScrollBarSlider; else if( preceeds( point, slider, 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, groove, 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; } default: return QCommonStyle::hitTestComplexControl( control, option, point, widget ); } } //______________________________________________________________ void Style::drawPrimitive( PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { painter->save(); StylePrimitive fcn( 0 ); switch( element ) { // register primitives for which nothing is done case PE_FrameStatusBar: fcn = &Style::emptyPrimitive; break; case PE_Frame: fcn = &Style::drawFramePrimitive; break; // frame focus primitive is set at run time, in oxygenConfigurationChanged case PE_FrameFocusRect: fcn = _frameFocusPrimitive; break; case PE_FrameGroupBox: fcn = &Style::drawFrameGroupBoxPrimitive; break; case PE_FrameLineEdit: fcn = &Style::drawFramePrimitive; break; case PE_FrameMenu: fcn = &Style::drawFrameMenuPrimitive; break; // TabBar case PE_FrameTabBarBase: fcn = &Style::drawFrameTabBarBasePrimitive; break; case PE_FrameTabWidget: fcn = &Style::drawFrameTabWidgetPrimitive; break; case PE_FrameWindow: fcn = &Style::drawFrameWindowPrimitive; break; case PE_IndicatorTabClose: fcn = &Style::drawIndicatorTabClose; break; // arrows 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_IndicatorDockWidgetResizeHandle: fcn = &Style::drawIndicatorDockWidgetResizeHandlePrimitive; break; case PE_IndicatorHeaderArrow: fcn = &Style::drawIndicatorHeaderArrowPrimitive; break; case PE_PanelButtonCommand: fcn = &Style::drawPanelButtonCommandPrimitive; break; case PE_PanelButtonTool: fcn = &Style::drawPanelButtonToolPrimitive; break; case PE_PanelItemViewItem: fcn = &Style::drawPanelItemViewItemPrimitive; break; case PE_PanelLineEdit: fcn = &Style::drawPanelLineEditPrimitive; break; case PE_PanelMenu: fcn = &Style::drawPanelMenuPrimitive; break; case PE_PanelScrollAreaCorner: fcn = &Style::drawPanelScrollAreaCornerPrimitive; break; case PE_PanelTipLabel: fcn = &Style::drawPanelTipLabelPrimitive; break; case PE_IndicatorMenuCheckMark: fcn = &Style::drawIndicatorMenuCheckMarkPrimitive; break; case PE_IndicatorBranch: fcn = &Style::drawIndicatorBranchPrimitive; break; case PE_IndicatorButtonDropDown: fcn = &Style::drawIndicatorButtonDropDownPrimitive; break; case PE_IndicatorCheckBox: fcn = &Style::drawIndicatorCheckBoxPrimitive; break; case PE_IndicatorRadioButton: fcn = &Style::drawIndicatorRadioButtonPrimitive; break; case PE_IndicatorTabTear: fcn = &Style::drawIndicatorTabTearPrimitive; break; case PE_IndicatorToolBarHandle: fcn = &Style::drawIndicatorToolBarHandlePrimitive; break; case PE_IndicatorToolBarSeparator: fcn = &Style::drawIndicatorToolBarSeparatorPrimitive; break; case PE_Widget: fcn = &Style::drawWidgetPrimitive; break; default: break; } // try find primitive in map, and run. // exit if result is true, otherwise fallback to generic case if( !( fcn && ( this->*fcn )( option, painter, widget ) ) ) { QCommonStyle::drawPrimitive( element, option, painter, widget ); } painter->restore(); } //______________________________________________________________ void Style::drawControl( ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { painter->save(); StyleControl fcn( 0 ); if( element == CE_CapacityBar ) { fcn = &Style::drawCapacityBarControl; } else { switch( element ) { case CE_ComboBoxLabel: fcn = &Style::drawComboBoxLabelControl; break; case CE_DockWidgetTitle: fcn = &Style::drawDockWidgetTitleControl; break; case CE_HeaderEmptyArea: fcn = &Style::drawHeaderEmptyAreaControl; break; case CE_HeaderLabel: fcn = &Style::drawHeaderLabelControl; 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; /* for CE_PushButtonBevel the only thing that is done is draw the PanelButtonCommand primitive since the prototypes are identical we register the second directly in the control map: fcn = without using an intermediate function */ 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_ScrollBarAddPage: fcn = &Style::drawScrollBarAddPageControl; break; case CE_ScrollBarSubLine: fcn = &Style::drawScrollBarSubLineControl; break; case CE_ScrollBarSubPage: fcn = &Style::drawScrollBarSubPageControl; break; case CE_ShapedFrame: fcn = &Style::drawShapedFrameControl; break; case CE_SizeGrip: fcn = &Style::drawSizeGripControl; break; case CE_Splitter: fcn = &Style::drawSplitterControl; break; case CE_TabBarTabLabel: fcn = &Style::drawTabBarTabLabelControl; break; // default tab style is 'SINGLE' case CE_TabBarTabShape: fcn = _tabBarTabShapeControl; break; case CE_ToolBoxTabLabel: fcn = &Style::drawToolBoxTabLabelControl; break; case CE_ToolBoxTabShape: fcn = &Style::drawToolBoxTabShapeControl; break; case CE_ToolButtonLabel: fcn = &Style::drawToolButtonLabelControl; break; default: break; } } if( !( fcn && ( this->*fcn )( option, painter, widget ) ) ) { QCommonStyle::drawControl( element, option, painter, widget ); } painter->restore(); } //______________________________________________________________ void Style::drawComplexControl( ComplexControl element, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { painter->save(); StyleComplexControl fcn( 0 ); switch( element ) { case CC_ComboBox: fcn = &Style::drawComboBoxComplexControl; break; case CC_Dial: fcn = &Style::drawDialComplexControl; break; case CC_GroupBox: fcn = &Style::drawGroupBoxComplexControl; break; case CC_Slider: fcn = &Style::drawSliderComplexControl; break; case CC_SpinBox: fcn = &Style::drawSpinBoxComplexControl; break; case CC_TitleBar: fcn = &Style::drawTitleBarComplexControl; break; case CC_ToolButton: fcn = &Style::drawToolButtonComplexControl; break; default: break; } if( !( fcn && ( this->*fcn )( option, painter, widget ) ) ) { QCommonStyle::drawComplexControl( element, option, painter, widget ); } painter->restore(); } //___________________________________________________________________________________ void Style::drawItemText( QPainter* painter, const QRect& r, 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; } return QCommonStyle::drawItemText( painter, r, flags, palette, enabled, text, textRole ); } //_____________________________________________________________________ bool Style::eventFilter( QObject *object, QEvent *event ) { if( QTabBar* tabBar = qobject_cast( object ) ) { return eventFilterTabBar( tabBar, event ); } if( QToolBar* toolBar = qobject_cast( object ) ) { return eventFilterToolBar( toolBar, event ); } if( QDockWidget* dockWidget = qobject_cast( object ) ) { return eventFilterDockWidget( dockWidget, event ); } if( QToolBox* toolBox = qobject_cast( object ) ) { return eventFilterToolBox( toolBox, event ); } if( QMdiSubWindow* subWindow = qobject_cast( object ) ) { return eventFilterMdiSubWindow( subWindow, event ); } if( QScrollBar* scrollBar = qobject_cast( object ) ) { return eventFilterScrollBar( scrollBar, event ); } if( QProgressBar* progressBar = qobject_cast( object ) ) { return eventFilterProgressBar( progressBar, event ); } // cast to QWidget QWidget *widget = static_cast( object ); if( widget->inherits( "QComboBoxPrivateContainer" ) ) { return eventFilterComboBoxContainer( widget, event ); } return QCommonStyle::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->rect() ) ); else widget->clearMask(); return false; } case QEvent::Paint: { QPainter painter( widget ); QPaintEvent *paintEvent = static_cast( event ); painter.setClipRegion( paintEvent->region() ); const QRect r( widget->rect() ); const QColor color( widget->palette().color( widget->window()->backgroundRole() ) ); const bool hasAlpha( helper().hasAlphaChannel( widget ) ); if( hasAlpha ) { TileSet *tileSet( helper().roundCorner( color ) ); tileSet->render( r, &painter ); painter.setCompositionMode( QPainter::CompositionMode_SourceOver ); painter.setClipRegion( helper().roundedMask( r.adjusted( 1, 1, -1, -1 ) ), Qt::IntersectClip ); } // background helper().renderMenuBackground( &painter, paintEvent->rect(), widget, widget->palette() ); // frame if( hasAlpha ) painter.setClipping( false ); helper().drawFloatFrame( &painter, r, 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() ) { if( helper().compositingActive() ) dockWidget->setMask( helper().roundedMask( dockWidget->rect().adjusted( 1, 1, -1, -1 ) ) ); else dockWidget->setMask( helper().roundedMask( dockWidget->rect() ) ); } 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 r( dockWidget->rect() ); if( dockWidget->isWindow() ) { helper().renderWindowBackground( &painter, r, dockWidget, color ); helper().drawFloatFrame( &painter, r, color, !helper().compositingActive() ); } else { // need to draw window background for autoFilled dockWidgets for better rendering if( dockWidget->autoFillBackground() ) { helper().renderWindowBackground( &painter, r, dockWidget, color ); } // adjust color QColor top( helper().backgroundColor( color, dockWidget, r.topLeft() ) ); QColor bottom( helper().backgroundColor( color, dockWidget, r.bottomLeft() ) ); TileSet *tileSet = helper().dockFrame( top, bottom ); tileSet->render( r, &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 r( subWindow->rect() ); TileSet *tileSet( helper().roundCorner( subWindow->palette().color( subWindow->backgroundRole() ) ) ); tileSet->render( r, &painter ); painter.setClipRegion( helper().roundedMask( r.adjusted( 1, 1, -1, -1 ) ), Qt::IntersectClip ); helper().renderWindowBackground( &painter, clip, subWindow, subWindow, subWindow->palette(), 0, 58 ); } } // continue with normal painting return false; } //_________________________________________________________ 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->rect() ) ); } else toolBar->clearMask(); return false; } case QEvent::Paint: { QPainter painter( toolBar ); QPaintEvent *paintEvent = static_cast( event ); painter.setClipRegion( paintEvent->region() ); const QRect r( 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, r, toolBar, color ); } return true; } else { // background helper().renderWindowBackground( &painter, r, 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 = handleRTL( &opt, QRect( r.topLeft(), QSize( 8, r.height() ) ) ); opt.state |= QStyle::State_Horizontal; } else { opt.rect = handleRTL( &opt, QRect( r.topLeft(), QSize( r.width(), 8 ) ) ); } drawIndicatorToolBarHandlePrimitive( &opt, &painter, toolBar ); } if( helper().compositingActive() ) helper().drawFloatFrame( &painter, r.adjusted( -1, -1, 1, 1 ), color, false ); else helper().drawFloatFrame( &painter, r, color, true ); // 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 r( toolBox->rect() ); const StyleOptions opts( NoFill ); QPainter painter( toolBox ); painter.setClipRegion( static_cast( event )->region() ); renderSlab( &painter, r, toolBox->palette().color( QPalette::Button ), opts ); } } return false; } //_________________________________________________________ bool Style::eventFilterProgressBar( QProgressBar* widget, QEvent* event ) { if( event->type() == QEvent::Show ) { int id = widget->startTimer( 30 ); widget->setProperty( PropertyNames::progressTimer, QVariant(id) ); return true; } else if( event->type() == QEvent::Timer ) { if (widget->minimum() != widget->maximum()) { // not busy return false; } QVariant kValue = widget->property( PropertyNames::progressTimer ); QTimerEvent* te = static_cast(event); if (!kValue.isValid() || kValue.toInt() != te->timerId()) { // not this event filter timer return false; } qreal minimum = widget->minimum(); qreal maximum = 100; qreal progress = widget->property(PropertyNames::progressValue).toReal(); qreal newprogress = 0; QString direction = widget->property(PropertyNames::progressDirection).toString(); Qt::Orientation orientation = widget->orientation(); if (orientation == Qt::Horizontal) { maximum = widget->width(); } else if (orientation == Qt::Vertical) { maximum = widget->height(); } maximum = maximum - (maximum/ProgressBar_BusyIndicatorSize); if (direction == QLatin1String("left")) { newprogress = progress - 3; } else if (direction == QLatin1String("right")) { newprogress = progress + 3; } if (newprogress >= maximum) { newprogress = maximum; widget->setProperty( PropertyNames::progressDirection, "left" ); } else if (newprogress <= minimum ) { newprogress = minimum; widget->setProperty( PropertyNames::progressDirection, "right" ); } widget->setProperty( PropertyNames::progressValue, newprogress ); widget->update(); return true; } else if ( event->type() == QEvent::Hide ) { QVariant kValue = widget->property( PropertyNames::progressTimer ); if (kValue.isValid()) { widget->killTimer( kValue.toInt() ); widget->setProperty( PropertyNames::progressTimer, QVariant() ); widget->setProperty( PropertyNames::progressDirection, QVariant() ); widget->setProperty( PropertyNames::progressValue, QVariant() ); } return true; } return false; } //____________________________________________________________________ QRect Style::progressBarContentsRect( const QStyleOption* option, const QWidget* ) const { const QRect out( insideMargin( option->rect, ProgressBar_GrooveMargin ) ); const QStyleOptionProgressBarV2 *pbOpt( qstyleoption_cast( option ) ); if( pbOpt && pbOpt->orientation == Qt::Vertical ) return out.adjusted( 0, 1, 0, -1 ); else return out.adjusted( 1, 0, -1, 0 ); } //____________________________________________________________________ QRect Style::tabBarTabButtonRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const { const QStyleOptionTab* tabOpt( qstyleoption_cast( option ) ); if ( !tabOpt ) return QRect(); QRect r( QCommonStyle::subElementRect( element, option, widget ) ); const bool selected( option->state&State_Selected ); switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: r.translate( 0, -1 ); if( selected ) r.translate( 0, -1 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: r.translate( 0, -1 ); if( selected ) r.translate( 0, 1 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: r.translate( 0, 1 ); if( selected ) r.translate( -1, 0 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: r.translate( 0, -2 ); if( selected ) r.translate( 1, 0 ); break; default: break; } return r; } //____________________________________________________________________ QRect Style::tabWidgetTabContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const QStyleOptionTabWidgetFrame* tabOpt = qstyleoption_cast( option ); if( !tabOpt ) return option->rect; // do nothing if tabbar is hidden if( tabOpt->tabBarSize.isEmpty() ) return option->rect; QRect r( option->rect ); // include margins r = tabWidgetTabPaneRect( option, widget ); // document mode const bool documentMode( tabOpt->lineWidth == 0 ); if( !documentMode ) { r = insideMargin( r, TabWidget_ContentsMargin ); r.translate( 0, -1 ); } return r; } //____________________________________________________________________ QRect Style::tabWidgetTabPaneRect( const QStyleOption* option, const QWidget* ) const { const QStyleOptionTabWidgetFrame* tabOpt = qstyleoption_cast( option ); if( !tabOpt ) return option->rect; QRect r( option->rect ); const bool documentMode( tabOpt->lineWidth == 0 ); int overlap( TabBar_BaseOverlap ); if( documentMode ) overlap -= TabWidget_ContentsMargin; switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { if( documentMode ) overlap++; r.setTop( r.top() + qMax( tabOpt->tabBarSize.height() - overlap, 0 ) ); break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { if( documentMode ) overlap--; r.setBottom( r.bottom() - qMax( tabOpt->tabBarSize.height() - overlap, 0 ) ); break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { r.setLeft( r.left() + qMax( tabOpt->tabBarSize.width() - overlap, 0 ) ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { r.setRight( r.right() - qMax( tabOpt->tabBarSize.width() - overlap, 0 ) ); break; } } return r; } //____________________________________________________________________ QRect Style::tabWidgetLeftCornerRect( const QStyleOption* option, const QWidget* widget ) const { const QStyleOptionTabWidgetFrame *tabOpt = qstyleoption_cast( option ); if( !tabOpt ) return QRect(); QRect r( option->rect ); const QRect paneRect( subElementRect( SE_TabWidgetTabPane, option, widget ) ); const QTabWidget* tabWidget( qobject_cast( widget ) ); const bool documentMode( tabWidget ? tabWidget->documentMode() : false ); const QSize& size( tabOpt->leftCornerWidgetSize ); const int h( size.height() ); const int w( size.width() ); switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: r = QRect( QPoint( paneRect.x(), paneRect.y() - h ), size ); r = visualRect( tabOpt->direction, tabOpt->rect, r ); if( !documentMode ) r.translate( 0, 3 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: r = QRect( QPoint( paneRect.x(), paneRect.height() ), size ); r = visualRect( tabOpt->direction, tabOpt->rect, r ); if( !documentMode ) r.translate( 0, -3 ); else r.translate( 0, 2 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: r = QRect( QPoint( paneRect.x() - w, paneRect.y() ), size ); if( !documentMode ) r.translate( 2, 0 ); else r.translate( -2, 0 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: r = QRect( QPoint( paneRect.x() + paneRect.width(), paneRect.y() ), size ); if( !documentMode ) r.translate( -2, 0 ); else r.translate( 2, 0 ); break; default: break; } return r; } //____________________________________________________________________ QRect Style::tabWidgetRightCornerRect( const QStyleOption* option, const QWidget* widget ) const { const QStyleOptionTabWidgetFrame *tabOpt = qstyleoption_cast( option ); if( !tabOpt ) return QRect(); QRect r( option->rect ); const QRect paneRect( subElementRect( SE_TabWidgetTabPane, option, widget ) ); const QTabWidget* tabWidget( qobject_cast( widget ) ); const bool documentMode( tabWidget ? tabWidget->documentMode() : false ); const QSize& size( tabOpt->rightCornerWidgetSize ); const int h( size.height() ); const int w( size.width() ); switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: r = QRect( QPoint( paneRect.right() - w + 1, paneRect.y() - h ), size ); r = visualRect( tabOpt->direction, tabOpt->rect, r ); if( !documentMode ) r.translate( 0, 3 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: r = QRect( QPoint( paneRect.right() - w + 1, paneRect.height() ), size ); r = visualRect( tabOpt->direction, tabOpt->rect, r ); if( !documentMode ) r.translate( 0, -3 ); else r.translate( 0, 2 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: r = QRect( QPoint( paneRect.x() - w, paneRect.bottom() - h + 1 ), size ); if( !documentMode ) r.translate( 2, 0 ); else r.translate( -2, 0 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: r = QRect( QPoint( paneRect.x() + paneRect.width(), paneRect.bottom() - h + 1 ), size ); if( !documentMode ) r.translate( -2, 0 ); else r.translate( 2, 0 ); break; default: break; } return r; } //______________________________________________________________ QRect Style::groupBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { QRect r = option->rect; // switch ( subControl ) { case SC_GroupBoxFrame: return r.adjusted( -1, -2, 1, 0 ); case SC_GroupBoxContents: { // cast option and check const QStyleOptionGroupBox *gbOpt = qstyleoption_cast( option ); if( !gbOpt ) break; const bool isFlat( gbOpt->features & QStyleOptionFrameV2::Flat ); const int th( gbOpt->fontMetrics.height() + 8 ); const QRect cr( subElementRect( SE_CheckBoxIndicator, option, widget ) ); const int fw( pixelMetric( PM_DefaultFrameWidth, option, widget ) ); const bool checkable( gbOpt->subControls & QStyle::SC_GroupBoxCheckBox ); const bool emptyText( gbOpt->text.isEmpty() ); r.adjust( fw, fw, -fw, -fw ); if( checkable && !emptyText ) r.adjust( 0, qMax( th, cr.height() ), 0, 0 ); else if( checkable ) r.adjust( 0, cr.height(), 0, 0 ); else if( !emptyText ) r.adjust( 0, th, 0, 0 ); // add additional indentation to flat group boxes if( isFlat ) { const int leftMarginExtension( 16 ); r = visualRect( option->direction, r, r.adjusted( leftMarginExtension,0,0,0 ) ); } return r; } case SC_GroupBoxCheckBox: case SC_GroupBoxLabel: { // cast option and check const QStyleOptionGroupBox *gbOpt = qstyleoption_cast( option ); if( !gbOpt ) break; const bool isFlat( gbOpt->features & QStyleOptionFrameV2::Flat ); QFont font; if (widget) { font = widget->font(); } else { font = QApplication::font(); } // calculate text width assuming bold text in flat group boxes if( isFlat ) font.setBold( true ); QFontMetrics fontMetrics = QFontMetrics( font ); const int h( fontMetrics.height() ); const int tw( fontMetrics.size( Qt::TextShowMnemonic, gbOpt->text + QLatin1String( " " ) ).width() ); r.setHeight( h ); // translate down by 6 pixels in non flat mode, // to avoid collision with groupbox frame if( !isFlat ) r.moveTop( 6 ); QRect cr; if( gbOpt->subControls & QStyle::SC_GroupBoxCheckBox ) { cr = subElementRect( SE_CheckBoxIndicator, option, widget ); QRect gcr( ( gbOpt->rect.width() - tw -cr.width() )/2 , ( h-cr.height() )/2+r.y(), cr.width(), cr.height() ); if( subControl == SC_GroupBoxCheckBox ) { if( !isFlat ) return visualRect( option->direction, option->rect, gcr ); else return visualRect( option->direction, option->rect, QRect( 0,0,cr.width(),cr.height() ) ); } } // left align labels in flat group boxes, center align labels in framed group boxes if( isFlat ) r = QRect( cr.width(),r.y(),tw,r.height() ); else r = QRect( ( gbOpt->rect.width() - tw - cr.width() )/2 + cr.width(), r.y(), tw, r.height() ); return visualRect( option->direction, option->rect, r ); } default: break; } return QCommonStyle::subControlRect( CC_GroupBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::comboBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { const QRect& r( option->rect ); const QStyleOptionComboBox *cb = qstyleoption_cast( option ); if( !cb ) return QCommonStyle::subControlRect( CC_ComboBox, option, subControl, widget ); switch( subControl ) { case SC_ComboBoxFrame: return cb->frame ? r : QRect(); case SC_ComboBoxListBoxPopup: return r.adjusted( 1,0,-1,0 ); case SC_ComboBoxArrow: case SC_ComboBoxEditField: { // frame width int fw = ComboBox_FrameWidth; // button width int bw = ComboBox_ButtonWidth; // button margin int bm = ComboBox_ButtonMargin; int bml = bm + ComboBox_ButtonMargin_Left; int bmr = bm + ComboBox_ButtonMargin_Right; int bmt = bm + ComboBox_ButtonMargin_Top; int bmb = bm + ComboBox_ButtonMargin_Bottom; // ComboBox without a frame, set the corresponding layout values to 0, reduce button width. if( !cb->frame ) { bw = bw - bmr; // reduce button with as the right button margin will be ignored. fw = 0; // TODO: why is bml not also set to 0 bmt = bmb = 0; } if( subControl == SC_ComboBoxArrow ) { return handleRTL( option, QRect( r.right()-bw+bml+1, r.top()+bmt, bw-bml-bmr, r.height()-bmt-bmb ) ); } else { QRect labelRect( r.left()+fw, r.top()+fw, r.width()-fw-bw, r.height()-2*fw ); labelRect = insideMargin( labelRect, ComboBox_ContentsMargin, ComboBox_ContentsMargin_Left, ComboBox_ContentsMargin_Top, ComboBox_ContentsMargin_Right, ComboBox_ContentsMargin_Bottom ); return handleRTL( option, labelRect ); } } default: break; } return QCommonStyle::subControlRect( CC_ComboBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::scrollBarInternalSubControlRect( const QStyleOptionComplex* option, SubControl subControl ) const { const QRect& r = option->rect; const State& flags( option->state ); const bool horizontal( flags&State_Horizontal ); switch ( subControl ) { case SC_ScrollBarSubLine: { int majorSize( scrollBarButtonHeight( _subLineButtons ) ); if( horizontal ) return handleRTL( option, QRect( r.x(), r.y(), majorSize, r.height() ) ); else return handleRTL( option, QRect( r.x(), r.y(), r.width(), majorSize ) ); } case SC_ScrollBarAddLine: { int majorSize( scrollBarButtonHeight( _addLineButtons ) ); if( horizontal ) return handleRTL( option, QRect( r.right() - majorSize, r.y(), majorSize, r.height() ) ); else return handleRTL( option, QRect( r.x(), r.bottom() - majorSize, r.width(), majorSize ) ); } default: return QRect(); } } //___________________________________________________________________________________________________________________ QRect Style::scrollBarSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { const State& flags( option->state ); const bool horizontal( flags&State_Horizontal ); switch ( subControl ) { case SC_ScrollBarSubLine: case SC_ScrollBarAddLine: return scrollBarInternalSubControlRect( option, subControl ); //The main groove area. This is used to compute the others... case SC_ScrollBarGroove: { QRect top = handleRTL( option, scrollBarInternalSubControlRect( option, SC_ScrollBarSubLine ) ); QRect bot = handleRTL( option, scrollBarInternalSubControlRect( option, SC_ScrollBarAddLine ) ); QPoint topLeftCorner; QPoint botRightCorner; if( horizontal ) { topLeftCorner = QPoint( top.right() + 1, top.top() ); botRightCorner = QPoint( bot.left() - 1, top.bottom() ); } else { topLeftCorner = QPoint( top.left(), top.bottom() + 1 ); botRightCorner = QPoint( top.right(), bot.top() - 1 ); } // define rect return handleRTL( option, QRect( topLeftCorner, botRightCorner ) ); } case SC_ScrollBarSlider: { const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return QRect(); //We do handleRTL here to unreflect things if need be QRect groove = handleRTL( option, scrollBarSubControlRect( 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, ( int )ScrollBar_MinimumSliderHeight ); 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 handleRTL( option, QRect( groove.x() + pos, groove.y(), sliderSize, groove.height() ) ); else return handleRTL( option, QRect( groove.x(), groove.y() + pos, groove.width(), sliderSize ) ); } case SC_ScrollBarSubPage: { //We do handleRTL here to unreflect things if need be QRect slider = handleRTL( option, scrollBarSubControlRect( option, SC_ScrollBarSlider, widget ) ); QRect groove = handleRTL( option, scrollBarSubControlRect( option, SC_ScrollBarGroove, widget ) ); if( horizontal ) return handleRTL( option, QRect( groove.x(), groove.y(), slider.x() - groove.x(), groove.height() ) ); else return handleRTL( option, QRect( groove.x(), groove.y(), groove.width(), slider.y() - groove.y() ) ); } case SC_ScrollBarAddPage: { //We do handleRTL here to unreflect things if need be QRect slider = handleRTL( option, scrollBarSubControlRect( option, SC_ScrollBarSlider, widget ) ); QRect groove = handleRTL( option, scrollBarSubControlRect( option, SC_ScrollBarGroove, widget ) ); if( horizontal ) return handleRTL( option, QRect( slider.right() + 1, groove.y(), groove.right() - slider.right(), groove.height() ) ); else return handleRTL( option, QRect( groove.x(), slider.bottom() + 1, groove.width(), groove.bottom() - slider.bottom() ) ); } default: return QRect(); } } //___________________________________________________________________________________________________________________ QRect Style::spinBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { const QRect& r( option->rect ); const QStyleOptionSpinBox *sb = qstyleoption_cast( option ); if( !sb ) return r; int fw = SpinBox_FrameWidth; int bw = SpinBox_ButtonWidth; int bm = SpinBox_ButtonMargin; int bml = bm + SpinBox_ButtonMargin_Left; int bmt = bm + SpinBox_ButtonMargin_Top; int bmr = bm + SpinBox_ButtonMargin_Right; int bmb = bm + SpinBox_ButtonMargin_Bottom; int bs = 0 ; if( !sb->frame ) { bw = bw - bmr; fw = 0; // TODO: why is bml not also set to 0 bmt = bmb = bmr = 0; } const int buttonsWidth = bw-bml-bmr; const int buttonsLeft = r.right()-bw+bml+1; // compute the height of each button... const int availableButtonHeight = r.height()-bmt-bmb - bs; const int heightUp = availableButtonHeight / 2; const int heightDown = availableButtonHeight - heightUp; switch ( subControl ) { case SC_SpinBoxUp: return handleRTL( option, QRect( buttonsLeft, r.top()+bmt, buttonsWidth, heightUp ) ); case SC_SpinBoxDown: return handleRTL( option, QRect( buttonsLeft, r.bottom()-bmb-heightDown, buttonsWidth, heightDown ) ); case SC_SpinBoxEditField: { const QRect labelRect( r.left()+fw, r.top()+fw, r.width()-fw-bw, r.height()-2*fw ); return handleRTL( option, labelRect ); } case SC_SpinBoxFrame: return sb->frame ? r : QRect(); default: break; } return QCommonStyle::subControlRect( CC_SpinBox, option, subControl, widget ); } //______________________________________________________________ QSize Style::checkBoxSizeFromContents( const QStyleOption*, const QSize& contentsSize, const QWidget* ) const { //Add size for indicator const int indicator( CheckBox_Size ); //Make sure we can fit the indicator QSize size( contentsSize ); size.setHeight( qMax( size.height(), indicator ) ); //Add space for the indicator and the icon const int spacer( CheckBox_BoxTextSpace ); size.rwidth() += indicator + spacer; return size; } //______________________________________________________________ QSize Style::comboBoxSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { QSize size = expandSize( contentsSize, ComboBox_ContentsMargin, ComboBox_ContentsMargin_Left, ComboBox_ContentsMargin_Top, ComboBox_ContentsMargin_Right, ComboBox_ContentsMargin_Bottom ); // add frame width size = expandSize( size, ComboBox_FrameWidth ); // Add the button width size.rwidth() += ComboBox_ButtonWidth; // TODO: For some reason the size is not right in the following configurations // this is still to be understood and might reveal some deeper issue. // notably, should compare to zhqt is done for PushButtons const QStyleOptionComboBox *cb = qstyleoption_cast( option ); if( cb && !cb->editable && ( !cb->currentIcon.isNull() || cb->fontMetrics.height() > 13 ) ) size.rheight()+=1; // also expand to account for scrollbar size.rwidth() += StyleConfigData::scrollBarWidth() - 6; return size; } //______________________________________________________________ QSize Style::headerSectionSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { const QStyleOptionHeader* headerOpt( qstyleoption_cast( option ) ); if( !headerOpt ) return contentsSize; //TODO: check if hardcoded icon size is the right thing to do QSize iconSize = headerOpt->icon.isNull() ? QSize( 0,0 ) : QSize( 22,22 ); QSize textSize = headerOpt->fontMetrics.size( 0, headerOpt->text ); int iconSpacing = Header_TextToIconSpace; int w = iconSize.width() + iconSpacing + textSize.width(); int h = qMax( iconSize.height(), textSize.height() ); return expandSize( QSize( w, h ), Header_ContentsMargin ); } //______________________________________________________________ QSize Style::menuItemSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { 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 drawMenuItemContol QSize insideSize; switch ( menuItemOption->menuItemType ) { case QStyleOptionMenuItem::Normal: case QStyleOptionMenuItem::DefaultItem: case QStyleOptionMenuItem::SubMenu: { int iconColW = qMax( menuItemOption->maxIconWidth, ( int ) MenuItem_IconWidth ); int leftColW = iconColW; if( menuItemOption->menuHasCheckableItems ) { leftColW += MenuItem_CheckWidth + MenuItem_CheckSpace; } leftColW += MenuItem_IconSpace; int rightColW = MenuItem_ArrowSpace + MenuItem_ArrowWidth; QFontMetrics fm( menuItemOption->font ); int textW; int tabPos = menuItemOption->text.indexOf( QLatin1Char( '\t' ) ); if( tabPos == -1 ) textW = contentsSize.width(); else { // The width of the accelerator 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() ) textW = contentsSize.width() + MenuItem_AccelSpace; } int h = qMax( contentsSize.height(), ( int ) MenuItem_MinHeight ); insideSize = QSize( leftColW + textW + rightColW, h ); break; } case QStyleOptionMenuItem::Separator: { // separator can have a title and an icon // in that case they are rendered as menubar 'title', which // corresponds to checked toolbuttons. // a rectangle identical to the one of normal items is returned. if( !( menuItemOption->text.isEmpty() && menuItemOption->icon.isNull() ) ) { QStyleOptionMenuItem local( *menuItemOption ); local.menuItemType = QStyleOptionMenuItem::Normal; return menuItemSizeFromContents( &local, contentsSize, widget ); } else { insideSize = QSize( 10, 0 ); break; } } case QStyleOptionMenuItem::Scroller: case QStyleOptionMenuItem::TearOff: case QStyleOptionMenuItem::Margin: case QStyleOptionMenuItem::EmptyArea: return contentsSize; } // apply the outermost margin. return expandSize( insideSize, MenuItem_Margin ); } //______________________________________________________________ QSize Style::pushButtonSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { const QStyleOptionButton* bOpt = qstyleoption_cast( option ); if( !bOpt ) return contentsSize; // adjust to handle button margins QSize size = expandSize( contentsSize, PushButton_ContentsMargin, PushButton_ContentsMargin_Left, PushButton_ContentsMargin_Top, PushButton_ContentsMargin_Right, PushButton_ContentsMargin_Bottom ); if( bOpt->features & QStyleOptionButton::HasMenu ) { size.rwidth() += PushButton_TextToIconSpace; } if( !bOpt->text.isEmpty() && !bOpt->icon.isNull() ) { // Incorporate the spacing between the icon and text. Qt sticks 4 there, // but we use PushButton::TextToIconSpace. size.rwidth() += PushButton_TextToIconSpace -4; } return size; } //______________________________________________________________ QSize Style::tabBarTabSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { const QStyleOptionTab *tabOpt( qstyleoption_cast( option ) ); QSize size; const bool verticalTabs( tabOpt && isVerticalTab( tabOpt ) ); if( verticalTabs ) { size = expandSize( contentsSize, TabBar_TabContentsMargin, TabBar_TabContentsMargin_Top, TabBar_TabContentsMargin_Right, TabBar_TabContentsMargin_Bottom, TabBar_TabContentsMargin_Left ); } else { size = expandSize( contentsSize, TabBar_TabContentsMargin, TabBar_TabContentsMargin_Left, TabBar_TabContentsMargin_Top, TabBar_TabContentsMargin_Right, TabBar_TabContentsMargin_Bottom ); } // need to add extra size to match corner buttons // try cast parent for tabWidget const QTabWidget* tabWidget( widget ? qobject_cast( widget->parent() ):0 ); if( !tabWidget ) return size; // try get corner widgets const QWidget* leftWidget( tabWidget->cornerWidget( Qt::TopLeftCorner ) ); const QWidget* rightWidget( tabWidget->cornerWidget( Qt::TopRightCorner ) ); QSize cornerSize; if( leftWidget && leftWidget->isVisible() ) cornerSize = leftWidget->minimumSizeHint(); if( rightWidget && rightWidget->isVisible() ) cornerSize = cornerSize.expandedTo( rightWidget->minimumSizeHint() ); if( !cornerSize.isValid() ) return size; // expand size // note: the extra pixels added to the relevant dimension are fine-tuned. if( verticalTabs ) size.setWidth( qMax( size.width(), cornerSize.width() + 6 ) ); else size.setHeight( qMax( size.height(), cornerSize.height() + 4 ) ); return size; } //______________________________________________________________ QSize Style::toolButtonSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { QSize size = contentsSize; const QStyleOptionToolButton* tbOpt = qstyleoption_cast( option ); if( tbOpt && !tbOpt->icon.isNull() && !tbOpt->text.isEmpty() && tbOpt->toolButtonStyle == Qt::ToolButtonTextUnderIcon ) { size.rheight() -= 5; } // We want to avoid super-skiny buttons, for things like "up" when icons + text // For this, we would like to make width >= height. // However, once we get here, QToolButton may have already put in the menu area // ( PM_MenuButtonIndicator ) into the width. So we may have to take it out, fix things // up, and add it back in. So much for class-independent rendering... int menuAreaWidth = 0; if( tbOpt ) { if( tbOpt->features & QStyleOptionToolButton::MenuButtonPopup ) { menuAreaWidth = pixelMetric( QStyle::PM_MenuButtonIndicator, option, widget ); } else if( tbOpt->features & QStyleOptionToolButton::HasMenu ) { // TODO: something wrong here: The size is not properly accounted for // when drawing the slab. size.rwidth() += ToolButton_InlineMenuIndicatorSize; } } size.rwidth() -= menuAreaWidth; if( size.width() < size.height() ) size.setWidth( size.height() ); size.rwidth() += menuAreaWidth; const QToolButton* t( qobject_cast( widget ) ); if( t && t->autoRaise() ) return expandSize( size, ToolButton_ContentsMargin ); // these are toolbutton margins else return expandSize( size, PushButton_ContentsMargin, 0, PushButton_ContentsMargin_Top, 0, PushButton_ContentsMargin_Bottom ); } //___________________________________________________________________________________ bool Style::drawFramePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const State& flags( option->state ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); const bool enabled( flags & State_Enabled ); const bool isInputWidget( widget && widget->testAttribute( Qt::WA_Hover ) ); // hover const bool hoverHighlight( enabled && isInputWidget && ( flags&State_MouseOver ) ); // focus bool focusHighlight( false ); if( enabled && ( flags&State_HasFocus ) ) focusHighlight = true; else if( isKTextEditFrame( widget ) && widget->parentWidget()->hasFocus() ) { focusHighlight = true; } if( flags & State_Sunken ) { const QRect local( r.adjusted( 1, 1, -1, -1 ) ); if( frameShadowFactory().isRegistered( widget ) ) { frameShadowFactory().updateState( widget, focusHighlight, hoverHighlight ); } else { HoleOptions options( 0 ); if( focusHighlight ) options |= HoleFocus; if( hoverHighlight ) options |= HoleHover; helper().renderHole( painter, palette.color( QPalette::Window ), local, options, TileSet::Ring ); } } else if( flags & State_Raised ) { const QRect local( r.adjusted( -1, -1, 1, 1 ) ); renderSlab( painter, local, palette.color( QPalette::Background ), NoFill ); } 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& flags( option->state ); const QRect r( option->rect.adjusted( 0, 0, 0, -1 ) ); const QPalette& palette( option->palette ); if( r.width() < 10 ) return true; QLinearGradient lg( r.bottomLeft(), r.bottomRight() ); lg.setColorAt( 0.0, Qt::transparent ); lg.setColorAt( 1.0, Qt::transparent ); if( flags & State_Selected ) { lg.setColorAt( 0.2, palette.color( QPalette::BrightText ) ); lg.setColorAt( 0.8, palette.color( QPalette::BrightText ) ); } else { lg.setColorAt( 0.2, palette.color( QPalette::Text ) ); lg.setColorAt( 0.8, palette.color( QPalette::Text ) ); } painter->setRenderHint( QPainter::Antialiasing, false ); painter->setPen( QPen( lg, 1 ) ); painter->drawLine( r.bottomLeft(), r.bottomRight() ); return true; } //______________________________________________________________ bool Style::drawFrameGroupBoxPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionFrame *fOpt = qstyleoption_cast( option ); if( !fOpt ) return true; // no frame for flat groupboxes QStyleOptionFrameV2 fOpt2( *fOpt ); if( fOpt2.features & QStyleOptionFrameV2::Flat ) return true; // normal frame const QPalette& palette( option->palette ); const QRect& r( option->rect ); const QColor base( helper().backgroundColor( palette.color( QPalette::Window ), widget, r.center() ) ); painter->save(); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); QLinearGradient innerGradient( 0, r.top()-r.height()+12, 0, r.bottom()+r.height()-19 ); QColor light( helper().calcLightColor( base ) ); light.setAlphaF( 0.4 ); innerGradient.setColorAt( 0.0, light ); light.setAlphaF( 0.0 ); innerGradient.setColorAt( 1.0, light ); painter->setBrush( innerGradient ); painter->setClipRect( r.adjusted( 0, 0, 0, -19 ) ); helper().fillSlab( *painter, r ); painter->setClipping( false ); helper().slope( base, 0.0 )->render( r, painter ); painter->restore(); 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 ); } return true; } //___________________________________________________________________________________ bool Style::drawFrameTabBarBasePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const QStyleOptionTabBarBase* tabOpt( qstyleoption_cast( option ) ); if( !tabOpt ) return true; if( tabOpt->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& r( option->rect ); QRect frameRect( r ); SlabRect slab; switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { frameRect.adjust( -7, -GlowWidth, 7, GlowWidth ); frameRect.translate( 0, 4 ); slab = SlabRect( frameRect, TileSet::Top ); break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { frameRect.adjust( -7, -GlowWidth, 7, GlowWidth ); frameRect.translate( 0, -4 ); slab = SlabRect( frameRect, TileSet::Bottom ); break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { frameRect.adjust( -GlowWidth, -7, GlowWidth, 7 + 1 ); frameRect.translate( 5, 0 ); slab = SlabRect( frameRect, TileSet::Left ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { frameRect.adjust( -GlowWidth, -7, GlowWidth, 7 + 1 ); frameRect.translate( -5, 0 ); slab = SlabRect( frameRect, TileSet::Right ); break; } default: return true; } // render registered slabs renderSlab( painter, slab, palette.color( QPalette::Window ), NoFill ); return true; } //___________________________________________________________________________________ bool Style::drawFrameTabWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const QStyleOptionTabWidgetFrame* tabOpt( qstyleoption_cast( option ) ); if( !tabOpt ) return true; const QRect& r( 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( tabOpt->tabBarSize.isEmpty() ) return true; // get tabbar dimentions const int w( tabOpt->tabBarSize.width() ); const int h( tabOpt->tabBarSize.height() ); // left corner widget const int lw( tabOpt->leftCornerWidgetSize.width() ); const int lh( tabOpt->leftCornerWidgetSize.height() ); // right corner const int rw( tabOpt->rightCornerWidgetSize.width() ); const int rh( tabOpt->rightCornerWidgetSize.height() ); // list of slabs to be drawn SlabRectList slabs; // expand rect by glow width. QRect baseSlabRect( insideMargin( r, -GlowWidth ) ); // render the three free sides switch( tabOpt->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() - w - lw, slabRect.left() + rw ) + 7 ); slabRect.setHeight( 7 ); slabs << SlabRect( slabRect, TileSet::TopLeft ); // right side if( rw > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setLeft( slabRect.right() - rw - 7 ); slabRect.setHeight( 7 ); slabs << SlabRect( slabRect, TileSet::TopRight ); } } else { // left side if( lw > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setRight( baseSlabRect.left() + lw + 7 ); slabRect.setHeight( 7 ); slabs << SlabRect( slabRect, TileSet::TopLeft ); } // right side QRect slabRect( baseSlabRect ); slabRect.setLeft( qMin( slabRect.left() + w + lw + 1, slabRect.right() - rw ) -7 ); slabRect.setHeight( 7 ); slabs << SlabRect( slabRect, TileSet::TopRight ); } 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() - w - lw, slabRect.left() + rw ) + 7 ); slabRect.setTop( slabRect.bottom() - 7 ); slabs << SlabRect( slabRect, TileSet::BottomLeft ); // right side if( rw > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setLeft( slabRect.right() - rw - 7 ); slabRect.setTop( slabRect.bottom() - 7 ); slabs << SlabRect( slabRect, TileSet::BottomRight ); } } else { // left side if( lw > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setRight( baseSlabRect.left() + lw + 7 ); slabRect.setTop( slabRect.bottom() - 7 ); slabs << SlabRect( slabRect, TileSet::BottomLeft ); } // right side QRect slabRect( baseSlabRect ); slabRect.setLeft( qMin( slabRect.left() + w + lw + 1, slabRect.right() - rw ) -7 ); slabRect.setTop( slabRect.bottom() - 7 ); slabs << SlabRect( slabRect, TileSet::BottomRight ); } break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Left ); // top side if( lh > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setBottom( baseSlabRect.top() + lh + 7 + 1 ); slabRect.setWidth( 7 ); slabs << SlabRect( slabRect, TileSet::TopLeft ); } // bottom side QRect slabRect( baseSlabRect ); slabRect.setTop( qMin( slabRect.top() + h + lh, slabRect.bottom() - rh ) -7 + 1 ); slabRect.setWidth( 7 ); slabs << SlabRect( slabRect, TileSet::BottomLeft ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Right ); // top side if( lh > 0 ) { QRect slabRect( baseSlabRect ); slabRect.setBottom( baseSlabRect.top() + lh + 7 + 1 ); slabRect.setLeft( slabRect.right()-7 ); slabs << SlabRect( slabRect, TileSet::TopRight ); } // bottom side QRect slabRect( baseSlabRect ); slabRect.setTop( qMin( slabRect.top() + h + lh, slabRect.bottom() - rh ) -7 + 1 ); slabRect.setLeft( slabRect.right()-7 ); slabs << SlabRect( slabRect, TileSet::BottomRight ); break; } break; default: break; } // render registered slabs foreach( const SlabRect& slab, slabs ) { renderSlab( painter, slab, palette.color( QPalette::Window ), NoFill ); } return true; } //___________________________________________________________________________________ bool Style::drawFrameWindowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const QRect& r( option->rect ); const QPalette& palette( option->palette ); helper().drawFloatFrame( painter, r, palette.window().color(), false ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorTabClose( 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 = KIcon( "dialog-close" ); if( _tabCloseIcon.isNull() ) return false; // still not found? cancel } 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::drawIndicatorArrowPrimitive( ArrowOrientation orientation, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { QRect r( option->rect ); const QPalette& palette( option->palette ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); // define gradient and polygon for drawing arrow const QPolygonF a = genericArrow( orientation, ArrowNormal ); const qreal penThickness = 1.6; const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); QColor color; const QToolButton* toolButton( qobject_cast( widget ) ); if( toolButton && toolButton->arrowType() != Qt::NoArrow ) { /* arrows painted in toolbutton need a re-centered rect, and have no highlight */ if( toolButton->arrowType() != Qt::LeftArrow ) { r.translate( 1, 0 ); } // set color properly color = (toolButton->autoRaise() ? palette.color( QPalette::WindowText ):palette.color( QPalette::ButtonText ) ); } else if( mouseOver ) { color = helper().viewHoverBrush().brush( palette ).color(); } else { color = palette.color( QPalette::WindowText ); } painter->translate( r.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( a ); painter->translate( 0,-offset ); painter->setPen( QPen( helper().decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorHeaderArrowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { Q_UNUSED(widget); const QStyleOptionHeader *headerOpt = qstyleoption_cast( option ); const State& flags( option->state ); // arrow orientation ArrowOrientation orientation( ArrowNone ); if( flags&State_UpArrow || ( headerOpt && headerOpt->sortIndicator==QStyleOptionHeader::SortUp ) ) orientation = ArrowUp; else if( flags&State_DownArrow || ( headerOpt && headerOpt->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& r( option->rect ); const QPalette& palette( option->palette ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); // define gradient and polygon for drawing arrow const QPolygonF a = genericArrow( orientation, ArrowNormal ); QColor color = palette.color( QPalette::WindowText ); const QColor background = palette.color( QPalette::Window ); const QColor highlight( helper().viewHoverBrush().brush( palette ).color() ); const qreal penThickness = 1.6; const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); if( mouseOver ) color = highlight; painter->translate( r.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( a ); painter->translate( 0,-offset ); painter->setPen( QPen( helper().decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); return true; } //______________________________________________________________ bool Style::drawPanelButtonCommandPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const QPalette& palette( option->palette ); StyleOptions opts = 0; if( flags & ( State_On|State_Sunken ) ) opts |= Sunken; if( flags & State_HasFocus ) opts |= Focus; if( enabled && ( flags & State_MouseOver ) ) opts |= Hover; // 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 QRect& r( option->rect ); const QStyleOptionButton* bOpt( qstyleoption_cast< const QStyleOptionButton* >( option ) ); bool flat = ( bOpt && ( bOpt->features.testFlag( QStyleOptionButton::Flat ) || ( ( !bOpt->icon.isNull() ) && sizeFromContents( CT_PushButton, option, bOpt->iconSize, widget ).height() > r.height() ) ) ); if( flat ) { QRect slitRect( r ); if( !( opts & Sunken ) ) { // hover rect if( mouseOver ) { helper().slitFocused( helper().viewFocusBrush().brush( QPalette::Active ).color() )->render( slitRect, painter ); } } else { slitRect.adjust( 0, 0, 0, -1 ); HoleOptions options( 0 ); if( mouseOver ) options |= HoleHover; // flat pressed-down buttons do not get focus effect, // consistently with tool buttons helper().renderHole( painter, palette.color( QPalette::Window ), slitRect, options ); } } else { const QRect slabRect( r.adjusted( -1, 0, 1, 0 ) ); // match color to the window background QColor buttonColor( helper().backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) ); // merge button color with highlight in case of default button if( enabled && bOpt && (bOpt->features&QStyleOptionButton::DefaultButton) ) { const QColor tintColor( helper().calcLightColor( buttonColor ) ); buttonColor = KColorUtils::mix( buttonColor, tintColor, 0.5 ); } renderButtonSlab( painter, slabRect, buttonColor, opts ); } return true; } //______________________________________________________________ bool Style::drawPanelButtonToolPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { /* For toolbutton in TabBars, corresponding to expanding arrows, no frame is drawn However one needs to draw the window background, because the button rect might overlap with some tab below. ( this is a Qt bug ) */ const bool isInTabBar( widget && qobject_cast( widget->parent() ) ); if( isInTabBar ) { const QPalette& palette( option->palette ); QRect r( option->rect ); // adjust rect depending on shape const QTabBar* tabBar( static_cast( widget->parent() ) ); switch( tabBar->shape() ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: r.setBottom( r.bottom()-6 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: r.setTop( r.top() + 6 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: r.setRight( r.right() - 6 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: r.setLeft( r.left() + 6 ); 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( r, parent->palette().color( parent->backgroundRole() ) ); else helper().renderWindowBackground( painter, r, widget, local ); return true; } const QRect& r( option->rect ); const State& flags( option->state ); const QPalette& palette( option->palette ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool hasFocus( enabled && ( flags & State_HasFocus ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const bool autoRaised( flags & State_AutoRaise ); // check whether toolbutton is in toolbar const bool isInToolBar( widget && qobject_cast( widget->parent() ) ); // toolbar engine const bool current( isInToolBar && widget && widget->parentWidget()); const bool toolBarTimerActive( isInToolBar && widget ); // slit rect QRect slitRect( r ); // non autoraised tool buttons get same slab as regular buttons if( widget && !autoRaised ) { StyleOptions opts = 0; slitRect.adjust( -1, 0, 1, 0 ); // "normal" parent, and non "autoraised" ( that is: always raised ) buttons if( flags & ( State_On|State_Sunken ) ) opts |= Sunken; if( flags & State_HasFocus ) opts |= Focus; if( enabled && ( flags & State_MouseOver ) ) opts |= Hover; TileSet::Tiles tiles( TileSet::Ring ); // adjust tiles and rect in case of menubutton const QToolButton* t = qobject_cast( widget ); if( t && t->popupMode()==QToolButton::MenuButtonPopup ) { if( reverseLayout ) { tiles = TileSet::Bottom | TileSet::Top | TileSet::Right; slitRect.adjust( -4, 0, 0, 0 ); } else { tiles = TileSet::Bottom | TileSet::Top | TileSet::Left; slitRect.adjust( 0, 0, 4, 0 ); } } // match button color to window background const QColor buttonColor( helper().backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) ); // render slab renderButtonSlab( painter, slitRect, buttonColor, opts, tiles ); return true; } //! fine tuning of slitRect geometry if( widget && widget->inherits( "QToolBarExtension" ) ) slitRect.adjust( 1, 1, -1, -1 ); else if( widget && widget->objectName() == "qt_menubar_ext_button" ) slitRect.adjust( -1, -1, 0, 0 ); // normal ( auto-raised ) toolbuttons if( flags & ( State_Sunken|State_On ) ) { HoleOptions options( HoleContrast ); if( hasFocus && enabled ) options |= HoleFocus; if( mouseOver && enabled ) options |= HoleHover; if( toolBarTimerActive && current ) { helper().renderHole( painter, palette.color( QPalette::Window ), slitRect, options | HoleHover ); } else { helper().renderHole( painter, palette.color( QPalette::Window ), slitRect, options ); } } else { if( hasFocus || mouseOver || ( toolBarTimerActive && current ) ) { helper().slitFocused( helper().viewFocusBrush().brush( QPalette::Active ).color() )->render( slitRect, painter ); } } return true; } //___________________________________________________________________________________ bool Style::drawPanelItemViewItemPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionViewItemV4 *opt = qstyleoption_cast( option ); const QAbstractItemView *view = qobject_cast( widget ); const bool hover = ( option->state & State_MouseOver ) && ( !view || view->selectionMode() != QAbstractItemView::NoSelection ); const bool hasCustomBackground = opt->backgroundBrush.style() != Qt::NoBrush && !( option->state & State_Selected ); const bool hasSolidBackground = !hasCustomBackground || opt->backgroundBrush.style() == Qt::SolidPattern; if( !hover && !( option->state & State_Selected ) && !hasCustomBackground && !( opt->features & QStyleOptionViewItemV2::Alternate ) ) { return true; } QPalette::ColorGroup cg; if( option->state & State_Enabled ) cg = ( option->state & State_Active ) ? QPalette::Normal : QPalette::Inactive; else cg = QPalette::Disabled; QColor color; if( hasCustomBackground && hasSolidBackground ) color = opt->backgroundBrush.color(); else color = option->palette.color( cg, QPalette::Highlight ); if( hover && !hasCustomBackground ) { if( !( option->state & State_Selected ) ) color.setAlphaF( 0.2 ); else color = color.lighter( 110 ); } if( opt && ( opt->features & QStyleOptionViewItemV2::Alternate ) ) { painter->fillRect( option->rect, option->palette.brush( cg, QPalette::AlternateBase ) ); } if( !hover && !( option->state & State_Selected ) && !hasCustomBackground ) { return true; } if( hasCustomBackground && !hasSolidBackground ) { const QPointF oldBrushOrigin = painter->brushOrigin(); painter->setBrushOrigin( opt->rect.topLeft() ); painter->setBrush( opt->backgroundBrush ); painter->setPen( Qt::NoPen ); painter->drawRect( opt->rect ); painter->setBrushOrigin( oldBrushOrigin ); } else { // get selection tileset QRect r = option->rect; TileSet *tileSet( helper().selection( color, r.height(), hasCustomBackground ) ); bool roundedLeft = false; bool roundedRight = false; if( opt ) { roundedLeft = ( opt->viewItemPosition == QStyleOptionViewItemV4::Beginning ); roundedRight = ( opt->viewItemPosition == QStyleOptionViewItemV4::End ); if( opt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne || opt->viewItemPosition == QStyleOptionViewItemV4::Invalid || ( view && view->selectionBehavior() != QAbstractItemView::SelectRows ) ) { roundedLeft = true; roundedRight = true; } } const bool reverseLayout( option->direction == Qt::RightToLeft ); TileSet::Tiles tiles( TileSet::Center ); if( !reverseLayout ? roundedLeft : roundedRight ) tiles |= TileSet::Left; else r.adjust( -8, 0, 0, 0 ); if( !reverseLayout ? roundedRight : roundedLeft ) tiles |= TileSet::Right; else r.adjust( 0, 0, 8, 0 ); if( r.isValid() ) tileSet->render( r, painter, tiles ); } return true; } //___________________________________________________________________________________ bool Style::drawPanelLineEditPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QRect& r( option->rect ); const QPalette& palette( option->palette ); // cast option and check const QStyleOptionFrame *panel = qstyleoption_cast( option ); if( !panel ) return true; const QBrush inputBrush( palette.base() ); const int lineWidth( panel->lineWidth ); if( lineWidth > 0 ) { painter->save(); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); painter->setBrush( inputBrush ); helper().fillHole( *painter, r.adjusted( 0, -1, 0, 0 ) ); drawFramePrimitive( panel, painter, widget ); painter->restore(); } else { painter->fillRect( r.adjusted( 2,2,-2,-2 ), inputBrush ); } return true; } //___________________________________________________________________________________ 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; const QStyleOptionMenuItem* mOpt( qstyleoption_cast( option ) ); if( !( mOpt && widget ) ) return true; const QRect& r = mOpt->rect; const QColor color = mOpt->palette.color( widget->window()->backgroundRole() ); const bool hasAlpha( helper().hasAlphaChannel( widget ) ); if( hasAlpha ) { painter->setCompositionMode( QPainter::CompositionMode_Source ); TileSet *tileSet( helper().roundCorner( color ) ); tileSet->render( r, painter ); painter->setCompositionMode( QPainter::CompositionMode_SourceOver ); painter->setClipRegion( helper().roundedMask( r.adjusted( 1, 1, -1, -1 ) ), Qt::IntersectClip ); } helper().renderMenuBackground( painter, r, widget, mOpt->palette ); if( hasAlpha ) painter->setClipping( false ); helper().drawFloatFrame( painter, r, color, !hasAlpha ); 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::drawPanelTipLabelPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // force registration of widget if( widget && widget->window() ) { shadowHelper().registerWidget( widget->window(), true ); } // parent style painting if frames should not be styled if( !StyleConfigData::toolTipDrawStyledFrames() ) return false; const QRect& r( 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() ) { topColor.setAlpha( 220 ); bottomColor.setAlpha( 220 ); } QLinearGradient gr( 0, r.top(), 0, r.bottom() ); gr.setColorAt( 0, topColor ); gr.setColorAt( 1, bottomColor ); // contrast pixmap QLinearGradient gr2( 0, r.top(), 0, r.bottom() ); gr2.setColorAt( 0.5, helper().calcLightColor( bottomColor ) ); gr2.setColorAt( 0.9, bottomColor ); painter->save(); if( hasAlpha ) { painter->setRenderHint( QPainter::Antialiasing ); QRectF local( r ); local.adjust( 0.5, 0.5, -0.5, -0.5 ); painter->setPen( Qt::NoPen ); painter->setBrush( gr ); painter->drawRoundedRect( local, 4, 4 ); painter->setBrush( Qt::NoBrush ); painter->setPen( QPen( gr2, 1.1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawRoundedRect( local, 3.5, 3.5 ); } else { painter->setPen( Qt::NoPen ); painter->setBrush( gr ); painter->drawRect( r ); painter->setBrush( Qt::NoBrush ); painter->setPen( QPen( gr2, 1.1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawRect( r ); } painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorMenuCheckMarkPrimitive( const QStyleOption *option, QPainter *painter, const QWidget * ) const { const QRect& r( option->rect ); const State& flags( option->state ); const QPalette& palette( option->palette ); const bool enabled( flags & State_Enabled ); StyleOptions opts( NoFill ); if( !enabled ) opts |= Disabled; CheckBoxState state = CheckOn; renderCheckBox( painter, r, palette, opts, state ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorBranchPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const State& flags( option->state ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); const QPoint center( r.center() ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const int centerX = center.x(); const int centerY = center.y(); int expanderAdjust = 0; //draw expander if ( flags & State_Children ) { int sizeLimit = qMin( qMin( r.width(), r.height() ), ( int ) Tree_MaxExpanderSize ); const bool expanderOpen( flags & State_Open ); // make sure size limit is odd if( !( sizeLimit&1 ) ) --sizeLimit; expanderAdjust = sizeLimit/2 + 1; QRect expanderRect = centerRect( r, sizeLimit, sizeLimit ); const int radius( ( expanderRect.width() - 4 ) / 2 ); // flags const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); // color const QColor expanderColor( mouseOver ? helper().viewHoverBrush().brush( palette ).color():palette.color( QPalette::Text ) ); if( !StyleConfigData::viewDrawTriangularExpander() ) { // plus or minus sign used for expanders painter->save(); painter->setPen( expanderColor ); painter->drawLine( center - QPoint( radius, 0 ), center + QPoint( radius, 0 ) ); if( !expanderOpen ) { painter->drawLine( center - QPoint( 0, radius ), center + QPoint( 0, radius ) ); } painter->restore(); } else { // arrows painter->save(); painter->translate( center ); // get size from option QPolygonF a; ArrowSize size = ArrowSmall; qreal penThickness( 1.2 ); qreal offset( 0.5 ); switch( StyleConfigData::viewTriangularExpanderSize() ) { case StyleConfigData::TE_TINY: size = ArrowTiny; break; case StyleConfigData::TE_NORMAL: penThickness = 1.6; offset = 0.0; size = ArrowNormal; break; default: case StyleConfigData::TE_SMALL: size = ArrowSmall; break; } if( expanderOpen ) { painter->translate( 0, offset ); a = genericArrow( ArrowDown, size ); } else { painter->translate( offset, 0 ); a = genericArrow( reverseLayout ? ArrowLeft:ArrowRight, size ); } painter->setPen( QPen( expanderColor, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->setRenderHint( QPainter::Antialiasing ); painter->drawPolyline( a ); painter->restore(); } } // tree branches if( !StyleConfigData::viewDrawTreeBranchLines() ) return true; painter->setPen( KColorUtils::mix( palette.color( QPalette::Text ), palette.color( QPalette::Background ), 0.8 ) ); if ( flags & ( State_Item | State_Children | State_Sibling ) ) { const QLine line( QPoint( centerX, r.top() ), QPoint( centerX, centerY - expanderAdjust ) ); painter->drawLine( line ); } //The right/left ( depending on dir ) line gets drawn if we have an item if ( flags & State_Item ) { const QLine line = reverseLayout ? QLine( QPoint( r.left(), centerY ), QPoint( centerX - expanderAdjust, centerY ) ): QLine( QPoint( centerX + expanderAdjust, centerY ), QPoint( r.right(), centerY ) ); painter->drawLine( line ); } //The bottom if we have a sibling if ( flags & State_Sibling ) { const QLine line( QPoint( centerX, centerY + expanderAdjust ), QPoint( centerX, r.bottom() ) ); painter->drawLine( line ); } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorButtonDropDownPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QPalette& palette( option->palette ); const QRect& r( option->rect ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const bool autoRaise( flags & State_AutoRaise ); const bool sunken( enabled && ( flags & State_Sunken ) ); // match button color to window background const QColor highlight( helper().viewHoverBrush().brush( palette ).color() ); QColor color = palette.color( autoRaise ? QPalette::WindowText:QPalette::ButtonText ); QColor background = palette.color( QPalette::Window ); StyleOptions opts = 0; // define gradient and polygon for drawing arrow QPolygonF a = genericArrow( ArrowDown, ArrowNormal ); qreal penThickness = 1.6; // toolbuttons const QToolButton *tool( qobject_cast( widget ) ); if( tool && tool->popupMode()==QToolButton::MenuButtonPopup ) { if( !autoRaise ) { const bool hasFocus( enabled && ( flags & State_HasFocus ) ); color = palette.color( QPalette::ButtonText ); background = helper().backgroundColor( palette.color( QPalette::Button ), widget, r.center() ); if( hasFocus ) opts |= Focus; if( mouseOver ) opts |= Hover; // paint frame painter->save(); if( reverseLayout ) { QRect frameRect( r.adjusted( 0, 0, 10, 0 ) ); if( flags & ( State_On|State_Sunken ) ) opts |= Sunken; painter->setClipRect( frameRect.adjusted( 0, 0, -8, 0 ), Qt::IntersectClip ); renderButtonSlab( painter, frameRect, background, opts, TileSet::Bottom | TileSet::Top | TileSet::Left ); } else { QRect frameRect( r.adjusted( -10,0,0,0 ) ); if( flags & ( State_On|State_Sunken ) ) opts |= Sunken; painter->setClipRect( frameRect.adjusted( 8, 0, 0, 0 ), Qt::IntersectClip ); renderButtonSlab( painter, frameRect, background, opts, TileSet::Bottom | TileSet::Top | TileSet::Right ); } painter->restore(); // draw separating vertical line const QColor color( palette.color( QPalette::Button ) ); QColor light =helper().alphaColor( helper().calcLightColor( color ), 0.6 ); QColor dark = helper().calcDarkColor( color ); dark.setAlpha( 200 ); int yTop( r.top()+2 ); if( sunken ) yTop += 1; const int yBottom( r.bottom()-4 ); painter->setPen( QPen( light,1 ) ); if( reverseLayout ) { painter->drawLine( r.right()+5, yTop+1, r.right()+5, yBottom ); painter->drawLine( r.right()+3, yTop+2, r.right()+3, yBottom ); painter->setPen( QPen( dark,1 ) ); painter->drawLine( r.right()+4, yTop, r.right()+4, yBottom ); a.translate( 3, 1 ); } else { painter->drawLine( r.x()-5, yTop+1, r.x()-5, yBottom-1 ); painter->drawLine( r.x()-3, yTop+1, r.x()-3, yBottom-1 ); painter->setPen( QPen( dark,1 ) ); painter->drawLine( r.x()-4, yTop, r.x()-4, yBottom ); a.translate( -3,1 ); } } else if( const QStyleOptionToolButton *tbOption = qstyleoption_cast( option ) ) { // handle arrow over animation const bool arrowHover( enabled && mouseOver && ( tbOption->activeSubControls & SC_ToolButtonMenu ) ); if( arrowHover ) color = highlight; else color = palette.color( autoRaise ? QPalette::WindowText:QPalette::ButtonText ); } } else { color = palette.color( autoRaise ? QPalette::WindowText:QPalette::ButtonText ); // smaller down arrow for menu indication on toolbuttons penThickness = 1.4; a = genericArrow( ArrowDown, ArrowSmall ); } painter->translate( r.center() ); painter->setRenderHint( QPainter::Antialiasing ); // white reflection const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( helper().calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->translate( 0,-offset ); painter->setPen( QPen( helper().decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorCheckBoxPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // get rect const QRect& r( option->rect ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool hasFocus( flags & State_HasFocus ); StyleOptions opts( 0 ); if( !enabled ) opts |= Disabled; if( mouseOver ) opts |= Hover; if( hasFocus ) opts |= Focus; // get checkbox state CheckBoxState state; if( flags & State_NoChange ) state = CheckTriState; else if( flags & State_Sunken ) state = CheckSunken; else if( flags & State_On ) state = CheckOn; else state = CheckOff; // match button color to window background QPalette palette( option->palette ); palette.setColor( QPalette::Button, helper().backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) ); renderCheckBox( painter, r, palette, opts, state ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorRadioButtonPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // get rect const QRect& r( option->rect ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool hasFocus( flags & State_HasFocus ); StyleOptions opts( 0 ); if( !enabled ) opts |= Disabled; if( mouseOver ) opts |= Hover; if( hasFocus ) opts |= Focus; // match button color to window background QPalette palette( option->palette ); palette.setColor( QPalette::Button, helper().backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) ); CheckBoxState state; if( flags & State_Sunken ) state = CheckSunken; else if( flags & State_On ) state = CheckOn; else state = CheckOff; renderRadioButton( painter, r, palette, opts, state ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorTabTearPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionTab* tabOpt( qstyleoption_cast( option ) ); if( !tabOpt ) return true; const QRect& r( 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* tabOptV3( qstyleoption_cast( option ) ); bool documentMode( tabOptV3 ? tabOptV3->documentMode : false ); const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : NULL; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); QRect gradientRect( r ); switch( tabOpt->shape ) { case QTabBar::TriangularNorth: case QTabBar::RoundedNorth: gradientRect.adjust( 0, 0, 0, -5 ); if( !reverseLayout ) gradientRect.translate( -GlowWidth,0 ); break; case QTabBar::TriangularSouth: case QTabBar::RoundedSouth: gradientRect.adjust( 0, 5, 0, 0 ); if( !reverseLayout ) gradientRect.translate( -GlowWidth,0 ); break; case QTabBar::TriangularWest: case QTabBar::RoundedWest: gradientRect.adjust( 0, 0, -5, 0 ); gradientRect.translate( 0,-GlowWidth ); break; case QTabBar::TriangularEast: case QTabBar::RoundedEast: gradientRect.adjust( 5, 0, 0, 0 ); gradientRect.translate( 0,-GlowWidth ); break; default: return true; } // fade tabbar QPixmap pm( gradientRect.size() ); pm.fill( Qt::transparent ); QPainter pp( &pm ); const bool verticalTabs( isVerticalTab( tabOpt ) ); int w = 0, h = 0; if( verticalTabs ) h = gradientRect.height(); else w = gradientRect.width(); QLinearGradient grad; if( reverseLayout && !verticalTabs ) grad = QLinearGradient( 0, 0, w, h ); else grad = QLinearGradient( w, h, 0, 0 ); grad.setColorAt( 0, Qt::transparent ); grad.setColorAt( 0.6, Qt::black ); if( widget ) helper().renderWindowBackground( &pp, pm.rect(), widget, palette ); pp.setCompositionMode( QPainter::CompositionMode_DestinationAtop ); pp.fillRect( pm.rect(), QBrush( grad ) ); pp.end(); // draw pixmap painter->drawPixmap( gradientRect.topLeft()+QPoint( 0,-1 ),pm ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorToolBarHandlePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const State& flags( option->state ); const bool horizontal( flags & State_Horizontal ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); int counter( 1 ); if( horizontal ) { const int center( r.left()+r.width()/2 ); for( int j = r.top()+2; j <= r.bottom()-3; j+=3, ++counter ) { if( counter%2 == 0 ) helper().renderDot( painter, QPoint( center+1, j ), palette.color( QPalette::Background ) ); else helper().renderDot( painter, QPoint( center-2, j ), palette.color( QPalette::Background ) ); } } else { const int center( r.top()+r.height()/2 ); for( int j = r.left()+2; j <= r.right()-3; j+=3, ++counter ) { if( counter%2 == 0 ) helper().renderDot( painter, QPoint( j, center+1 ), palette.color( QPalette::Background ) ); else helper().renderDot( painter, QPoint( j, center-2 ), palette.color( QPalette::Background ) ); } } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorToolBarSeparatorPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const State& flags( option->state ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); if( StyleConfigData::toolBarDrawItemSeparator() ) { const QColor color( palette.color( QPalette::Window ) ); if( flags & State_Horizontal ) helper().drawSeparator( painter, r, color, Qt::Vertical ); else helper().drawSeparator( painter, r, color, Qt::Horizontal ); } 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::drawCapacityBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option const QStyleOptionProgressBar* cbOption( qstyleoption_cast( option ) ); if( !cbOption ) return true; // draw container QStyleOptionProgressBarV2 sub_opt( *cbOption ); sub_opt.rect = subElementRect( QStyle::SE_ProgressBarGroove, cbOption, widget ); drawProgressBarGrooveControl( &sub_opt, painter, widget ); // draw bar sub_opt.rect = subElementRect( QStyle::SE_ProgressBarContents, cbOption, widget ); drawProgressBarContentsControl( &sub_opt, painter, widget ); // draw label sub_opt.rect = subElementRect( QStyle::SE_ProgressBarLabel, cbOption, widget ); drawProgressBarLabelControl( &sub_opt, painter, widget ); return true; } //___________________________________________________________________________________ bool Style::drawComboBoxLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { //same as CommonStyle, except for filling behind icon if( const QStyleOptionComboBox *cb = qstyleoption_cast( option ) ) { QRect editRect( subControlRect( CC_ComboBox, cb, SC_ComboBoxEditField, widget ) ); painter->save(); if( !cb->currentIcon.isNull() ) { QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; QPixmap pixmap( cb->currentIcon.pixmap( cb->iconSize, mode ) ); QRect iconRect( editRect ); iconRect.setWidth( cb->iconSize.width() + 4 ); iconRect = alignedRect( cb->direction, Qt::AlignLeft | Qt::AlignVCenter, iconRect.size(), editRect ); drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); if( cb->direction == Qt::RightToLeft ) editRect.adjust( 0, 0, -4-cb->iconSize.width(), 0 ); else editRect.adjust( cb->iconSize.width() + 4, 0, 0, 0 ); } if( !cb->currentText.isEmpty() && !cb->editable ) { const bool hasFrame( cb->frame ); // add extra 1 pixel horizontal margin QRect textRect( editRect.adjusted( 1, 0, -1, 0 ) ); // add extra vertical translation to fix positioning issue introduced with Qt-4.8 // when no icon is set if( cb->currentIcon.isNull() ) textRect.translate( 0, -1 ); const QPalette::ColorRole role( hasFrame ? QPalette::ButtonText : QPalette::WindowText ); drawItemText( painter, textRect, visualAlignment( cb->direction, Qt::AlignLeft | Qt::AlignVCenter ), cb->palette, cb->state & State_Enabled, cb->currentText, role ); } painter->restore(); return true; } else return false; } //___________________________________________________________________________________ bool Style::drawDockWidgetTitleControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionDockWidget* dwOpt = ::qstyleoption_cast( option ); if ( !dwOpt ) return true; const QPalette& palette( option->palette ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // cast to v2 to check vertical bar const QStyleOptionDockWidgetV2 *v2 = qstyleoption_cast( option ); const bool verticalTitleBar( v2 ? v2->verticalTitleBar : false ); const QRect btnr( subElementRect( dwOpt->floatable ? SE_DockWidgetFloatButton : SE_DockWidgetCloseButton, option, widget ) ); // get rectangle and adjust to properly accounts for buttons QRect r( insideMargin( dwOpt->rect, DockWidget_TitleMargin ) ); if( verticalTitleBar ) { if( btnr.isValid() ) r.setTop( btnr.bottom()+1 ); } else if( reverseLayout ) { if( btnr.isValid() ) r.setLeft( btnr.right()+1 ); r.adjust( 0,0,-4,0 ); } else { if( btnr.isValid() ) r.setRight( btnr.left()-1 ); r.adjust( 4,0,0,0 ); } QString title( dwOpt->title ); QString tmpTitle = title; // this is quite suboptimal // and does not really work if( tmpTitle.contains( "&" ) ) { int pos = tmpTitle.indexOf( "&" ); if( !( tmpTitle.size()-1 > pos && tmpTitle.at( pos+1 ) == QChar( '&' ) ) ) tmpTitle.remove( pos, 1 ); } int tw = dwOpt->fontMetrics.width( tmpTitle ); int width = verticalTitleBar ? r.height() : r.width(); if( width < tw ) title = dwOpt->fontMetrics.elidedText( title, Qt::ElideRight, width, Qt::TextShowMnemonic ); if( verticalTitleBar ) { QSize s = r.size(); s.transpose(); r.setSize( s ); painter->save(); painter->translate( r.left(), r.top() + r.width() ); painter->rotate( -90 ); painter->translate( -r.left(), -r.top() ); drawItemText( painter, r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette, enabled, title, QPalette::WindowText ); painter->restore(); } else { drawItemText( painter, r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette, enabled, title, QPalette::WindowText ); } 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 ); 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::drawHeaderLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const QStyleOptionHeader* headerOpt( qstyleoption_cast( option ) ); if( !headerOpt ) return true; QRect rect( headerOpt->rect ); if ( !headerOpt->icon.isNull() ) { const QPixmap pixmap( headerOpt->icon.pixmap( pixelMetric( PM_SmallIconSize ), ( headerOpt->state & State_Enabled ) ? QIcon::Normal : QIcon::Disabled ) ); int pixw = pixmap.width(); QRect aligned = alignedRect( headerOpt->direction, QFlag( headerOpt->iconAlignment ), pixmap.size(), rect ); QRect inter = aligned.intersected( rect ); painter->drawPixmap( inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width(), inter.height() ); if ( headerOpt->direction == Qt::LeftToRight ) rect.setLeft( rect.left() + pixw + 2 ); else rect.setRight( rect.right() - pixw - 2 ); } drawItemText( painter, rect, headerOpt->textAlignment, headerOpt->palette, ( headerOpt->state & State_Enabled ), headerOpt->text, QPalette::WindowText ); return true; } //___________________________________________________________________________________ bool Style::drawHeaderSectionControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QRect& r( option->rect ); const QPalette& palette( option->palette ); const QStyleOptionHeader* headerOpt( qstyleoption_cast( option ) ); if( !headerOpt ) return true; const bool horizontal( headerOpt->orientation == Qt::Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const bool isFirst( horizontal && ( headerOpt->position == QStyleOptionHeader::Beginning ) ); const bool isCorner( widget && widget->inherits( "QTableCornerButton" ) ); // corner header lines if( isCorner ) { if( widget ) helper().renderWindowBackground( painter, r, widget, palette ); else painter->fillRect( r, palette.color( QPalette::Window ) ); if( reverseLayout ) renderHeaderLines( r, palette, painter, TileSet::BottomLeft ); else renderHeaderLines( r, palette, painter, TileSet::BottomRight ); } else renderHeaderBackground( r, palette, painter, widget, horizontal, reverseLayout ); // dots const QColor color( palette.color( QPalette::Window ) ); if( horizontal ) { if( headerOpt->section != 0 || isFirst ) { const int center( r.center().y() ); const int pos( reverseLayout ? r.left()+1 : r.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( r.center().x() ); const int pos( r.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::drawMenuBarItemControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { Q_UNUSED(widget); const QStyleOptionMenuItem* menuOpt = ::qstyleoption_cast( option ); if ( !menuOpt ) return true; const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); // text QPalette::ColorRole role( QPalette::WindowText ); if( StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG && ( flags & State_Sunken ) && enabled ) { role = QPalette::HighlightedText; } drawItemText( painter, r, Qt::AlignCenter | Qt::TextShowMnemonic, palette, enabled, menuOpt->text, role ); return true; } //___________________________________________________________________________________ bool Style::drawMenuItemControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QRect& r( option->rect ); const QPalette& palette( option->palette ); const State& flags( option->state ); const bool active( flags & State_Selected ); const bool enabled( flags & State_Enabled ); const bool hasFocus( enabled && ( flags & State_HasFocus ) ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); // do nothing if invalid option, or empty area const QStyleOptionMenuItem* menuItemOption = qstyleoption_cast( option ); if( !menuItemOption || menuItemOption->menuItemType == QStyleOptionMenuItem::EmptyArea ) return true; //First, figure out the left column width. const int iconColW = qMax( menuItemOption->maxIconWidth, ( int )MenuItem_IconWidth ); const int checkColW = MenuItem_CheckWidth; const int checkSpace = MenuItem_CheckSpace; int leftColW = iconColW; // only use the additional check row if the menu has checkable menuItems. bool hasCheckableItems = menuItemOption->menuHasCheckableItems; if( hasCheckableItems ) leftColW += checkColW + checkSpace; // right arrow column... int rightColW = MenuItem_ArrowSpace + MenuItem_ArrowWidth; //Separators: done with the bg, can paint them and bail them out. if( menuItemOption->menuItemType == QStyleOptionMenuItem::Separator ) { // check text and icon // separators with non empty text are rendered as checked toolbuttons if( !menuItemOption->text.isEmpty() ) { QStyleOptionToolButton toolButtonOpt; toolButtonOpt.features = QStyleOptionToolButton::None; toolButtonOpt.state = State_On|State_Sunken|State_Enabled; toolButtonOpt.rect = r.adjusted( 0, 0, 0, 1 ); toolButtonOpt.subControls = SC_ToolButton; toolButtonOpt.icon = menuItemOption->icon; toolButtonOpt.font = widget->font(); toolButtonOpt.font.setBold( true ); toolButtonOpt.iconSize = QSize( pixelMetric( QStyle::PM_SmallIconSize,0,0 ), pixelMetric( QStyle::PM_SmallIconSize,0,0 ) ); // for now menu size is not calculated properly // ( meaning it doesn't account for titled separators width // as a fallback, we elide the text to be displayed int width( r.width() ); if( !menuItemOption->icon.isNull() ) { width -= toolButtonOpt.iconSize.width() + 2; } width -= 2*ToolButton_ContentsMargin; toolButtonOpt.text = QFontMetrics( toolButtonOpt.font ).elidedText( menuItemOption->text, Qt::ElideRight, width ); toolButtonOpt.toolButtonStyle = Qt::ToolButtonTextBesideIcon; drawToolButtonComplexControl( &toolButtonOpt, painter, widget ); return true; } else { // in all other cases draw regular separator const QColor color( helper().menuBackgroundColor( palette.color( QPalette::Window ), widget, r.center() ) ); helper().drawSeparator( painter, r, color, Qt::Horizontal ); return true; } } //Remove the margin ( for everything but the column background ) const QRect ir( insideMargin( r, MenuItem_Margin ) ); //Active indicator... if( active && enabled ) { const QColor color( helper().menuBackgroundColor( helper().calcMidColor( palette.color( QPalette::Window ) ), widget, r.center() ) ); renderMenuItemRect( option, r, color, palette, painter ); } // color QPalette::ColorRole textRole( ( active && enabled && StyleConfigData::menuHighlightMode() == StyleConfigData::MM_STRONG ) ? QPalette::HighlightedText: QPalette::WindowText ); //Readjust the column rectangle back to proper height QRect leftColRect( ir.x(), ir.y(), leftColW, ir.height() ); // paint a normal check- resp. radiomark. const QRect checkColRect( leftColRect.x(), leftColRect.y(), checkColW, leftColRect.height() ); const CheckBoxState checkBoxState( menuItemOption->checked ? CheckOn:CheckOff ); if( menuItemOption->checkType == QStyleOptionMenuItem::NonExclusive ) { StyleOptions opts( 0 ); opts |= Sunken; if( !enabled ) opts |= Disabled; if( mouseOver ) opts |= Hover; if( hasFocus ) opts |= Focus; const QRect r( handleRTL( option, checkColRect ) ); QPalette localPalette( palette ); localPalette.setColor( QPalette::Window, helper().menuBackgroundColor( palette.color( QPalette::Window ), widget, r.topLeft() ) ); renderCheckBox( painter, r.adjusted( 2,-2,2,2 ), localPalette, opts, checkBoxState ); } else if( menuItemOption->checkType == QStyleOptionMenuItem::Exclusive ) { StyleOptions opts( 0 ); if( !enabled ) opts |= Disabled; if( mouseOver ) opts |= Hover; if( hasFocus ) opts |= Focus; const QRect r( handleRTL( option, checkColRect ) ); QPalette localPalette( palette ); localPalette.setColor( QPalette::Window, helper().menuBackgroundColor( palette.color( QPalette::Window ), widget, r.topLeft() ) ); renderRadioButton( painter, r.adjusted( 2,-2,2,2 ), localPalette, opts, checkBoxState ); } // Paint the menu icon. if( !menuItemOption->icon.isNull() ) { QRect iconColRect; if( hasCheckableItems ) { iconColRect = QRect( leftColRect.x()+checkColW+checkSpace, leftColRect.y(), leftColRect.width()-( checkColW+checkSpace ), leftColRect.height() ); } else iconColRect = leftColRect; // icon mode QIcon::Mode mode; if( enabled ) mode = active ? QIcon::Active: QIcon::Normal; else mode = QIcon::Disabled; // icon state const QIcon::State iconState( ( ( flags & State_On ) || ( flags & State_Sunken ) ) ? QIcon::On:QIcon::Off ); // icon size const QSize size( pixelMetric( PM_SmallIconSize ), pixelMetric( PM_SmallIconSize ) ); const QRect r( handleRTL( option, centerRect( iconColRect, size ) ) ); const QPixmap icon = menuItemOption->icon.pixmap( size, mode, iconState ); painter->drawPixmap( centerRect( r, size ), icon ); } //Now include the spacing when calculating the next columns leftColW += MenuItem_IconSpace; //Render the text, including any accel. QString text = menuItemOption->text; const QRect textRect( handleRTL( option, QRect( ir.x() + leftColW, ir.y(), ir.width() - leftColW - rightColW, ir.height() ) ) ); painter->setFont( menuItemOption->font ); int tabPos = menuItemOption->text.indexOf( QLatin1Char( '\t' ) ); if( tabPos != -1 ) { text = menuItemOption->text.left( tabPos ); QString accl = menuItemOption->text.mid( tabPos + 1 ); drawItemText( painter, textRect, Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::AlignRight, palette, enabled, accl, textRole ); } //Draw the text. drawItemText( painter, textRect, Qt::AlignVCenter | Qt::TextShowMnemonic, palette, enabled, text, textRole ); //Render arrow, if need be. if( menuItemOption->menuItemType == QStyleOptionMenuItem::SubMenu ) { const qreal penThickness = 1.6; const QColor color = palette.color( textRole ); const QColor background = palette.color( QPalette::Window ); const int aw = MenuItem_ArrowWidth; QRect arrowRect = handleRTL( option, QRect( ir.x() + ir.width() - aw, ir.y(), aw, ir.height() ) ); // get arrow shape QPolygonF a = genericArrow( option->direction == Qt::LeftToRight ? ArrowRight : ArrowLeft, ArrowNormal ); painter->translate( arrowRect.center() ); painter->setRenderHint( QPainter::Antialiasing ); // white reflection const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( helper().calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->translate( 0,-offset ); painter->setPen( QPen( helper().decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { if( const QStyleOptionProgressBar *pb = qstyleoption_cast( option ) ) { // same as QCommonStyle::drawControl, except that it handles animations QStyleOptionProgressBarV2 subopt = *pb; subopt.rect = subElementRect( SE_ProgressBarGroove, pb, widget ); drawProgressBarGrooveControl( &subopt, painter, widget ); subopt.rect = subElementRect( SE_ProgressBarContents, &subopt, widget ); drawProgressBarContentsControl( &subopt, painter, widget ); if( pb->textVisible ) { subopt.rect = subElementRect( SE_ProgressBarLabel, pb, widget ); drawProgressBarLabelControl( &subopt, painter, widget ); } } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarContentsControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { Q_UNUSED(widget); const QStyleOptionProgressBar* pbOpt = qstyleoption_cast( option ); if ( !pbOpt ) return true; const QStyleOptionProgressBarV2* pbOpt2 = qstyleoption_cast( option ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); // check if anything is to be drawn qreal progress = pbOpt->progress - pbOpt->minimum; const bool busyIndicator = ( pbOpt->minimum == pbOpt->maximum ); if( busyIndicator && widget ) { // load busy value from widget property QVariant busyValue( widget->property( PropertyNames::progressValue ) ); if( busyValue.isValid() ) progress = busyValue.toReal(); } if( !( progress || busyIndicator ) ) return true; const int steps = qMax( pbOpt->maximum - pbOpt->minimum, 1 ); const bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal; //Calculate width fraction qreal widthFrac( busyIndicator ? ProgressBar_BusyIndicatorSize/100.0 : progress/steps ); widthFrac = qMin( (qreal)1.0, widthFrac ); // And now the pixel width const int indicatorSize( widthFrac*( horizontal ? r.width():r.height() ) ); // do nothing if indicator size is too small if( indicatorSize < 4 ) return true; QRect indicatorRect; if ( busyIndicator ) { // The space around which we move around... int remSize = ( ( 1.0 - widthFrac )*( horizontal ? r.width():r.height() ) ); remSize = qMax( remSize, 1 ); int pstep = int( progress )%( 2*remSize ); if ( pstep > remSize ) { pstep = -( pstep - 2*remSize ); } if ( horizontal ) indicatorRect = QRect( r.x() + pstep, r.y(), indicatorSize, r.height() ); else indicatorRect = QRect( r.x(), r.y() + pstep, r.width(), indicatorSize ); } else { if ( horizontal ) indicatorRect = QRect( r.x(), r.y(), indicatorSize, r.height() ); else indicatorRect = QRect( r.x(), r.bottom()- indicatorSize + 1, r.width(), indicatorSize ); } // handle right to left indicatorRect = handleRTL( option, indicatorRect ); // make sure rect is large enough /* this account for adjustments done here and in StyleHelper::progressBarIndicator */ if( indicatorRect.adjusted( 2, 1, -2, -1 ).isValid() ) { indicatorRect.adjust( 1, 0, -1, -1 ); // calculate dimension int dimension( 20 ); if( pbOpt2 ) dimension = qMax( 5, horizontal ? indicatorRect.height() : indicatorRect.width() ); TileSet* tileSet( helper().progressBarIndicator( palette, dimension ) ); tileSet->render( indicatorRect, painter, TileSet::Full ); } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarGrooveControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const QStyleOptionProgressBarV2 *pbOpt = qstyleoption_cast( option ); const Qt::Orientation orientation( pbOpt? pbOpt->orientation : Qt::Horizontal ); // ajust rect for alignment QRect rect( option->rect ); if( orientation == Qt::Horizontal ) rect.adjust( 1, 0, -1, 0 ); else rect.adjust( 0, 1, 0, -1 ); renderScrollBarHole( painter, rect, option->palette.color( QPalette::Window ), orientation ); return true; } //___________________________________________________________________________________ bool Style::drawProgressBarLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const QStyleOptionProgressBar* pbOpt = qstyleoption_cast( option ); if( !pbOpt ) return true; const QRect& r( option->rect ); const QPalette& palette( option->palette ); const State& flags( option->state ); const bool enabled( flags&State_Enabled ); const QStyleOptionProgressBarV2* pbOpt2 = qstyleoption_cast( option ); const bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal; const bool reverseLayout = ( option->direction == Qt::RightToLeft ); // rotate label for vertical layout if( ! ( horizontal || reverseLayout ) ) { painter->translate( r.topRight() ); painter->rotate( 90.0 ); } else if( !horizontal ) { painter->translate( r.bottomLeft() ); painter->rotate( -90.0 ); } Qt::Alignment hAlign( ( pbOpt->textAlignment == Qt::AlignLeft ) ? Qt::AlignHCenter : pbOpt->textAlignment ); /* Figure out the geometry of the indicator. This is copied from drawProgressBarContentsControl */ QRect progressRect; const QRect textRect( horizontal? r : QRect( 0, 0, r.height(), r.width() ) ); const qreal progress = pbOpt->progress - pbOpt->minimum; const int steps = qMax( pbOpt->maximum - pbOpt->minimum, 1 ); const bool busyIndicator = ( steps <= 1 ); int indicatorSize( 0 ); if( !busyIndicator ) { const qreal widthFrac = qMin( (qreal)1.0, progress / steps ); indicatorSize = widthFrac*( horizontal ? r.width() : r.height() ) - (horizontal ? 2:1); } if( indicatorSize > 0 ) { if ( horizontal ) painter->setClipRect( handleRTL( option, QRect( r.x(), r.y(), indicatorSize, r.height() ) ) ); else if ( !reverseLayout ) painter->setClipRect( QRect( r.height()-indicatorSize, 0, r.height(), r.width() ) ); else painter->setClipRect( QRect( 0, 0, indicatorSize, r.width() ) ); // first pass ( highlighted ) drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, pbOpt->text, QPalette::HighlightedText ); // second pass ( normal ) if( horizontal ) painter->setClipRect( handleRTL( option, QRect( r.x() + indicatorSize, r.y(), r.width() - indicatorSize, r.height() ) ) ); else if( !reverseLayout ) painter->setClipRect( QRect( 0, 0, r.height() - indicatorSize, r.width() ) ); else painter->setClipRect( QRect( indicatorSize, 0, r.height()- indicatorSize, r.width() ) ); drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, pbOpt->text, QPalette::WindowText ); } else { drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, pbOpt->text, QPalette::WindowText ); } return true; } //___________________________________________________________________________________ bool Style::drawPushButtonLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const QStyleOptionButton* bOpt = qstyleoption_cast( option ); if ( !bOpt ) return true; const QRect& r( option->rect ); const QPalette& palette( option->palette ); const State& flags( option->state ); const bool active( ( flags & State_On ) || ( flags & State_Sunken ) ); const bool enabled( flags & State_Enabled ); const bool hasFocus( flags & State_HasFocus ); const bool flat( bOpt->features.testFlag( QStyleOptionButton::Flat ) ); //Extract out coordinates for easier manipulation int x, y, w, h; r.getRect( &x, &y, &w, &h ); //Layout the stuff. if ( bOpt->features & QStyleOptionButton::HasMenu ) { const int indicatorWidth( PushButton_MenuIndicatorSize ); const int indicatorSpacing = PushButton_TextToIconSpace; w -= indicatorWidth + indicatorSpacing; // arrow const QRect arrowRect( x + w + indicatorSpacing, y+1, indicatorWidth, h ); const qreal penThickness = 1.6; QPolygonF a = 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( arrowRect.center() ); painter->setRenderHint( QPainter::Antialiasing ); const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( helper().calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->translate( 0,-offset ); painter->setPen( QPen( helper().decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->restore(); } // Draw the icon if there is one if( !bOpt->icon.isNull() ) { if ( !bOpt->text.isEmpty() ) { const int margin = PushButton_TextToIconSpace; const int length = bOpt->iconSize.width() + margin + painter->fontMetrics().size( Qt::TextShowMnemonic, bOpt->text ).width(); //Calculate offset. const int offset = ( w - length )/2; const QRect iconRect( handleRTL( bOpt, QRect( QPoint( x + offset, y + h/2 - bOpt->iconSize.height()/2 ), bOpt->iconSize ) ) ); QIcon::Mode mode; if( enabled ) mode = ( hasFocus ) ? QIcon::Active: QIcon::Normal; else mode = QIcon::Disabled; QIcon::State iconState = active ? QIcon::On : QIcon::Off; QSize size = bOpt->iconSize; if( !size.isValid() ) size = QSize( pixelMetric( PM_SmallIconSize ), pixelMetric( PM_SmallIconSize ) ); QPixmap icon = bOpt->icon.pixmap( size, mode, iconState ); painter->drawPixmap( centerRect( iconRect, icon.size() ), icon ); //new bounding rect for the text x += offset + bOpt->iconSize.width() + margin; w = length - bOpt->iconSize.width() - margin; } else { const QRect iconRect( x, y, w, h ); QIcon::Mode mode; if( enabled ) mode = ( hasFocus ) ? QIcon::Active: QIcon::Normal; else mode = QIcon::Disabled; QIcon::State iconState = active ? QIcon::On : QIcon::Off; QSize size = bOpt->iconSize; if( !size.isValid() ) size = QSize( pixelMetric( PM_SmallIconSize ), pixelMetric( PM_SmallIconSize ) ); QPixmap icon = bOpt->icon.pixmap( size, mode, iconState ); painter->drawPixmap( centerRect( iconRect, icon.size() ), icon ); } } else { //Center the text int textW = painter->fontMetrics().size( Qt::TextShowMnemonic, bOpt->text ).width(); x += ( w - textW )/2; w = textW; } QRect textRect( handleRTL( bOpt, QRect( x, y, w, h ) ) ); if( !bOpt->icon.isNull() ) textRect.adjust( 0, 0, 0, 1 ); const QPalette::ColorRole role( flat ? QPalette::WindowText : QPalette::ButtonText ); drawItemText( painter, textRect, Qt::AlignCenter | Qt::TextShowMnemonic, palette, enabled, bOpt->text, role ); return true; } //___________________________________________________________________________________ bool Style::drawRubberBandControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { if( const QStyleOptionRubberBand *rbOpt = qstyleoption_cast( option ) ) { painter->save(); QColor color = rbOpt->palette.color( QPalette::Highlight ); painter->setPen( KColorUtils::mix( color, rbOpt->palette.color( QPalette::Active, QPalette::WindowText ) ) ); color.setAlpha( 50 ); painter->setBrush( color ); painter->setClipRegion( rbOpt->rect ); painter->drawRect( rbOpt->rect.adjusted( 0,0,-1,-1 ) ); painter->restore(); return true; } else return false; } //___________________________________________________________________________________ bool Style::drawScrollBarSliderControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { Q_UNUSED(widget); // cast option and check const QStyleOptionSlider *sliderOption = qstyleoption_cast( option ); if( !sliderOption ) return true; QRect r( option->rect ); const QPalette& palette( option->palette ); const State& flags( option->state ); const bool horizontal( flags & State_Horizontal ); const bool enabled( flags&State_Enabled ); const bool mouseOver( enabled && ( flags&State_MouseOver ) ); if( horizontal ) { // adjust rect r.adjust( 0, 1, 0, -1 ); const bool reverseLayout( option->direction == Qt::RightToLeft ); if( reverseLayout ) { if( _addLineButtons == NoButton ) r.adjust( -2, 0, 0, 0 ); if( _subLineButtons == NoButton ) r.adjust( 0, 0, -1, 0 ); } else { if( _addLineButtons == NoButton ) r.adjust( 0, 0, 2, 0 ); if( _subLineButtons == NoButton ) r.adjust( 1, 0, 0, 0 ); } // prepare hole rendering QRect holeRect( r.adjusted( -4, 0, 4, 0 ) ); if( reverseLayout ) { if( _addLineButtons == NoButton ) holeRect.adjust( -1, 0, 0, 0 ); if( _subLineButtons == NoButton ) holeRect.adjust( 0, 0, 1, 0 ); } else if( _subLineButtons == NoButton ) holeRect.adjust( -1, 0, 0, 0 ); // check if scrollbar is at maximum or minimum TileSet::Tiles tiles( TileSet::Vertical ); if( _addLineButtons == NoButton && sliderOption->sliderValue == sliderOption->maximum ) { if( reverseLayout ) { tiles |= TileSet::Left; holeRect.adjust( 5, 0, 0, 0 ); } else { tiles |= TileSet::Right; holeRect.adjust( 0, 0, -4, 0 ); } } if( _subLineButtons == NoButton && sliderOption->sliderValue == sliderOption->minimum ) { if( reverseLayout ) { tiles |= TileSet::Right; holeRect.adjust( 0, 0, -5, 0 ); } else { tiles |= TileSet::Left; holeRect.adjust( 5, 0, 0, 0 ); } } // render renderScrollBarHole( painter, holeRect, palette.color( QPalette::Window ), Qt::Horizontal, tiles ); renderScrollBarHandle( painter, r, palette, Qt::Horizontal, mouseOver ); } else { // adjust rect r.adjust( 1, 0, -1, 0 ); // prepare hole rendering TileSet::Tiles tiles( TileSet::Horizontal ); QRect holeRect( r.adjusted( 0, -3, 0, 4 ) ); // check if scrollbar is at maximum or minimum if( _addLineButtons == NoButton && sliderOption->sliderValue == sliderOption->maximum ) { tiles |= TileSet::Bottom; holeRect.adjust( 0, 0, 0, -4 ); } if( _subLineButtons == NoButton && sliderOption->sliderValue == sliderOption->minimum ) { tiles |= TileSet::Top; holeRect.adjust( 0, 5, 0, 0 ); } // render renderScrollBarHole( painter, holeRect, palette.color( QPalette::Window ), Qt::Vertical, tiles ); renderScrollBarHandle( painter, r, palette, Qt::Vertical, 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& flags( option->state ); const bool horizontal( flags & 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 r( scrollBarInternalSubControlRect( sliderOption, SC_ScrollBarAddLine ) ); // draw the end of the scrollbar groove if( horizontal ) { if( reverseLayout ) renderScrollBarHole( painter, QRect( r.right(), r.top()+1, 6, r.height()-2 ), background, Qt::Horizontal, TileSet::Vertical | TileSet::Left ); else renderScrollBarHole( painter, QRect( r.left()-5, r.top()+1, 6, r.height()-2 ), background, Qt::Horizontal, TileSet::Vertical | TileSet::Right ); } else { QRect holeRect( r.left()+1, r.top()-5, r.width()-2, 6 ); renderScrollBarHole( painter, holeRect, background, Qt::Vertical, TileSet::Bottom | TileSet::Horizontal ); } QColor color; QStyleOptionSlider localOption( *sliderOption ); if( _addLineButtons == DoubleButton ) { if( horizontal ) { //Draw the arrows const QSize halfSize( r.width()/2, r.height() ); const QRect leftSubButton( r.topLeft(), halfSize ); const QRect rightSubButton( leftSubButton.topRight() + QPoint( 1, 0 ), halfSize ); localOption.rect = leftSubButton; color = scrollBarArrowColor( &localOption, reverseLayout ? SC_ScrollBarAddLine:SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, leftSubButton, color, background, ArrowLeft ); localOption.rect = rightSubButton; color = scrollBarArrowColor( &localOption, reverseLayout ? SC_ScrollBarSubLine:SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, rightSubButton, color, background, ArrowRight ); } else { const QSize halfSize( r.width(), r.height()/2 ); const QRect topSubButton( r.topLeft(), halfSize ); const QRect botSubButton( topSubButton.bottomLeft() + QPoint( 0, 1 ), halfSize ); localOption.rect = topSubButton; color = scrollBarArrowColor( &localOption, SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, topSubButton, color, background, ArrowUp ); localOption.rect = botSubButton; color = scrollBarArrowColor( &localOption, SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, botSubButton, color, background, ArrowDown ); } } else if( _addLineButtons == SingleButton ) { localOption.rect = r; color = scrollBarArrowColor( &localOption, SC_ScrollBarAddLine, widget ); if( horizontal ) renderScrollBarArrow( painter, r, color, background, reverseLayout ? ArrowLeft : ArrowRight ); else renderScrollBarArrow( painter, r, color, background, ArrowDown ); } return true; } //___________________________________________________________________________________ bool Style::drawScrollBarAddPageControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); if ( !sliderOption ) return true; QRect r( option->rect ); const QPalette& palette( option->palette ); const QColor color( palette.color( QPalette::Window ) ); const State& flags( option->state ); const bool horizontal( flags & State_Horizontal ); const bool reverseLayout( sliderOption->direction == Qt::RightToLeft ); // define tiles and adjust rect if( horizontal ) { TileSet::Tiles tiles( TileSet::Vertical ); if( reverseLayout ) { if( _addLineButtons == NoButton ) { tiles |= TileSet::Left; r.adjust( -2, 1, 10, -1 ); } else r.adjust( 0, 1, 10, -1 ); } else if( _addLineButtons == NoButton ) { tiles |= TileSet::Right; r.adjust( -10, 1, 2, -1 ); } else r.adjust( -10, 1, 0, -1 ); renderScrollBarHole( painter, r, color, Qt::Horizontal, tiles ); } else { TileSet::Tiles tiles( TileSet::Horizontal ); if( _addLineButtons == NoButton ) { tiles |= TileSet::Bottom; r.adjust( 1, -10, -1, 0 ); } else r.adjust( 1, -10, -1, 0 ); renderScrollBarHole( painter, r, color, Qt::Vertical, tiles ); } 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& flags( option->state ); const bool horizontal( flags & 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 r( scrollBarInternalSubControlRect( sliderOption, SC_ScrollBarSubLine ) ); // draw the end of the scrollbar groove if( horizontal ) { if( reverseLayout ) renderScrollBarHole( painter, QRect( r.left()-5, r.top()+1, 5, r.height()-2 ), background, Qt::Horizontal, TileSet::Vertical | TileSet::Right ); else renderScrollBarHole( painter, QRect( r.right()+1, r.top()+1, 5, r.height()-2 ), background, Qt::Horizontal, TileSet::Vertical | TileSet::Left ); r.translate( 1, 0 ); } else { renderScrollBarHole( painter, QRect( r.left()+1, r.bottom()+3, r.width()-2, 5 ), background, Qt::Vertical, TileSet::Top | TileSet::Horizontal ); r.translate( 0, 2 ); } QColor color; QStyleOptionSlider localOption( *sliderOption ); if( _subLineButtons == DoubleButton ) { if( horizontal ) { //Draw the arrows const QSize halfSize( r.width()/2, r.height() ); const QRect leftSubButton( r.topLeft(), halfSize ); const QRect rightSubButton( leftSubButton.topRight() + QPoint( 1, 0 ), halfSize ); localOption.rect = leftSubButton; color = scrollBarArrowColor( &localOption, reverseLayout ? SC_ScrollBarAddLine:SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, leftSubButton, color, background, ArrowLeft ); localOption.rect = rightSubButton; color = scrollBarArrowColor( &localOption, reverseLayout ? SC_ScrollBarSubLine:SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, rightSubButton, color, background, ArrowRight ); } else { const QSize halfSize( r.width(), r.height()/2 ); const QRect topSubButton( r.topLeft(), halfSize ); const QRect botSubButton( topSubButton.bottomLeft() + QPoint( 0, 1 ), halfSize ); localOption.rect = topSubButton; color = scrollBarArrowColor( &localOption, SC_ScrollBarSubLine, widget ); renderScrollBarArrow( painter, topSubButton, color, background, ArrowUp ); localOption.rect = botSubButton; color = scrollBarArrowColor( &localOption, SC_ScrollBarAddLine, widget ); renderScrollBarArrow( painter, botSubButton, color, background, ArrowDown ); } } else if( _subLineButtons == SingleButton ) { localOption.rect = r; color = scrollBarArrowColor( &localOption, SC_ScrollBarSubLine, widget ); if( horizontal ) renderScrollBarArrow( painter, r, color, background, reverseLayout ? ArrowRight : ArrowLeft ); else renderScrollBarArrow( painter, r, color, background, ArrowUp ); } return true; } //___________________________________________________________________________________ bool Style::drawScrollBarSubPageControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); if ( !sliderOption ) return true; QRect r( option->rect ); const QPalette& palette( option->palette ); const QColor color( palette.color( QPalette::Window ) ); const State& flags( option->state ); const bool horizontal( flags & State_Horizontal ); const bool reverseLayout( sliderOption->direction == Qt::RightToLeft ); if( horizontal ) { TileSet::Tiles tiles( TileSet::Vertical ); if( reverseLayout ) { if( _subLineButtons == NoButton ) { tiles |= TileSet::Right; r.adjust( -10, 1, -1, -1 ); } else r.adjust( -10, 1, 0, -1 ); } else if( _subLineButtons == NoButton ) { tiles |= TileSet::Left; r.adjust( 1, 1, 10, -1 ); } else r.adjust( 0, 1, 10, -1 ); renderScrollBarHole( painter, r, color, Qt::Horizontal, tiles ); } else { TileSet::Tiles tiles( TileSet::Horizontal ); if( _subLineButtons == NoButton ) tiles |= TileSet::Top; r.adjust( 1, 2, -1, 12 ); renderScrollBarHole( painter, r, color, Qt::Vertical, tiles ); } return true; } //___________________________________________________________________________________ bool Style::drawShapedFrameControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionFrameV3* frameOpt = qstyleoption_cast( option ); if( !frameOpt ) return false; switch( frameOpt->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; } default: break; } return false; } //___________________________________________________________________________________ bool Style::drawTabBarTabLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const QStyleOptionTab *tabOpt = qstyleoption_cast< const QStyleOptionTab* >( option ); if( !tabOpt ) return true; // add extra offset for selected tas QStyleOptionTabV3 tabOptV3( *tabOpt ); const bool selected( option->state&State_Selected ); // get rect QRect r( option->rect ); // handle selection and orientation /* painter is rotated and translated to deal with various orientations rect is translated to 0,0, and possibly transposed */ switch( tabOptV3.shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { if( selected ) r.translate( 0, -1 ); painter->translate( r.topLeft() ); r.moveTopLeft( QPoint( 0,0 ) ); break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { if( selected ) r.translate( 0, 1 ); painter->translate( r.topLeft() ); r.moveTopLeft( QPoint( 0,0 ) ); break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { if( selected ) r.translate( -1, 0 ); painter->translate( r.bottomLeft() ); painter->rotate( -90 ); r = QRect( QPoint( 0, 0 ), QSize( r.height(), r.width() ) ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { if( selected ) r.translate( 1, 0 ); painter->translate( r.topRight() ); painter->rotate( 90 ); r = QRect( QPoint( 0, 0 ), QSize( r.height(), r.width() ) ); break; } default: break; } // make room for left and right widgets // left widget const bool verticalTabs( isVerticalTab( tabOpt ) ); const bool hasLeftButton( !( option->direction == Qt::RightToLeft ? tabOptV3.rightButtonSize.isEmpty():tabOptV3.leftButtonSize.isEmpty() ) ); const bool hasRightButton( !( option->direction == Qt::RightToLeft ? tabOptV3.leftButtonSize.isEmpty():tabOptV3.rightButtonSize.isEmpty() ) ); if( hasLeftButton ) { r.setLeft( r.left() + 4 + ( verticalTabs ? tabOptV3.leftButtonSize.height() : tabOptV3.leftButtonSize.width() ) ); } // make room for left and right widgets // left widget if( hasRightButton ) { r.setRight( r.right() - 4 - ( verticalTabs ? tabOptV3.rightButtonSize.height() : tabOptV3.rightButtonSize.width() ) ); } // compute textRect and iconRect // now that orientation is properly dealt with, everything is handled as a 'north' orientation QRect textRect; QRect iconRect; if( tabOptV3.icon.isNull() ) { textRect = r.adjusted( 6, 0, -6, 0 ); } else { const QSize& iconSize( tabOptV3.iconSize ); iconRect = centerRect( r, iconSize ); if( !tabOptV3.text.isEmpty() ) { iconRect.moveLeft( r.left() + 8 ); textRect = r; textRect.setLeft( iconRect.right()+3 ); textRect.setRight( r.right() - 6 ); } } if( !verticalTabs ) { textRect = visualRect(option->direction, r, textRect ); iconRect = visualRect(option->direction, r, iconRect ); } // render icon if( !iconRect.isNull() ) { // not sure why this is necessary if( tabOptV3.shape == QTabBar::RoundedNorth || tabOptV3.shape == QTabBar::TriangularNorth ) { iconRect.translate( 0, -1 ); } const QPixmap tabIcon = tabOptV3.icon.pixmap( tabOptV3.iconSize, ( tabOptV3.state & State_Enabled ) ? QIcon::Normal : QIcon::Disabled, ( tabOptV3.state & State_Selected ) ? QIcon::On : QIcon::Off ); painter->drawPixmap( iconRect.x(), iconRect.y(), tabIcon ); } // render text if( !textRect.isNull() ) { const QPalette& palette( option->palette ); const QString& text( tabOptV3.text ); const bool enabled( option->state & State_Enabled ); const int alignment( Qt::AlignCenter|Qt::TextShowMnemonic ); drawItemText( painter, textRect, alignment, palette, enabled, text, QPalette::WindowText ); } return true; } //___________________________________________________________________________________ bool Style::drawTabBarTabShapeControl_Single( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionTab* tabOpt( qstyleoption_cast( option ) ); if( !tabOpt ) return true; const State& flags( option->state ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); const bool enabled( flags & State_Enabled ); const bool selected( flags&State_Selected ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // this is needed to complete the base frame when there are widgets in tabbar const QTabBar* tabBar( qobject_cast( widget ) ); const QRect tabBarRect( tabBar ? insideMargin( tabBar->rect(), -GlowWidth ):QRect() ); // check if tab is being dragged const bool isDragged( selected && painter->device() != tabBar ); // 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 && ( flags & State_MouseOver ) ); // handle base frame painting, for tabbars in which tab is being dragged tabBarData().drawTabBarBaseControl( tabOpt, painter, widget ); if( selected && tabBar && isDragged ) tabBarData().lock( tabBar ); else if( selected && tabBarData().locks( tabBar ) ) tabBarData().release(); // tab position and flags const QStyleOptionTab::TabPosition& position = tabOpt->position; const bool isFirst( position == QStyleOptionTab::OnlyOneTab || position == QStyleOptionTab::Beginning ); const bool isRightOfSelected( tabOpt->selectedPosition == QStyleOptionTab::PreviousIsSelected ); // document mode const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast( option ); bool documentMode = tabOptV3 ? tabOptV3->documentMode : false; const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : NULL; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); const bool verticalTabs( isVerticalTab( tabOpt ) ); const QRect tabWidgetRect( tabWidget ? insideMargin( tabWidget->rect(), -GlowWidth ).translated( -widget->geometry().topLeft() ) : QRect() ); // corner widgets const bool hasLeftCornerWidget( tabOpt->cornerWidgets & QStyleOptionTab::LeftCornerWidget ); const bool hasRightCornerWidget( tabOpt->cornerWidgets & QStyleOptionTab::RightCornerWidget ); // 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 && !isDragged ); bool fillBackground( selected && isDragged ); bool isLeftFrameAligned( false ); bool isRightFrameAligned( false ); if( verticalTabs ) { /* for vertical tabs: 1/ leftFrameAligned corresponds to top side 2/ rightFrameAligned corresponds to the bottom side 3/ their value does not depend on reverseLayout */ isLeftFrameAligned = isFrameAligned; isRightFrameAligned = (!documentMode) && tabWidget && ( r.bottom() >= tabWidgetRect.bottom() - 2 );; fillBackground |= selected && isRightFrameAligned; } else if( reverseLayout ) { isLeftFrameAligned = (!documentMode) && tabWidget && ( r.left() <= tabWidgetRect.left() + 2 ); isRightFrameAligned = isFrameAligned; fillBackground |= selected && isLeftFrameAligned; } else { isLeftFrameAligned = isFrameAligned; isRightFrameAligned = (!documentMode) && tabWidget && ( r.right() >= tabWidgetRect.right() - 2 ); fillBackground |= selected && isRightFrameAligned; } // part of the tab in which the text is drawn QRect tabRect( r ); // connection to the frame SlabRectList slabs; switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { // part of the tab in which the text is drawn // larger tabs when selected if( selected ) tabRect.adjust( 0, -1, 0, 2 ); else tabRect.adjust( 0, 1, 0, 2 ); // reduces the space between tabs tabRect.adjust( -GlowWidth,0,GlowWidth,0 ); // connection to the main frame if( selected ) { // do nothing if dragged if( isDragged ) break; // left side if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - GlowWidth ); frameRect.setRight( tabRect.left() + 7 ); frameRect.setTop( tabRect.bottom() - 13 ); frameRect.setBottom( frameRect.bottom() + 7 - 1 ); slabs << SlabRect( frameRect, TileSet::Left ); } else { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 ); frameRect.setRight( tabRect.left() + 7 + 3 ); frameRect.setTop( r.bottom() - 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } // right side if( isRightFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 ); frameRect.setRight( frameRect.right() + GlowWidth ); frameRect.setTop( tabRect.bottom() - 13 ); frameRect.setBottom( frameRect.bottom() + 7 - 1 ); slabs << SlabRect( frameRect, TileSet::Right ); } else { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 - 3 ); frameRect.setRight( frameRect.right() + 7 ); frameRect.setTop( r.bottom() - 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } // extra base, to extend below inactive tabs and buttons if( tabBar ) { if( r.left() > tabBarRect.left() + 1 ) { QRect frameRect( r ); frameRect.setLeft( tabBarRect.left() - 7 + 1 ); frameRect.setRight( r.left() + 7 - 1 ); frameRect.setTop( r.bottom() - 7 ); if( documentMode || reverseLayout ) slabs << SlabRect( frameRect, TileSet::Top ); else slabs << SlabRect( frameRect, TileSet::TopLeft ); } if( r.right() < tabBarRect.right() - 1 ) { QRect frameRect( r ); frameRect.setLeft( r.right() - 7 + 1 ); frameRect.setRight( tabBarRect.right() + 7 - 1 ); frameRect.setTop( r.bottom() - 7 ); if( documentMode || !reverseLayout ) slabs << SlabRect( frameRect, TileSet::Top ); else slabs << SlabRect( frameRect, TileSet::TopRight ); } } } else { if( isRightFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 ); frameRect.setRight( frameRect.right() + GlowWidth ); frameRect.setTop( tabRect.bottom() - 13 ); frameRect.setBottom( frameRect.bottom() + 7 - 2 ); slabs << SlabRect( frameRect, TileSet::Right ); } if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - GlowWidth ); frameRect.setRight( tabRect.left() + 7 ); frameRect.setTop( tabRect.bottom() - 13 ); frameRect.setBottom( frameRect.bottom() + 7 - 2 ); slabs << SlabRect( frameRect, TileSet::Left ); } } break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { // larger tabs when selected if( selected ) tabRect.adjust( 0, -2, 0, 1 ); else tabRect.adjust( 0, -2, 0, -1 ); // reduces the space between tabs tabRect.adjust( -GlowWidth,0,GlowWidth,0 ); // connection to the main frame if( selected ) { // do nothing if dragged if( isDragged ) break; // left side if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - GlowWidth ); frameRect.setRight( tabRect.left() + 7 ); frameRect.setTop( frameRect.top() - 7 + 1 ); frameRect.setBottom( tabRect.top() + 13 ); slabs << SlabRect( frameRect, TileSet::Left ); } else { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 ); frameRect.setRight( tabRect.left() + 7 + 3 ); frameRect.setBottom( r.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Bottom ); } // right side if( isRightFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 ); frameRect.setRight( frameRect.right() + GlowWidth ); frameRect.setTop( frameRect.top() - 7 + 1 ); frameRect.setBottom( tabRect.top() + 13 ); slabs << SlabRect( frameRect, TileSet::Right ); } else { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 - 3 ); frameRect.setRight( frameRect.right() + 7 ); frameRect.setBottom( r.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Bottom ); } // extra base, to extend below tabbar buttons if( tabBar ) { if( r.left() > tabBarRect.left() + 1 ) { QRect frameRect( r ); frameRect.setLeft( tabBarRect.left() - 7 + 1 ); frameRect.setRight( r.left() + 7 - 1 ); frameRect.setBottom( r.top() + 7 ); if( documentMode || reverseLayout ) slabs << SlabRect( frameRect, TileSet::Bottom ); else slabs << SlabRect( frameRect, TileSet::BottomLeft ); } if( r.right() < tabBarRect.right() - 1 ) { QRect frameRect( r ); frameRect.setLeft( r.right() - 7 + 1 ); frameRect.setRight( tabBarRect.right() + 7 - 1 ); frameRect.setBottom( r.top() + 7 ); if( documentMode || !reverseLayout ) slabs << SlabRect( frameRect, TileSet::Bottom ); else slabs << SlabRect( frameRect, TileSet::BottomRight ); } } } else { if( isRightFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 ); frameRect.setRight( frameRect.right() + GlowWidth ); frameRect.setTop( frameRect.top() - 7 + 2 ); frameRect.setBottom( tabRect.top() + 13 ); slabs << SlabRect( frameRect, TileSet::Right ); } if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - GlowWidth ); frameRect.setRight( tabRect.left() + 7 ); frameRect.setTop( frameRect.top() - 7 + 2 ); frameRect.setBottom( tabRect.top() + 13 ); slabs << SlabRect( frameRect, TileSet::Left ); } } break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { // larger tabs when selected if( selected ) tabRect.adjust( -1, 0, 2, 0 ); else tabRect.adjust( 1, 0, 2, 0 ); // reduces the space between tabs tabRect.adjust( 0, -GlowWidth,0,GlowWidth ); // connection to the main frame if( selected ) { // do nothing if dragged if( isDragged ) break; // top side if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 13 ); frameRect.setRight( frameRect.right() + 7 - 1 ); frameRect.setTop( frameRect.top() - GlowWidth ); frameRect.setBottom( tabRect.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } else { QRect frameRect( r ); frameRect.setLeft( r.right() - 7 ); frameRect.setTop( frameRect.top() - 7 ); frameRect.setBottom( tabRect.top() + 7 + 3 ); slabs << SlabRect( frameRect, TileSet::Left ); } // bottom side if( isRightFrameAligned ) { // FIXME: QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 13 ); frameRect.setRight( frameRect.right() + 7 - 1 ); frameRect.setTop( tabRect.bottom() - 7 ); frameRect.setBottom( frameRect.bottom() + GlowWidth ); slabs << SlabRect( frameRect, TileSet::Bottom ); } else { QRect frameRect( r ); frameRect.setLeft( r.right() - 7 ); frameRect.setTop( tabRect.bottom() - 7 - 3 ); frameRect.setBottom( frameRect.bottom() + 7 ); slabs << SlabRect( frameRect, TileSet::Left ); } // extra base, to extend below tabbar buttons if( tabBar ) { if( r.top() > tabBarRect.top() + 1 ) { QRect frameRect( r ); frameRect.setTop( tabBarRect.top() - 7 + 1 ); frameRect.setBottom( r.top() + 7 - 1 ); frameRect.setLeft( r.right() - 7 ); if( documentMode ) slabs << SlabRect( frameRect, TileSet::Left ); else slabs << SlabRect( frameRect, TileSet::TopLeft ); } if( r.bottom() < tabBarRect.bottom() - 1 ) { QRect frameRect( r ); frameRect.setTop( r.bottom() - 7 + 1 ); if( hasRightCornerWidget && documentMode ) frameRect.setBottom( tabBarRect.bottom() + 7 - 1 ); else frameRect.setBottom( tabBarRect.bottom() + 7 ); frameRect.setLeft( r.right() - 7 ); slabs << SlabRect( frameRect, TileSet::Left ); } } } else { if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 13 ); frameRect.setRight( frameRect.right() + 7 - 2 ); frameRect.setTop( frameRect.top() - GlowWidth ); frameRect.setBottom( tabRect.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } if( isRightFrameAligned ) { // FIXME: QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 13 ); frameRect.setRight( frameRect.right() + 7 - 2 ); frameRect.setTop( tabRect.bottom() - 7 ); frameRect.setBottom( frameRect.bottom() + GlowWidth ); slabs << SlabRect( frameRect, TileSet::Bottom ); } } break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { // larger tabs when selected if( selected ) tabRect.adjust( -2, 0, 1, 0 ); else tabRect.adjust( -2, 0, -1, 0 ); // reduces the space between tabs tabRect.adjust( 0, -GlowWidth,0,GlowWidth ); // connection to the main frame if( selected ) { // do nothing if dragged if( isDragged ) break; // top side if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 + 1 ); frameRect.setRight( tabRect.left() + 13 ); frameRect.setTop( frameRect.top() - GlowWidth ); frameRect.setBottom( tabRect.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } else { QRect frameRect( r ); frameRect.setRight( r.left() + 7 ); frameRect.setTop( frameRect.top() - 7 ); frameRect.setBottom( tabRect.top() + 7 + 3 ); slabs << SlabRect( frameRect, TileSet::Right ); } // bottom side if( isRightFrameAligned ) { // FIXME: QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 + 1 ); frameRect.setRight( tabRect.left() + 13 ); frameRect.setTop( tabRect.bottom() - 7 ); frameRect.setBottom( frameRect.bottom() + GlowWidth ); slabs << SlabRect( frameRect, TileSet::Bottom ); } else { QRect frameRect( r ); frameRect.setRight( r.left() + 7 ); frameRect.setTop( tabRect.bottom() - 7 - 3 ); frameRect.setBottom( frameRect.bottom() + 7 ); slabs << SlabRect( frameRect, TileSet::Right ); } // extra base, to extend below tabbar buttons if( tabBar ) { if( r.top() > tabBarRect.top() + 1 ) { QRect frameRect( r ); frameRect.setTop( tabBarRect.top() - 7 + 1 ); frameRect.setBottom( r.top() + 7 - 1 ); frameRect.setRight( r.left() + 7 ); if( documentMode ) slabs << SlabRect( frameRect, TileSet::Right ); else slabs << SlabRect( frameRect, TileSet::TopRight ); } if( r.bottom() < tabBarRect.bottom() - 1 ) { QRect frameRect( r ); frameRect.setTop( r.bottom() - 7 + 1 ); if( hasRightCornerWidget && documentMode ) frameRect.setBottom( tabBarRect.bottom() + 7 - 1 ); else frameRect.setBottom( tabBarRect.bottom() + 7 ); frameRect.setRight( r.left() + 7 ); slabs << SlabRect( frameRect, TileSet::Right ); } } } else { if( isLeftFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 + 2 ); frameRect.setRight( tabRect.left() + 13 ); frameRect.setTop( frameRect.top() - GlowWidth ); frameRect.setBottom( tabRect.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } if( isRightFrameAligned ) { // FIXME: QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 + 2 ); frameRect.setRight( tabRect.left() + 13 ); frameRect.setTop( tabRect.bottom() - 7 ); frameRect.setBottom( frameRect.bottom() + GlowWidth ); slabs << SlabRect( frameRect, TileSet::Bottom ); } } break; } default: break; } // slab options StyleOptions slabOptions( NoFill ); if( StyleConfigData::tabSubtleShadow() ) slabOptions |= SubtleShadow; if( ( !selected ) && mouseOver ) slabOptions |= Hover; // 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 foreach( SlabRect slab, slabs ) // krazy:exclude=foreach { adjustSlabRect( slab, tabWidgetRect, documentMode, verticalTabs ); if( selected ) renderSlab( painter, slab, color, slabOptions ); else { renderSlab( painter, slab, color, slabOptions); } } // adjust clip rect and render tabs if( tabBar ) { painter->save(); painter->setClipRegion( tabBarClipRegion( tabBar ) ); } // draw tab TileSet::Tiles tiles( tilesByShape( tabOpt->shape ) ); if( selected ) { // render window background first, if needed if( fillBackground ) fillTabBackground( painter, tabRect, color, tabOpt->shape, widget ); // render window background in case of dragged tabwidget renderSlab( painter, tabRect, color, slabOptions, tiles ); } else renderSlab( painter, tabRect, color, slabOptions, tiles ); // fill tab fillTab( painter, tabRect, color, tabOpt->shape, selected ); // restore clip region if( tabBar ) painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawTabBarTabShapeControl_Plain( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionTab* tabOpt( qstyleoption_cast( option ) ); if( !tabOpt ) return true; const State& flags( option->state ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); const bool enabled( flags & State_Enabled ); const bool selected( flags&State_Selected ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // tab position and flags const QStyleOptionTab::TabPosition& position = tabOpt->position; bool isFirst( position == QStyleOptionTab::OnlyOneTab || position == QStyleOptionTab::Beginning ); bool isLast( position == QStyleOptionTab::OnlyOneTab || position == QStyleOptionTab::End ); bool isLeftOfSelected( tabOpt->selectedPosition == QStyleOptionTab::NextIsSelected ); bool isRightOfSelected( tabOpt->selectedPosition == QStyleOptionTab::PreviousIsSelected ); // document mode const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast( option ); bool documentMode = tabOptV3 ? tabOptV3->documentMode : false; const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : NULL; 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 ? insideMargin( tabBar->rect(), -GlowWidth ):QRect() ); // check if tab is being dragged const bool isDragged( selected && painter->device() != tabBar ); // 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 && ( flags & State_MouseOver ) ); // handle base frame painting, for tabbars in which tab is being dragged tabBarData().drawTabBarBaseControl( tabOpt, painter, widget ); if( selected && tabBar && isDragged ) tabBarData().lock( tabBar ); else if( selected && tabBarData().locks( tabBar ) ) tabBarData().release(); // corner widgets const bool hasLeftCornerWidget( tabOpt->cornerWidgets & QStyleOptionTab::LeftCornerWidget ); const bool hasRightCornerWidget( tabOpt->cornerWidgets & QStyleOptionTab::RightCornerWidget ); // 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 && !isDragged ); isFirst &= !isRightOfSelected; isLast &= !isLeftOfSelected; // swap flags based on reverse layout, so that they become layout independent const bool verticalTabs( isVerticalTab( tabOpt ) ); if( reverseLayout && !verticalTabs ) { qSwap( isFirst, isLast ); qSwap( isLeftOfSelected, isRightOfSelected ); } const qreal radius = 5; // part of the tab in which the text is drawn QRect tabRect( r ); QPainterPath path; // connection to the frame SlabRectList slabs; // highlighted slab ( if any ) SlabRect highlightSlab; switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { // part of the tab in which the text is drawn // larger tabs when selected if( selected ) tabRect.adjust( 0, -1, 0, 2 ); else tabRect.adjust( 0, 3, 1, -7 + 1 ); // connection to the main frame if( selected ) { // reduces the space between tabs tabRect.adjust( -GlowWidth,0,GlowWidth,0 ); // do nothing if dragged if( isDragged ) break; // left side if( isFrameAligned && !reverseLayout ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - GlowWidth ); frameRect.setRight( tabRect.left() + 7 ); frameRect.setTop( tabRect.bottom() - 13 ); frameRect.setBottom( frameRect.bottom() + 7 - 1 ); slabs << SlabRect( frameRect, TileSet::Left ); } else { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 ); frameRect.setRight( tabRect.left() + 7 + 3 ); frameRect.setTop( r.bottom() - 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } // right side if( isFrameAligned && reverseLayout ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 ); frameRect.setRight( frameRect.right() + GlowWidth ); frameRect.setTop( tabRect.bottom() - 13 ); frameRect.setBottom( frameRect.bottom() + 7 - 1 ); slabs << SlabRect( frameRect, TileSet::Right ); } else { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 - 3 ); frameRect.setRight( frameRect.right() + 7 ); frameRect.setTop( r.bottom() - 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } // extra base, to extend below inactive tabs and buttons if( tabBar ) { if( r.left() > tabBarRect.left() + 1 ) { QRect frameRect( r ); frameRect.setLeft( tabBarRect.left() - 7 + 1 ); frameRect.setRight( r.left() + 7 - 1 ); frameRect.setTop( r.bottom() - 7 ); if( documentMode || reverseLayout ) slabs << SlabRect( frameRect, TileSet::Top ); else slabs << SlabRect( frameRect, TileSet::TopLeft ); } if( r.right() < tabBarRect.right() - 1 ) { QRect frameRect( r ); frameRect.setLeft( r.right() - 7 + 1 ); frameRect.setRight( tabBarRect.right() + 7 - 1 ); frameRect.setTop( r.bottom() - 7 ); if( documentMode || !reverseLayout ) slabs << SlabRect( frameRect, TileSet::Top ); else slabs << SlabRect( frameRect, TileSet::TopRight ); } } } else { // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.setRight( tabRect.right() + 2 ); else if( isRightOfSelected ) tabRect.setLeft( tabRect.left() - 2 ); if( isFirst ) { tabRect.adjust( GlowWidth, 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, -GlowWidth-1, 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()-1, tabRect.width(), 7 ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( -2, 0, 7 + 1, 0 ), TileSet::TopLeft ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( -7, 0, 2, 0 ), TileSet::TopRight ); else highlightSlab = SlabRect( highlightRect.adjusted( -7, 0, 7, 0 ), TileSet::Top ); } break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { // larger tabs when selected if( selected ) tabRect.adjust( 0, -2, 0, 1 ); else tabRect.adjust( 0, 7 - 1, 1, -3 ); // connection to the main frame if( selected ) { // reduces the space between tabs tabRect.adjust( -GlowWidth,0,GlowWidth,0 ); // do nothing if dragged if( isDragged ) break; // left side if( isFrameAligned && !reverseLayout ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - GlowWidth ); frameRect.setRight( tabRect.left() + 7 ); frameRect.setTop( frameRect.top() - 7 + 1 ); frameRect.setBottom( tabRect.top() + 13 ); slabs << SlabRect( frameRect, TileSet::Left ); } else { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 ); frameRect.setRight( tabRect.left() + 7 + 3 ); frameRect.setBottom( r.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Bottom ); } // right side if( isFrameAligned && reverseLayout ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 ); frameRect.setRight( frameRect.right() + GlowWidth ); frameRect.setTop( frameRect.top() - 7 + 1 ); frameRect.setBottom( tabRect.top() + 13 ); slabs << SlabRect( frameRect, TileSet::Right ); } else { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 7 - 3 ); frameRect.setRight( frameRect.right() + 7 ); frameRect.setBottom( r.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Bottom ); } // extra base, to extend below tabbar buttons if( tabBar ) { if( r.left() > tabBarRect.left() + 1 ) { QRect frameRect( r ); frameRect.setLeft( tabBarRect.left() - 7 + 1 ); frameRect.setRight( r.left() + 7 - 1 ); frameRect.setBottom( r.top() + 7 ); if( documentMode || reverseLayout ) slabs << SlabRect( frameRect, TileSet::Bottom ); else slabs << SlabRect( frameRect, TileSet::BottomLeft ); } if( r.right() < tabBarRect.right() - 1 ) { QRect frameRect( r ); frameRect.setLeft( r.right() - 7 + 1 ); frameRect.setRight( tabBarRect.right() + 7 - 1 ); frameRect.setBottom( r.top() + 7 ); if( documentMode || !reverseLayout ) slabs << SlabRect( frameRect, TileSet::Bottom ); else slabs << SlabRect( frameRect, TileSet::BottomRight ); } } } else { // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.setRight( tabRect.right() + 2 ); else if( isRightOfSelected ) tabRect.setLeft( tabRect.left() - 2 ); if( isFirst ) { tabRect.adjust( GlowWidth, 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, -GlowWidth-1, 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()-5, tabRect.width(), 7 ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( -2, 0, 7 + 1, 0 ), TileSet::BottomLeft ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( -7, 0, 2, 0 ), TileSet::BottomRight ); else highlightSlab = SlabRect( highlightRect.adjusted( -7, 0, 7, 0 ), TileSet::Bottom ); } break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { // larger tabs when selected if( selected ) tabRect.adjust( -1, 0, 2, 0 ); else tabRect.adjust( 3, 0, -7 + 1, 1 ); // connection to the main frame if( selected ) { // reduces the space between tabs tabRect.adjust( 0, -GlowWidth,0,GlowWidth ); // do nothing if dragged if( isDragged ) break; // top side if( isFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( tabRect.right() - 13 ); frameRect.setRight( frameRect.right() + 7 - 1 ); frameRect.setTop( frameRect.top() - GlowWidth ); frameRect.setBottom( tabRect.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } else { QRect frameRect( r ); frameRect.setLeft( r.right() - 7 ); frameRect.setTop( frameRect.top() - 7 ); frameRect.setBottom( tabRect.top() + 7 + 3 ); slabs << SlabRect( frameRect, TileSet::Left ); } // bottom side QRect frameRect( r ); frameRect.setLeft( r.right() - 7 ); frameRect.setTop( tabRect.bottom() - 7 - 3 ); frameRect.setBottom( frameRect.bottom() + 7 ); slabs << SlabRect( frameRect, TileSet::Left ); // extra base, to extend below tabbar buttons if( tabBar ) { if( r.top() > tabBarRect.top() + 1 ) { QRect frameRect( r ); frameRect.setTop( tabBarRect.top() - 7 + 1 ); frameRect.setBottom( r.top() + 7 - 1 ); frameRect.setLeft( r.right() - 7 ); if( documentMode ) slabs << SlabRect( frameRect, TileSet::Left ); else slabs << SlabRect( frameRect, TileSet::TopLeft ); } if( r.bottom() < tabBarRect.bottom() - 1 ) { QRect frameRect( r ); frameRect.setTop( r.bottom() - 7 + 1 ); if( hasRightCornerWidget && documentMode ) frameRect.setBottom( tabBarRect.bottom() + 7 - 1 ); else frameRect.setBottom( tabBarRect.bottom() + 7 ); frameRect.setLeft( r.right() - 7 ); slabs << SlabRect( frameRect, TileSet::Left ); } } } else { // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.setBottom( tabRect.bottom() + 2 ); else if( isRightOfSelected ) tabRect.setTop( tabRect.top() - 2 ); if( isFirst ) { tabRect.adjust( 0, GlowWidth, 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, -GlowWidth ); 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()-1, tabRect.top(), 7, tabRect.height() ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( 0, -2, 0, 7 + 1 ), TileSet::TopLeft ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( 0, -7, 0, 2 ), TileSet::BottomLeft ); else highlightSlab = SlabRect( highlightRect.adjusted( 0, -7 + 1, 0, 7 + 1 ), TileSet::Left ); } break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { // larger tabs when selected if( selected ) tabRect.adjust( -2, 0, 1, 0 ); else tabRect.adjust( 7 - 1, 0, -3, 1 ); // connection to the main frame if( selected ) { // reduces the space between tabs tabRect.adjust( 0, -GlowWidth,0,GlowWidth ); // do nothing if dragged if( isDragged ) break; // top side if( isFrameAligned ) { QRect frameRect( r ); frameRect.setLeft( frameRect.left() - 7 + 1 ); frameRect.setRight( tabRect.left() + 13 ); frameRect.setTop( frameRect.top() - GlowWidth ); frameRect.setBottom( tabRect.top() + 7 ); slabs << SlabRect( frameRect, TileSet::Top ); } else { QRect frameRect( r ); frameRect.setRight( r.left() + 7 ); frameRect.setTop( frameRect.top() - 7 ); frameRect.setBottom( tabRect.top() + 7 + 3 ); slabs << SlabRect( frameRect, TileSet::Right ); } // bottom side QRect frameRect( r ); frameRect.setRight( r.left() + 7 ); frameRect.setTop( tabRect.bottom() - 7 - 3 ); frameRect.setBottom( frameRect.bottom() + 7 ); slabs << SlabRect( frameRect, TileSet::Right ); // extra base, to extend below tabbar buttons if( tabBar ) { if( r.top() > tabBarRect.top() + 1 ) { QRect frameRect( r ); frameRect.setTop( tabBarRect.top() - 7 + 1 ); frameRect.setBottom( r.top() + 7 - 1 ); frameRect.setRight( r.left() + 7 ); if( documentMode ) slabs << SlabRect( frameRect, TileSet::Right ); else slabs << SlabRect( frameRect, TileSet::TopRight ); } if( r.bottom() < tabBarRect.bottom() - 1 ) { QRect frameRect( r ); frameRect.setTop( r.bottom() - 7 + 1 ); if( hasRightCornerWidget && documentMode ) frameRect.setBottom( tabBarRect.bottom() + 7 - 1 ); else frameRect.setBottom( tabBarRect.bottom() + 7 ); frameRect.setRight( r.left() + 7 ); slabs << SlabRect( frameRect, TileSet::Right ); } } } else { // adjust sides when slab is adjacent to selected slab if( isLeftOfSelected ) tabRect.setBottom( tabRect.bottom() + 2 ); else if( isRightOfSelected ) tabRect.setTop( tabRect.top() - 2 ); if( isFirst ) { tabRect.adjust( 0, GlowWidth, 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, -GlowWidth ); 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()-5, tabRect.top(), 7, tabRect.height() ); if( isFrameAligned && isFirst ) highlightSlab = SlabRect( highlightRect.adjusted( 0, -2, 0, 7 + 1 ), TileSet::TopRight ); else if( isFrameAligned && isLast ) highlightSlab = SlabRect( highlightRect.adjusted( 0, -7, 0, 2 ), TileSet::BottomRight ); else highlightSlab = SlabRect( highlightRect.adjusted( 0, -7 + 1, 0, 7 + 1 ), TileSet::Right ); } break; } default: break; } 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 ? insideMargin( tabWidget->rect(), -GlowWidth ).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( selected ) { // render window background in case of dragged tabwidget if( isDragged ) fillTabBackground( painter, tabRect, color, tabOpt->shape, widget ); // slab options StyleOptions selectedTabOpts( NoFill ); if( StyleConfigData::tabSubtleShadow() ) selectedTabOpts |= SubtleShadow; TileSet::Tiles tiles( tilesByShape( tabOpt->shape ) ); renderSlab( painter, tabRect, color, selectedTabOpts, tiles ); fillTab( painter, tabRect, color, tabOpt->shape, selected ); } else { const QColor backgroundColor = helper().backgroundColor( color, widget, r.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(); // hovered highlight if( mouseOver && highlightSlab._r.isValid() ) { const StyleOptions hoverTabOpts( NoFill | Hover ); adjustSlabRect( highlightSlab, tabWidgetRect, documentMode, verticalTabs ); // pass an invalid color to have only the glow painted renderSlab( painter, highlightSlab, QColor(), hoverTabOpts ); } return true; } //___________________________________________________________________________________ void Style::TabBarData::drawTabBarBaseControl( const QStyleOptionTab* tabOpt, 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( tabOpt->direction == Qt::RightToLeft ); // get documentMode flag const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast( tabOpt ); bool documentMode = tabOptV3 ? tabOptV3->documentMode : false; const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : NULL; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); const QRect tabBarRect( _style.data()->insideMargin( tabBar->rect(), -GlowWidth ) ); // define slab Style::SlabRect slab; // switch on tab shape switch( tabOpt->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: { TileSet::Tiles tiles( TileSet::Top ); QRect frameRect; frameRect.setLeft( tabBarRect.left() - 7 + 1 ); frameRect.setRight( tabBarRect.right() + 7 - 1 ); frameRect.setTop( tabBarRect.bottom() - 8 ); frameRect.setHeight( 4 ); if( !( documentMode || reverseLayout ) ) tiles |= TileSet::Left; if( !documentMode && reverseLayout ) tiles |= TileSet::Right; slab = SlabRect( frameRect, tiles ); break; } case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: { TileSet::Tiles tiles( TileSet::Bottom ); QRect frameRect; frameRect.setLeft( tabBarRect.left() - 7 + 1 ); frameRect.setRight( tabBarRect.right() + 7 - 1 ); frameRect.setBottom( tabBarRect.top() + 8 ); frameRect.setTop( frameRect.bottom() - 4 ); if( !( documentMode || reverseLayout ) ) tiles |= TileSet::Left; if( !documentMode && reverseLayout ) tiles |= TileSet::Right; slab = SlabRect( frameRect, tiles ); break; } case QTabBar::RoundedWest: case QTabBar::TriangularWest: { TileSet::Tiles tiles( TileSet::Left ); QRect frameRect; frameRect.setTop( tabBarRect.top() - 7 + 1 ); frameRect.setBottom( tabBarRect.bottom() + 7 - 1 ); frameRect.setLeft( tabBarRect.right() - 8 ); frameRect.setWidth( 4 ); if( !( documentMode || reverseLayout ) ) tiles |= TileSet::Top; if( !documentMode && reverseLayout ) tiles |= TileSet::Bottom; slab = SlabRect( frameRect, tiles ); break; } case QTabBar::RoundedEast: case QTabBar::TriangularEast: { TileSet::Tiles tiles( TileSet::Right ); QRect frameRect; frameRect.setTop( tabBarRect.top() - 7 + 1 ); frameRect.setBottom( tabBarRect.bottom() + 7 - 1 ); frameRect.setRight( tabBarRect.left() + 8 ); frameRect.setLeft( frameRect.right() - 4 ); if( !( documentMode || reverseLayout ) ) tiles |= TileSet::Top; if( !documentMode && reverseLayout ) tiles |= TileSet::Bottom; slab = SlabRect( frameRect, tiles ); break; } default: break; } const bool verticalTabs( _style.data()->isVerticalTab( tabOpt ) ); const QRect tabWidgetRect( tabWidget ? _style.data()->insideMargin( tabWidget->rect(), -GlowWidth ).translated( -widget->geometry().topLeft() ) : QRect() ); const QPalette& palette( tabOpt->palette ); const QColor color( palette.color( QPalette::Window ) ); _style.data()->adjustSlabRect( slab, tabWidgetRect, documentMode, verticalTabs ); _style.data()->renderSlab( painter, slab, color, NoFill ); setDirty( false ); return; } //___________________________________________________________________________________ bool Style::drawToolBoxTabLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionToolBox* toolBoxOption( qstyleoption_cast( option ) ); const bool enabled( toolBoxOption->state & State_Enabled ); const bool selected( toolBoxOption->state & State_Selected ); QPixmap pm( toolBoxOption->icon.pixmap( pixelMetric( QStyle::PM_SmallIconSize, toolBoxOption, widget ), enabled ? QIcon::Normal : QIcon::Disabled ) ); const QRect cr( toolBoxTabContentsRect( toolBoxOption, widget ) ); QRect tr; QRect ir; int ih( 0 ); if( pm.isNull() ) tr = cr.adjusted( -1, 0, -8, 0 ); else { int iw = pm.width() + 4; ih = pm.height(); ir = QRect( cr.left() - 1, cr.top(), iw + 2, ih ); tr = QRect( ir.right(), cr.top(), cr.width() - ir.right() - 4, cr.height() ); } if( selected ) { QFont f( painter->font() ); f.setBold( true ); painter->setFont( f ); } QString txt( toolBoxOption->fontMetrics.elidedText( toolBoxOption->text, Qt::ElideRight, tr.width() ) ); if( ih ) painter->drawPixmap( ir.left(), ( toolBoxOption->rect.height() - ih ) / 2, pm ); int alignment( Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic ); drawItemText( painter, tr, alignment, toolBoxOption->palette, enabled, txt, QPalette::WindowText ); return true; } //___________________________________________________________________________________ bool Style::drawToolBoxTabShapeControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const QRect& r( option->rect ); const QPalette& palette( option->palette ); const State& flags( option->state ); const bool enabled( flags&State_Enabled ); const bool selected( flags&State_Selected ); const bool mouseOver( enabled && !selected && ( flags&State_MouseOver ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // cast to v2 and disable paint is tab is first const QStyleOptionToolBoxV2 *v2 = qstyleoption_cast( option ); if( v2 && v2->position == QStyleOptionToolBoxV2::Beginning && selected ) return true; // 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.push_back( helper().calcLightColor( color ) ); if( mouseOver ) { QColor highlight = helper().viewHoverBrush().brush( palette ).color(); colors.push_back( highlight ); colors.push_back( helper().alphaColor( highlight, 0.2 ) ); } else colors.push_back( dark ); // create path painter->save(); QPainterPath path; const int y( r.height()*15/100 ); if( reverseLayout ) { path.moveTo( r.left()+52, r.top() ); path.cubicTo( QPointF( r.left()+50-8, r.top() ), QPointF( r.left()+50-10, r.top()+y ), QPointF( r.left()+50-10, r.top()+y ) ); path.lineTo( r.left()+18+9, r.bottom()-y ); path.cubicTo( QPointF( r.left()+18+9, r.bottom()-y ), QPointF( r.left()+19+6, r.bottom()-1-0.3 ), QPointF( r.left()+19, r.bottom()-1-0.3 ) ); painter->setClipRect( QRect( r.left()+21, r.top(), 28, r.height() ) ); } else { path.moveTo( r.right()-52, r.top() ); path.cubicTo( QPointF( r.right()-50+8, r.top() ), QPointF( r.right()-50+10, r.top()+y ), QPointF( r.right()-50+10, r.top()+y ) ); path.lineTo( r.right()-18-9, r.bottom()-y ); path.cubicTo( QPointF( r.right()-18-9, r.bottom()-y ), QPointF( r.right()-19-6, r.bottom()-1-0.3 ), QPointF( r.right()-19, r.bottom()-1-0.3 ) ); painter->setClipRect( QRect( r.right()-48, r.top(), 32, r.height() ) ); } // paint painter->setRenderHint( QPainter::Antialiasing, true ); painter->translate( 0,2 ); foreach( const QColor& color, colors ) { painter->setPen( color ); painter->drawPath( path ); painter->translate( 0,-1 ); } painter->restore(); painter->save(); painter->setRenderHint( QPainter::Antialiasing, false ); painter->translate( 0,2 ); foreach( const QColor& color, colors ) { painter->setPen( color ); if( reverseLayout ) { painter->drawLine( r.left()+50-1, r.top(), r.right(), r.top() ); painter->drawLine( r.left()+20, r.bottom()-2, r.left(), r.bottom()-2 ); } else { painter->drawLine( r.left(), r.top(), r.right()-50+1, r.top() ); painter->drawLine( r.right()-20, r.bottom()-2, r.right(), r.bottom()-2 ); } painter->translate( 0,-1 ); } painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawToolButtonLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // need to customize palettes to deal with autoraised buttons const State& flags( option->state ); // normal processing if not autoRaised if( flags & State_AutoRaise ) { const QStyleOptionToolButton* toolButtonOpt( qstyleoption_cast( option ) ); if( !toolButtonOpt ) return true; QStyleOptionToolButton localOption( *toolButtonOpt ); localOption.palette.setColor( QPalette::ButtonText, option->palette.color( QPalette::WindowText ) ); QCommonStyle::drawControl( CE_ToolButtonLabel, &localOption, painter, widget ); } else { QCommonStyle::drawControl( CE_ToolButtonLabel, option, painter, widget ); } return true; } //______________________________________________________________ bool Style::drawComboBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const QStyleOptionComboBox* cb( qstyleoption_cast( option ) ); if( !cb ) return true; const State& flags( option->state ); const QRect& r( option->rect ); const QPalette& palette( option->palette ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool hasFocus( flags & State_HasFocus ); const bool& editable( cb->editable ); const bool& hasFrame( cb->frame ); // frame if( cb->subControls & SC_ComboBoxFrame ) { // style options StyleOptions opts = 0; if( mouseOver ) opts |= Hover; if( hasFocus ) opts |= Focus; if( ( flags & ( State_Sunken|State_On ) ) && !editable ) opts |= Sunken; const QColor inputColor( palette.color( QPalette::Base ) ); if( editable ) { // editable combobox. Make it look like a LineEdit const QRect fr( r.adjusted( 1,1,-1,-1 ) ); // input area painter->save(); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); painter->setBrush( inputColor ); if( !hasFrame ) { // adjust rect to match frameLess editors painter->fillRect( r, inputColor ); painter->restore(); } else { helper().fillHole( *painter, r.adjusted( 0, -1, 0, 0 ) ); painter->restore(); HoleOptions options( 0 ); if( hasFocus && enabled ) options |= HoleFocus; if( mouseOver && enabled ) options |= HoleHover; const QColor color( palette.color( QPalette::Window ) ); helper().renderHole( painter, color, fr, options ); } } else { // non editable combobox. Make it look like a PushButton // blend button color to the background const QColor buttonColor( helper().backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) ); const QRect slabRect( r.adjusted( -1, 0, 1, 0 ) ); if( !hasFrame ) { QRect slitRect( r ); if( !( opts & Sunken ) ) { // hover rect if( mouseOver ) { helper().slitFocused( helper().viewFocusBrush().brush( QPalette::Active ).color() )->render( slitRect, painter ); } } else { slitRect.adjust( 0, 0, 0, -1 ); HoleOptions options( HoleContrast ); if( mouseOver && enabled ) options |= HoleHover; helper().renderHole( painter, palette.color( QPalette::Window ), slitRect, options ); } } else { renderButtonSlab( painter, slabRect, buttonColor, opts ); } } } if( cb->subControls & SC_ComboBoxArrow ) { const QComboBox* comboBox = qobject_cast( widget ); const bool empty( comboBox && !comboBox->count() ); QColor color; QColor background; bool drawContrast( true ); if( cb->editable ) { if( enabled && empty ) color = palette.color( QPalette::Disabled, QPalette::Text ); else { // check animation state const bool subControlHover( enabled && mouseOver && cb->activeSubControls&SC_ComboBoxArrow ); if( subControlHover ) { color = helper().viewHoverBrush().brush( palette ).color(); } else { color = palette.color( QPalette::Text ); } } background = palette.color( QPalette::Background ); if( enabled ) drawContrast = false; } else { // foreground color const QPalette::ColorRole role( hasFrame ? QPalette::ButtonText : QPalette::WindowText ); if( enabled && empty ) color = palette.color( QPalette::Disabled, role ); else color = palette.color( role ); // background color background = palette.color( hasFrame ? QPalette::Button : QPalette::Window ); } // draw the arrow QRect arrowRect = comboBoxSubControlRect( option, SC_ComboBoxArrow, widget ); if( cb->currentIcon.isNull() && !cb->editable ) arrowRect.translate( 0, -1 ); const QPolygonF a( genericArrow( ArrowDown, ArrowNormal ) ); const qreal penThickness = 1.6; painter->save(); painter->translate( arrowRect.center() ); painter->setRenderHint( QPainter::Antialiasing ); if( drawContrast ) { const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( helper().calcLightColor( palette.color( QPalette::Window ) ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->translate( 0,-offset ); } painter->setPen( QPen( helper().decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->restore(); } return true; } //______________________________________________________________ bool Style::drawDialComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const State& flags( option->state ); const bool enabled = flags & State_Enabled; const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool hasFocus( enabled && ( flags & State_HasFocus ) ); const bool sunken( flags & ( State_On|State_Sunken ) ); StyleOptions opts = 0; if( sunken ) opts |= Sunken; if( hasFocus ) opts |= Focus; if( mouseOver ) opts |= Hover; 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, opts ); return true; } //______________________________________________________________ bool Style::drawGroupBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionGroupBox *groupBox = qstyleoption_cast( option ); if( groupBox && groupBox->features & QStyleOptionFrameV2::Flat ) { // for flat groupboxes, the groupBox title is rendered bold /* TODO: talk to pinheiro. This is not an optimal design I would rather 1/ keep the font unchanged 2/ add an horizontal separator next to the title ( Hugo ) */ const QFont oldFont = painter->font(); QFont font = oldFont; font.setBold( true ); painter->setFont( font ); QCommonStyle::drawComplexControl( CC_GroupBox, option, painter, widget ); painter->setFont( oldFont ); return true; } else return false; } //______________________________________________________________ bool Style::drawSliderComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionSlider *sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; const QPalette& palette( option->palette ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool hasFocus( flags & State_HasFocus ); if( sliderOption->subControls & SC_SliderTickmarks ) { renderSliderTickmarks( painter, sliderOption, widget ); } // groove if( sliderOption->subControls & SC_SliderGroove ) { // get rect QRect groove( subControlRect( CC_Slider, sliderOption, SC_SliderGroove, widget ) ); // adjustments if( sliderOption->orientation == Qt::Horizontal ) { const int center( groove.center().y() ); groove = QRect( groove.left(), center-Slider_GrooveWidth/2, groove.width(), Slider_GrooveWidth ).adjusted( 3, 0, -3, 0 ); groove.adjust( 2, 1, -2, 0 ); } else { const int center( groove.center().x() ); groove = QRect( center-Slider_GrooveWidth/2, groove.top(), Slider_GrooveWidth, groove.height() ).adjusted( 0, 3, 0, -3 ); groove.adjust( 0, 2, 0, -2 ); } // render if( groove.isValid() ) { helper().scrollHole( palette.color( QPalette::Window ), sliderOption->orientation, true )->render( groove, painter, TileSet::Full ); } } // handle if ( sliderOption->subControls & SC_SliderHandle ) { // get rect and center QRect r( subControlRect( CC_Slider, sliderOption, SC_SliderHandle, widget ) ); r = centerRect( r, 21, 21 ); const bool handleActive( sliderOption->activeSubControls & SC_SliderHandle ); StyleOptions opts( 0 ); if( hasFocus ) opts |= Focus; if( handleActive && mouseOver ) opts |= Hover; const QColor color( helper().backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) ); const QColor glow( slabShadowColor( color, opts ) ); const bool sunken( flags & (State_On|State_Sunken) ); painter->drawPixmap( r.topLeft(), helper().sliderSlab( color, glow, sunken, 0.0 ) ); } return true; } //______________________________________________________________ bool Style::drawSpinBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionSpinBox *sb = qstyleoption_cast( option ); if( !sb ) return true; const QRect& r( option->rect ); const QPalette& palette( option->palette ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & State_MouseOver ) ); const bool hasFocus( flags & State_HasFocus ); const QColor inputColor( palette.color( QPalette::Base ) ); if( sb->subControls & SC_SpinBoxFrame ) { QRect fr( r.adjusted( 1,1,-1,-1 ) ); painter->save(); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); painter->setBrush( inputColor ); if( !sb->frame ) { // frameless spinbox // frame is adjusted to have the same dimensions as a frameless editor painter->fillRect( r, inputColor ); painter->restore(); } else { // normal spinbox helper().fillHole( *painter, r.adjusted( 0, -1, 0, 0 ) ); painter->restore(); HoleOptions options( 0 ); if( hasFocus && enabled ) options |= HoleFocus; if( mouseOver && enabled ) options |= HoleHover; QColor local( palette.color( QPalette::Window ) ); helper().renderHole( painter, local, fr, options ); } } if( sb->subControls & SC_SpinBoxUp ) renderSpinBoxArrow( painter, sb, widget, SC_SpinBoxUp ); if( sb->subControls & SC_SpinBoxDown ) renderSpinBoxArrow( painter, sb, widget, SC_SpinBoxDown ); return true; } //______________________________________________________________ bool Style::drawTitleBarComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const QStyleOptionTitleBar *tb( qstyleoption_cast( option ) ); if( !tb ) return true; const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool active( enabled && ( tb->titleBarState & Qt::WindowActive ) ); // draw title text { QRect textRect = subControlRect( CC_TitleBar, tb, SC_TitleBarLabel, widget ); // make sure palette has the correct color group QPalette palette( option->palette ); palette.setCurrentColorGroup( active ? QPalette::Active: QPalette::Disabled ); QCommonStyle::drawItemText( painter, textRect, Qt::AlignCenter, palette, active, tb->text, QPalette::WindowText ); } // menu button if( ( tb->subControls & SC_TitleBarSysMenu ) && ( tb->titleBarFlags & Qt::WindowSystemMenuHint ) && !tb->icon.isNull() ) { const QRect br = subControlRect( CC_TitleBar, tb, SC_TitleBarSysMenu, widget ); tb->icon.paint( painter, br ); } if( ( tb->subControls & SC_TitleBarMinButton ) && ( tb->titleBarFlags & Qt::WindowMinimizeButtonHint ) ) { renderTitleBarButton( painter, tb, widget, SC_TitleBarMinButton ); } if( ( tb->subControls & SC_TitleBarMaxButton ) && ( tb->titleBarFlags & Qt::WindowMaximizeButtonHint ) ) { renderTitleBarButton( painter, tb, widget, SC_TitleBarMaxButton ); } if( ( tb->subControls & SC_TitleBarCloseButton ) ) { renderTitleBarButton( painter, tb, widget, SC_TitleBarCloseButton ); } if( ( tb->subControls & SC_TitleBarNormalButton ) && ( ( ( tb->titleBarFlags & Qt::WindowMinimizeButtonHint ) && ( tb->titleBarState & Qt::WindowMinimized ) ) || ( ( tb->titleBarFlags & Qt::WindowMaximizeButtonHint ) && ( tb->titleBarState & Qt::WindowMaximized ) ) ) ) { renderTitleBarButton( painter, tb, widget, SC_TitleBarNormalButton ); } if( tb->subControls & SC_TitleBarShadeButton ) { renderTitleBarButton( painter, tb, widget, SC_TitleBarShadeButton ); } if( tb->subControls & SC_TitleBarUnshadeButton ) { renderTitleBarButton( painter, tb, widget, SC_TitleBarUnshadeButton ); } if( ( tb->subControls & SC_TitleBarContextHelpButton ) && ( tb->titleBarFlags & Qt::WindowContextHelpButtonHint ) ) { renderTitleBarButton( painter, tb, widget, SC_TitleBarContextHelpButton ); } return true; } //______________________________________________________________ bool Style::drawToolButtonComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // check autoRaise state const State flags( option->state ); // get rect and palette const QStyleOptionToolButton *tool( qstyleoption_cast( option ) ); if( !tool ) return true; /* FIXME: this all logic is messy. The conditions to trigger the call to drawPrimitive can likely be simplified */ // local copy of option QStyleOptionToolButton tOpt( *tool ); tOpt.palette = option->palette; const QRect buttonRect( subControlRect( CC_ToolButton, tool, SC_ToolButton, widget ) ); // State_AutoRaise: only draw button when State_MouseOver State bflags = tool->state; if( bflags & State_AutoRaise && !( bflags & State_MouseOver ) ) { bflags &= ~State_Raised; } tOpt.state = bflags; if( tool->subControls & SC_ToolButton && ( bflags & ( State_Sunken | State_On | State_Raised ) ) ) { tOpt.rect = buttonRect; drawPanelButtonToolPrimitive( &tOpt, painter, widget ); } if( tool->subControls & SC_ToolButtonMenu ) { tOpt.rect = subControlRect( CC_ToolButton, tool, SC_ToolButtonMenu, widget ); painter->save(); drawIndicatorButtonDropDownPrimitive( &tOpt, painter, widget ); painter->restore(); } else if( tool->features & QStyleOptionToolButton::HasMenu ) { // This is requesting KDE3-style arrow indicator, per Qt 4.4 behavior. Qt 4.3 prefers to hide // the fact of the menu's existence. Whee! Since we don't know how to paint this right, // though, we have to have some metrics set for it to look nice. const int size( ToolButton_InlineMenuIndicatorSize ); if( size ) { const int xOff( ToolButton_InlineMenuIndicatorXOff ); const int yOff( ToolButton_InlineMenuIndicatorYOff ); tOpt.rect = QRect( buttonRect.right() + xOff + 1, buttonRect.bottom() + yOff + 1, size, size ); painter->save(); drawIndicatorButtonDropDownPrimitive( &tOpt, painter, widget ); painter->restore(); } } // CE_ToolButtonLabel expects a readjusted rect, for the button area proper QStyleOptionToolButton labelOpt = *tool; labelOpt.rect = buttonRect; drawToolButtonLabelControl( &labelOpt, painter, widget ); return true; } //_____________________________________________________________________ void Style::oxygenConfigurationChanged( void ) { // reset helper configuration helper().reloadConfig(); // background gradient helper().setUseBackgroundGradient( StyleConfigData::useBackgroundGradient() ); // background pixmap helper().setBackgroundPixmap( StyleConfigData::backgroundPixmap() ); // reset config StyleConfigData::self()->readConfig(); // update caches size int cacheSize( StyleConfigData::cacheEnabled() ? StyleConfigData::maxCacheSize():0 ); helper().setMaxCacheSize( cacheSize ); // reinitialize engines windowManager().initialize(); shadowHelper().reloadConfig(); // mnemonics mnemonics().setMode( StyleConfigData::mnemonicsMode() ); // widget explorer widgetExplorer().setEnabled( StyleConfigData::widgetExplorerEnabled() ); widgetExplorer().setDrawWidgetRects( StyleConfigData::drawWidgetRects() ); // 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; } // tabbar shape switch( StyleConfigData::tabStyle() ) { case StyleConfigData::TS_PLAIN: _tabBarTabShapeControl = &Style::drawTabBarTabShapeControl_Plain; break; default: case StyleConfigData::TS_SINGLE: _tabBarTabShapeControl = &Style::drawTabBarTabShapeControl_Single; break; } // frame focus if( StyleConfigData::viewDrawFocusIndicator() ) _frameFocusPrimitive = &Style::drawFrameFocusRectPrimitive; else _frameFocusPrimitive = &Style::emptyPrimitive; } //_____________________________________________________________________ void Style::globalPaletteChanged( void ) { helper().reloadConfig(); helper().invalidateCaches(); } //____________________________________________________________________ #ifndef QT_KATIE QIcon Style::standardIconImplementation( #else QIcon Style::standardIcon( #endif StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget ) const { switch( standardIcon ) { // copied from kstyle case SP_DesktopIcon: return KIcon( "user-desktop" ); case SP_TrashIcon: return KIcon( "user-trash" ); case SP_ComputerIcon: return KIcon( "computer" ); case SP_DriveFDIcon: return KIcon( "media-floppy" ); case SP_DriveHDIcon: return KIcon( "drive-harddisk" ); case SP_DriveCDIcon: return KIcon( "drive-optical" ); case SP_DriveDVDIcon: return KIcon( "drive-optical" ); case SP_DriveNetIcon: return KIcon( "folder-remote" ); case SP_DirHomeIcon: return KIcon( "user-home" ); case SP_DirOpenIcon: return KIcon( "document-open-folder" ); case SP_DirClosedIcon: return KIcon( "folder" ); case SP_DirIcon: return KIcon( "folder" ); //TODO: generate ( !? ) folder with link emblem case SP_DirLinkIcon: return KIcon( "folder" ); //TODO: look for a better icon case SP_FileIcon: return KIcon( "text-plain" ); //TODO: generate ( !? ) file with link emblem case SP_FileLinkIcon: return KIcon( "text-plain" ); //TODO: find correct icon case SP_FileDialogStart: return KIcon( "media-playback-start" ); //TODO: find correct icon case SP_FileDialogEnd: return KIcon( "media-playback-stop" ); case SP_FileDialogToParent: return KIcon( "go-up" ); case SP_FileDialogNewFolder: return KIcon( "folder-new" ); case SP_FileDialogDetailedView: return KIcon( "view-list-details" ); case SP_FileDialogInfoView: return KIcon( "document-properties" ); case SP_FileDialogContentsView: return KIcon( "view-list-icons" ); case SP_FileDialogListView: return KIcon( "view-list-text" ); case SP_FileDialogBack: return KIcon( "go-previous" ); case SP_MessageBoxInformation: return KIcon( "dialog-information" ); case SP_MessageBoxWarning: return KIcon( "dialog-warning" ); case SP_MessageBoxCritical: return KIcon( "dialog-error" ); case SP_MessageBoxQuestion: return KIcon( "dialog-information" ); case SP_DialogOkButton: return KIcon( "dialog-ok" ); case SP_DialogCancelButton: return KIcon( "dialog-cancel" ); case SP_DialogHelpButton: return KIcon( "help-contents" ); case SP_DialogOpenButton: return KIcon( "document-open" ); case SP_DialogSaveButton: return KIcon( "document-save" ); case SP_DialogCloseButton: return KIcon( "dialog-close" ); case SP_DialogApplyButton: return KIcon( "dialog-ok-apply" ); case SP_DialogResetButton: return KIcon( "document-revert" ); case SP_DialogDiscardButton: return KIcon( "dialog-cancel" ); case SP_DialogYesButton: return KIcon( "dialog-ok-apply" ); case SP_DialogNoButton: return KIcon( "dialog-cancel" ); case SP_ArrowUp: return KIcon( "go-up" ); case SP_ArrowDown: return KIcon( "go-down" ); case SP_ArrowLeft: return KIcon( "go-previous-view" ); case SP_ArrowRight: return KIcon( "go-next-view" ); case SP_ArrowBack: return KIcon( "go-previous" ); case SP_ArrowForward: return KIcon( "go-next" ); case SP_BrowserReload: return KIcon( "view-refresh" ); case SP_BrowserStop: return KIcon( "process-stop" ); case SP_MediaPlay: return KIcon( "media-playback-start" ); case SP_MediaStop: return KIcon( "media-playback-stop" ); case SP_MediaPause: return KIcon( "media-playback-pause" ); case SP_MediaSkipForward: return KIcon( "media-skip-forward" ); case SP_MediaSkipBackward: return KIcon( "media-skip-backward" ); case SP_MediaSeekForward: return KIcon( "media-seek-forward" ); case SP_MediaSeekBackward: return KIcon( "media-seek-backward" ); case SP_MediaVolume: return KIcon( "audio-volume-medium" ); case SP_MediaVolumeMuted: return KIcon( "audio-volume-muted" ); default: break; } // 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 = qApp->palette().window().color(); iconColor = qApp->palette().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 ) ); switch( standardIcon ) { case SP_TitleBarNormalButton: { QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ), pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarNormalButton ); return QIcon( pixmap ); } case SP_TitleBarShadeButton: { QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ), pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarShadeButton ); return QIcon( pixmap ); } case SP_TitleBarUnshadeButton: { QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ), pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarUnshadeButton ); return QIcon( pixmap ); } case SP_TitleBarCloseButton: case SP_DockWidgetCloseButton: { QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ), pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarCloseButton ); return QIcon( pixmap ); } case SP_ToolBarHorizontalExtensionButton: { QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize,0,0 ), pixelMetric( QStyle::PM_SmallIconSize,0,0 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setBrush( Qt::NoBrush ); painter.translate( qreal( pixmap.width() )/2.0, qreal( pixmap.height() )/2.0 ); const bool reverseLayout( option && option->direction == Qt::RightToLeft ); QPolygonF a = 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( a ); painter.translate( 0,-1 ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( iconColor, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter.drawPolyline( a ); return QIcon( pixmap ); } case SP_ToolBarVerticalExtensionButton: { QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize,0,0 ), pixelMetric( QStyle::PM_SmallIconSize,0,0 ) ); pixmap.fill( Qt::transparent ); QPainter painter( &pixmap ); painter.setRenderHints( QPainter::Antialiasing ); painter.setBrush( Qt::NoBrush ); painter.translate( qreal( pixmap.width() )/2.0, qreal( pixmap.height() )/2.0 ); QPolygonF a = 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( a ); painter.translate( 0,-1 ); painter.setBrush( Qt::NoBrush ); painter.setPen( QPen( iconColor, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter.drawPolyline( a ); return QIcon( pixmap ); } default: #ifndef QT_KATIE return QCommonStyle::standardIconImplementation( standardIcon, option, widget ); #else return QCommonStyle::standardIcon( standardIcon, option, widget ); #endif } } //_____________________________________________________________ void Style::initializeKGlobalSettings( void ) { if( qApp && !qApp->inherits( "KApplication" ) ) { /* for Qt, non-KDE applications, needs to explicitly activate KGlobalSettings. On the other hand, it is done internally in kApplication constructor, so no need to duplicate here. */ KGlobalSettings::self()->activate( KGlobalSettings::ListenForChanges ); } // connect palette changes to local slot, to make sure caches are cleared connect( KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(globalPaletteChanged()) ); // update flag _kGlobalSettingsInitialized = true; } //______________________________________________________________ void Style::polishScrollArea( QAbstractScrollArea* scrollArea ) const { if( !scrollArea ) 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; } //_________________________________________________________________________________ void Style::renderDialSlab( QPainter *painter, const QRect& r, const QColor &color, const QStyleOption *option, StyleOptions opts ) const { // cast option const QStyleOptionSlider* sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return; // adjust rect to be square, and centered const int dimension( qMin( r.width(), r.height() ) ); const QRect rect( centerRect( r, dimension, dimension ) ); // calculate glow color const QColor glow( slabShadowColor( color, opts ) ); // get main slab QPixmap pix( helper().dialSlab( color, glow, 0.0, dimension ) ); const qreal baseOffset( 3.5 ); const QColor light( helper().calcLightColor( color ) ); const QColor shadow( helper().calcShadowColor( color ) ); QPainter p( &pix ); p.setPen( Qt::NoPen ); p.setRenderHints( QPainter::Antialiasing ); // indicator qreal angle( 0 ); if( sliderOption->maximum == sliderOption->minimum ) angle = M_PI / 2; else { qreal fraction( qreal( sliderOption->sliderPosition - sliderOption->minimum )/qreal( sliderOption->maximum - sliderOption->minimum ) ); if( !sliderOption->upsideDown ) fraction = 1.0 - fraction; if( sliderOption->dialWrapping ) angle = 1.5*M_PI - fraction*2*M_PI; else angle = ( M_PI*8 - fraction*10*M_PI )/6; } QPointF center( pix.rect().center() ); 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 ); QLinearGradient lg( 0, baseOffset, 0, baseOffset + 2*sliderRect.height() ); p.setBrush( light ); p.setPen( Qt::NoPen ); p.drawEllipse( sliderRect.translated( 0, offset ) ); // mask p.setPen( Qt::NoPen ); p.save(); p.setCompositionMode( QPainter::CompositionMode_DestinationOut ); p.setBrush( QBrush( Qt::black ) ); p.drawEllipse( sliderRect ); p.restore(); // shadow p.translate( sliderRect.topLeft() ); helper().drawInverseShadow( p, shadow.darker( 200 ), 0.0, sliderRect.width(), 0.0 ); // glow if( glow.isValid() ) helper().drawInverseGlow( p, glow, 0.0, sliderRect.width(), sliderRect.width() ); p.end(); painter->drawPixmap( rect.topLeft(), pix ); return; } //____________________________________________________________________________________ void Style::renderButtonSlab( QPainter *painter, QRect r, const QColor &color, StyleOptions options, TileSet::Tiles tiles ) const { if( ( r.width() <= 0 ) || ( r.height() <= 0 ) ) return; r.translate( 0,-1 ); if( !painter->clipRegion().isEmpty() ) painter->setClipRegion( painter->clipRegion().translated( 0,-1 ) ); // fill if( !( options & NoFill ) ) helper().fillButtonSlab( *painter, r, color, options&Sunken ); // 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 *tile(0L); if( options & Sunken ) { tile = helper().slabSunken( color ); } else { QColor glow = slabShadowColor( color, options ); tile = helper().slab( color, glow, 0.0 ); } if( tile ) { tile->render( r, painter, tiles ); } } //____________________________________________________________________________________ void Style::renderSlab( QPainter *painter, QRect r, const QColor &color, StyleOptions options, TileSet::Tiles tiles ) const { // check rect if( !r.isValid() ) return; // this is needed for button vertical alignment r.translate( 0,-1 ); if( !painter->clipRegion().isEmpty() ) painter->setClipRegion( painter->clipRegion().translated( 0,-1 ) ); // additional adjustment for sunken frames if( options & Sunken ) r.adjust( -1,0,1,2 ); // 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, r.top(), 0, r.bottom() + r.height() ); innerGradient.setColorAt( 0.0, color ); innerGradient.setColorAt( 1.0, helper().calcLightColor( color ) ); painter->setBrush( innerGradient ); } else { QLinearGradient innerGradient( 0, r.top() - r.height(), 0, r.bottom() ); innerGradient.setColorAt( 0.0, helper().calcLightColor( color ) ); innerGradient.setColorAt( 1.0, color ); painter->setBrush( innerGradient ); } helper().fillSlab( *painter, r ); 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 *tile( 0 ); if( ( options & Sunken ) && color.isValid() ) { tile = helper().slabSunken( color ); } else { // calculate proper glow color based on current settings const QColor glow( slabShadowColor( color, options) ); if( color.isValid() || glow.isValid() ) tile = helper().slab( color, glow , 0.0 ); else return; } // render tileset if( tile ) tile->render( r, painter, tiles ); } //______________________________________________________________________________________________________________________________ void Style::fillTabBackground( QPainter* painter, const QRect &r, const QColor &color, QTabBar::Shape shape, const QWidget* widget ) const { // filling QRect fillRect( r ); switch( shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: fillRect.adjust( 4, 4, -4, -6 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: fillRect.adjust( 4, 4, -4, -4 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: fillRect.adjust( 4, 3, -5, -5 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: fillRect.adjust( 5, 3, -4, -5 ); break; default: return; } if( widget ) helper().renderWindowBackground( painter, fillRect, widget, color ); else painter->fillRect( fillRect, color ); } //______________________________________________________________________________________________________________________________ void Style::fillTab( QPainter* painter, const QRect &r, const QColor &color, QTabBar::Shape shape, bool active ) const { const QColor dark( helper().calcDarkColor( color ) ); const QColor shadow( helper().calcShadowColor( color ) ); const QColor light( helper().calcLightColor( color ) ); const QRect fillRect( r.adjusted( 4, 3,-4,-5 ) ); QLinearGradient highlight; switch( shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: highlight = QLinearGradient( fillRect.topLeft(), fillRect.bottomLeft() ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: highlight = QLinearGradient( fillRect.bottomLeft(), fillRect.topLeft() ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: highlight = QLinearGradient( fillRect.topRight(), fillRect.topLeft() ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: highlight = QLinearGradient( fillRect.topLeft(), fillRect.topRight() ); break; default: return; } if( active ) { highlight.setColorAt( 0.0, helper().alphaColor( light, 0.5 ) ); highlight.setColorAt( 0.1, helper().alphaColor( light, 0.5 ) ); highlight.setColorAt( 0.25, helper().alphaColor( light, 0.3 ) ); highlight.setColorAt( 0.5, helper().alphaColor( light, 0.2 ) ); highlight.setColorAt( 0.75, helper().alphaColor( light, 0.1 ) ); highlight.setColorAt( 0.9, Qt::transparent ); } else { // inactive highlight.setColorAt( 0.0, helper().alphaColor( light, 0.1 ) ); highlight.setColorAt( 0.4, helper().alphaColor( dark, 0.5 ) ); highlight.setColorAt( 0.8, helper().alphaColor( dark, 0.4 ) ); highlight.setColorAt( 0.9, Qt::transparent ); } painter->setRenderHints( QPainter::Antialiasing ); painter->setPen( Qt::NoPen ); painter->setBrush( highlight ); 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& flags( option->state ); // enable state bool enabled( flags & 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 && ( flags & State_MouseOver ) ); // check animation state const bool subControlHover( enabled && mouseOver && ( option->activeSubControls & subControl ) ); QColor color; if( subControlHover ) { color = helper().viewHoverBrush().brush( palette ).color(); } 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::Background ); const QPolygonF a( genericArrow( ( subControl == SC_SpinBoxUp ) ? ArrowUp:ArrowDown, ArrowNormal ) ); const QRect arrowRect( subControlRect( CC_SpinBox, option, subControl, widget ) ); painter->save(); painter->translate( arrowRect.center() ); painter->setRenderHint( QPainter::Antialiasing ); painter->setPen( QPen( helper().decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->restore(); return; } //___________________________________________________________________________________ void Style::renderSplitter( const QStyleOption* option, QPainter* painter, const QWidget* widget, bool horizontal ) const { Q_UNUSED(widget); const QPalette& palette( option->palette ); const QRect& r( option->rect ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool mouseOver( enabled && ( flags & ( State_MouseOver|State_Sunken ) ) ); // get base color const QColor color = palette.color( QPalette::Background ); if( horizontal ) { const int hCenter = r.center().x(); const int h = r.height(); if( mouseOver ) { const QColor highlight = helper().alphaColor( helper().calcLightColor( color ),0 ); const qreal a( r.height() > 30 ? 10.0/r.height():0.1 ); QLinearGradient lg( 0, r.top(), 0, r.bottom() ); lg.setColorAt( 0, Qt::transparent ); lg.setColorAt( a, highlight ); lg.setColorAt( 1.0-a, highlight ); lg.setColorAt( 1, Qt::transparent ); painter->fillRect( r, lg ); } const int ngroups( qMax( 1,h / 250 ) ); int center( ( h - ( ngroups-1 ) * 250 ) /2 + r.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( r.center().y() ); const int w( r.width() ); if( mouseOver ) { const QColor highlight( helper().alphaColor( helper().calcLightColor( color ),0 ) ); const qreal a( r.width() > 30 ? 10.0/r.width():0.1 ); QLinearGradient lg( r.left(), 0, r.right(), 0 ); lg.setColorAt( 0, Qt::transparent ); lg.setColorAt( a, highlight ); lg.setColorAt( 1.0-a, highlight ); lg.setColorAt( 1, Qt::transparent ); painter->fillRect( r, lg ); } const int ngroups( qMax( 1, w / 250 ) ); int center = ( w - ( ngroups-1 ) * 250 ) /2 + r.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 { const QRect r = subControlRect( CC_TitleBar, option, subControl, widget ); if( !r.isValid() ) return; QPalette palette = option->palette; const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool active( enabled && ( option->titleBarState & Qt::WindowActive ) ); const bool sunken( flags&State_Sunken ); const bool mouseOver( ( !sunken ) && widget && r.translated( widget->mapToGlobal( QPoint( 0,0 ) ) ).contains( QCursor::pos() ) ); // contrast color const QColor base =option->palette.color( QPalette::Active, QPalette::Window ); // icon color QColor color; if( mouseOver ) { color = ( subControl == SC_TitleBarCloseButton ) ? helper().viewNegativeTextBrush().brush( palette ).color(): helper().viewHoverBrush().brush( palette ).color(); } else { color = palette.color( active ? QPalette::Active : QPalette::Disabled, QPalette::WindowText ); } // rendering renderTitleBarButton( painter, r, 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 &r, const SubControl& subControl ) const { painter->save(); painter->translate( r.topLeft() ); painter->scale( qreal( r.width() )/16, qreal( r.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& r, const QPalette& palette, QPainter* painter, const QWidget* widget, bool horizontal, bool reverse ) const { // use window background for the background if( widget ) helper().renderWindowBackground( painter, r, widget, palette ); else painter->fillRect( r, palette.color( QPalette::Window ) ); if( horizontal ) renderHeaderLines( r, palette, painter, TileSet::Bottom ); else if( reverse ) renderHeaderLines( r, palette, painter, TileSet::Left ); else renderHeaderLines( r, palette, painter, TileSet::Right ); } //__________________________________________________________________________ void Style::renderHeaderLines( const QRect& r, 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( r ); 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::renderMenuItemRect( const QStyleOption* opt, const QRect& r, const QColor& base, const QPalette& palette, QPainter* painter ) const { // 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( opt ); if( menuItemOption && menuItemOption->menuItemType == QStyleOptionMenuItem::SubMenu ) { QPixmap pm( r.size() ); pm.fill( Qt::transparent ); QPainter pp( &pm ); QRect rr( QPoint( 0,0 ), r.size() ); pp.setRenderHint( QPainter::Antialiasing ); pp.setPen( Qt::NoPen ); pp.setBrush( color ); helper().fillHole( pp, rr ); helper().holeFlat( color, 0.0 )->render( rr.adjusted( 1, 2, -2, -1 ), &pp ); QRect maskr( visualRect( opt->direction, rr, QRect( rr.width()-40, 0, 40,rr.height() ) ) ); QLinearGradient gradient( visualPos( opt->direction, maskr, QPoint( maskr.left(), 0 ) ), visualPos( opt->direction, maskr, QPoint( maskr.right()-4, 0 ) ) ); gradient.setColorAt( 0.0, Qt::black ); gradient.setColorAt( 1.0, Qt::transparent ); pp.setBrush( gradient ); pp.setCompositionMode( QPainter::CompositionMode_DestinationIn ); pp.drawRect( maskr ); pp.end(); painter->drawPixmap( handleRTL( opt, r ), pm ); } } //________________________________________________________________________ void Style::renderCheckBox( QPainter *painter, const QRect &rect, const QPalette &palette, StyleOptions options, CheckBoxState state) const { const int s( qMin( rect.width(), rect.height() ) ); const QRect r( centerRect( rect, s, s ) ); if( !( options & NoFill ) ) { if( options & Sunken ) helper().holeFlat( palette.color( QPalette::Window ), 0.0, false )->render( r, painter, TileSet::Full ); else renderSlab( painter, r, palette.color( QPalette::Button ), options, TileSet::Ring ); } // check mark const qreal x( r.center().x() - 3.5 ); const qreal y( r.center().y() - 2.5 ); if( state != CheckOff ) { qreal penThickness( 2.0 ); 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; if( StyleConfigData::checkBoxStyle() == StyleConfigData::CS_CHECK ) { dashes << 1.0 << 2.0; penThickness = 1.3; pen.setWidthF( penThickness ); contrastPen.setWidthF( penThickness ); } else { dashes << 0.4 << 2.0; } 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(); if( !( options&Sunken ) ) painter->translate( 0, -1 ); painter->setRenderHint( QPainter::Antialiasing ); const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); if( StyleConfigData::checkBoxStyle() == StyleConfigData::CS_CHECK ) { painter->setPen( contrastPen ); painter->translate( 0, offset ); painter->drawLine( QPointF( x+9, y ), QPointF( x+3,y+7 ) ); painter->drawLine( QPointF( x, y+4 ), QPointF( x+3,y+7 ) ); painter->setPen( pen ); painter->translate( 0, -offset ); painter->drawLine( QPointF( x+9, y ), QPointF( x+3,y+7 ) ); painter->drawLine( QPointF( x, y+4 ), QPointF( x+3,y+7 ) ); } else { if( options&Sunken ) { painter->setPen( contrastPen ); painter->translate( 0, offset ); painter->drawLine( QPointF( x+8, y ), QPointF( x+1,y+7 ) ); painter->drawLine( QPointF( x+8, y+7 ), QPointF( x+1,y ) ); painter->setPen( pen ); painter->translate( 0, -offset ); painter->drawLine( QPointF( x+8, y ), QPointF( x+1,y+7 ) ); painter->drawLine( QPointF( x+8, y+7 ), QPointF( x+1,y ) ); } else { painter->setPen( contrastPen ); painter->translate( 0, offset ); painter->drawLine( QPointF( x+8, y-1 ), QPointF( x,y+7 ) ); painter->drawLine( QPointF( x+8, y+7 ), QPointF( x,y-1 ) ); painter->setPen( pen ); painter->translate( 0, -offset ); painter->drawLine( QPointF( x+8, y-1 ), QPointF( x,y+7 ) ); painter->drawLine( QPointF( x+8, y+7 ), QPointF( x,y-1 ) ); } } painter->restore(); } return; } //___________________________________________________________________ void Style::renderRadioButton( QPainter* painter, const QRect& rect, const QPalette& palette, StyleOptions options, CheckBoxState state) const { const int s( CheckBox_Size ); const QRect r( centerRect( rect, s, s ) ); const int x = r.x(); const int y = r.y(); const QColor color( palette.color( QPalette::Button ) ); const QColor glow( slabShadowColor( color, options ) ); painter->drawPixmap( x, y, helper().roundSlab( color, glow, 0.0 ) ); // draw the radio mark if( state != CheckOff ) { const qreal radius( 2.6 ); const qreal dx( 0.5*r.width() - radius ); const qreal dy( 0.5*r.height() - radius ); 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( QRectF( r ).adjusted( dx, dy, -dx, -dy ) ); // 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( QRectF( r ).adjusted( dx, dy, -dx, -dy ) ); painter->restore(); } return; } //______________________________________________________________________________ void Style::renderScrollBarHole( QPainter *painter, const QRect &r, const QColor &color, const Qt::Orientation& orientation, const TileSet::Tiles& tiles ) const { if( !r.isValid() ) return; // one need to make smaller shadow // notably on the size when rect height is too high const bool smallShadow( orientation == Qt::Horizontal ? r.height() < 10 : r.width() < 10 ); helper().scrollHole( color, orientation, smallShadow )->render( r, painter, tiles ); } //______________________________________________________________________________ void Style::renderScrollBarHandle( QPainter* painter, const QRect& r, const QPalette& palette, const Qt::Orientation& orientation, const bool& hover ) const { if( !r.isValid() ) return; // define rect and check const bool horizontal( orientation == Qt::Horizontal ); QRectF rect( horizontal ? r.adjusted( 3, 2, -3, -3 ):r.adjusted( 3, 4, -3, -3 ) ); if( !rect.isValid() ) return; 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().viewHoverBrush().brush( QPalette::Active ).color() ); if( hover ) glow = hovered; else glow = shadow; helper().scrollHandle( color, glow )-> render( rect.adjusted( -3, -3, 3, 3 ).toRect(), painter, TileSet::Full ); // contents const QColor mid( helper().calcMidColor( color ) ); QLinearGradient lg( 0, rect.top(), 0, rect.bottom() ); lg.setColorAt(0, color ); lg.setColorAt(1, mid ); painter->setPen( Qt::NoPen ); painter->setBrush( lg ); painter->drawRoundedRect( rect.adjusted( 1, 1, -1, -1), radius - 2, radius - 2 ); // bevel pattern const QColor light( helper().calcLightColor( color ) ); QLinearGradient patternGradient( 0, 0, horizontal ? 30:0, horizontal? 0:30 ); patternGradient.setSpread( QGradient::ReflectSpread ); patternGradient.setColorAt( 0.0, Qt::transparent ); patternGradient.setColorAt( 1.0, helper().alphaColor( light, 0.1 ) ); QRectF bevelRect( rect ); if( horizontal ) bevelRect.adjust( 0, 3, 0, -3 ); else bevelRect.adjust( 3, 0, -3, 0 ); if( bevelRect.isValid() ) { painter->setBrush( patternGradient ); painter->drawRect( bevelRect ); } painter->restore(); return; } //______________________________________________________________________________ void Style::renderScrollBarArrow( QPainter* painter, const QRect& r, const QColor& color, const QColor& background, ArrowOrientation orientation ) const { const qreal penThickness = 1.6; QPolygonF a( genericArrow( orientation, ArrowNormal ) ); const QColor contrast( helper().calcLightColor( background ) ); const QColor base( helper().decoColor( background, color ) ); painter->save(); painter->translate( r.center() ); painter->setRenderHint( QPainter::Antialiasing ); const qreal offset( qMin( penThickness, qreal( 1.0 ) ) ); painter->translate( 0,offset ); painter->setPen( QPen( contrast, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->translate( 0,-offset ); painter->setPen( QPen( base, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) ); painter->drawPolyline( a ); painter->restore(); return; } //______________________________________________________________________________ QColor Style::scrollBarArrowColor( const QStyleOptionSlider* option, const SubControl& control, const QWidget* widget ) const { Q_UNUSED(widget); const QPalette& palette( option->palette ); 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 ); } return color; } //______________________________________________________________________________ void Style::renderSliderTickmarks( QPainter* painter, const QStyleOptionSlider* option, const QWidget* widget ) const { const int& ticks( option->tickPosition ); const int available( pixelMetric( PM_SliderSpaceAvailable, option, widget ) ); int interval = option->tickInterval; if( interval < 1 ) interval = option->pageStep; if( interval < 1 ) return; const QRect& r( option->rect ); const QPalette& palette( option->palette ); const int fudge( pixelMetric( PM_SliderLength, option, widget ) / 2 ); int current( option->minimum ); // Since there is no subrect for tickmarks do a translation here. painter->save(); painter->translate( r.x(), r.y() ); if( option->orientation == Qt::Horizontal ) { QColor base( helper().backgroundColor( palette.color( QPalette::Window ), widget, r.center() ) ); painter->setPen( helper().calcDarkColor( base ) ); } int tickSize( option->orientation == Qt::Horizontal ? r.height()/3:r.width()/3 ); while( current <= option->maximum ) { const int position( sliderPositionFromValue( option->minimum, option->maximum, current, available ) + fudge ); // calculate positions if( option->orientation == Qt::Horizontal ) { if( ticks == QSlider::TicksAbove ) painter->drawLine( position, 0, position, tickSize ); else if( ticks == QSlider::TicksBelow ) painter->drawLine( position, r.height()-tickSize, position, r.height() ); else { painter->drawLine( position, 0, position, tickSize ); painter->drawLine( position, r.height()-tickSize, position, r.height() ); } } else { QColor base( helper().backgroundColor( palette.color( QPalette::Window ), widget, QPoint( r.center().x(), position ) ) ); painter->setPen( helper().calcDarkColor( base ) ); if( ticks == QSlider::TicksAbove ) painter->drawLine( 0, position, tickSize, position ); else if( ticks == QSlider::TicksBelow ) painter->drawLine( r.width()-tickSize, position, r.width(), position ); else { painter->drawLine( 0, position, tickSize, position ); painter->drawLine( r.width()-tickSize, position, r.width(), position ); } } // go to next position current += interval; } painter->restore(); } //____________________________________________________________________________________ QColor Style::slabShadowColor( QColor color, StyleOptions options ) const { QColor glow; if( options & Hover ) glow = helper().viewHoverBrush().brush( QPalette::Active ).color(); else if( options & Focus ) glow = helper().viewFocusBrush().brush( QPalette::Active ).color(); else if( ( options & SubtleShadow ) && color.isValid() ) glow = helper().alphaColor( helper().calcShadowColor( color ), 0.15 ); return glow; } //____________________________________________________________________________________ QPolygonF Style::genericArrow( Style::ArrowOrientation orientation, Style::ArrowSize size ) const { QPolygonF a; switch( orientation ) { case ArrowUp: { if( size == ArrowTiny ) a << QPointF( -1.75, 1.125 ) << QPointF( 0.5, -1.125 ) << QPointF( 2.75, 1.125 ); else if( size == ArrowSmall ) a << QPointF( -2,1.5 ) << QPointF( 0.5, -1.5 ) << QPointF( 3,1.5 ); else a << QPointF( -3,2.5 ) << QPointF( 0.5, -1.5 ) << QPointF( 4,2.5 ); break; } case ArrowDown: { if( size == ArrowTiny ) a << QPointF( -1.75, -1.125 ) << QPointF( 0.5, 1.125 ) << QPointF( 2.75, -1.125 ); else if( size == ArrowSmall ) a << QPointF( -2,-1.5 ) << QPointF( 0.5, 1.5 ) << QPointF( 3,-1.5 ); else a << QPointF( -3,-1.5 ) << QPointF( 0.5, 2.5 ) << QPointF( 4,-1.5 ); break; } case ArrowLeft: { if( size == ArrowTiny ) a << QPointF( 1.125, -1.75 ) << QPointF( -1.125, 0.5 ) << QPointF( 1.125, 2.75 ); else if( size == ArrowSmall ) a << QPointF( 1.5,-2 ) << QPointF( -1.5, 0.5 ) << QPointF( 1.5,3 ); else a << QPointF( 2.5,-3 ) << QPointF( -1.5, 0.5 ) << QPointF( 2.5,4 ); break; } case ArrowRight: { if( size == ArrowTiny ) a << QPointF( -1.125, -1.75 ) << QPointF( 1.125, 0.5 ) << QPointF( -1.125, 2.75 ); else if( size == ArrowSmall ) a << QPointF( -1.5,-2 ) << QPointF( 1.5, 0.5 ) << QPointF( -1.5,3 ); else a << QPointF( -1.5,-3 ) << QPointF( 2.5, 0.5 ) << QPointF( -1.5,4 ); break; } default: break; } return a; } }