kde-workspace/kstyles/oxygen/oxygenstyle.cpp
Ivailo Monev 96f645afe4 generic: prepare for Katie changes
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2024-03-15 09:05:41 +02:00

8724 lines
332 KiB
C++

// krazy:excludeall=qclasses
//////////////////////////////////////////////////////////////////////////////
// oxygenstyle.cpp
// Oxygen widget style for KDE 4
// -------------------
//
// Copyright ( C ) 2009-2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
// Copyright ( C ) 2008 Long Huynh Huu <long.upcase@googlemail.com>
// Copyright ( C ) 2007-2008 Casper Boemann <cbr@boemann.dk>
// Copyright ( C ) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
// Copyright ( C ) 2003-2005 Sandro Giessl <sandro@giessl.com>
//
// based on the KDE style "dotNET":
// Copyright ( C ) 2001-2002, Chris Lee <clee@kde.org>
// Carsten Pfeiffer <pfeiffer@kde.org>
// Karol Szwed <gallium@kde.org>
// 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 <malte@kde.org>
// ( c ) 2002,2003 Maksim Orlovich <mo002j@mail.rochester.edu>
// based on the KDE3 HighColor Style
// Copyright ( C ) 2001-2002 Karol Szwed <gallium@kde.org>
// ( C ) 2001-2002 Fredrik Höglund <fredrik@kde.org>
// Drawing routines adapted from the KDE2 HCStyle,
// Copyright ( C ) 2000 Daniel M. Duley <mosfet@kde.org>
// ( C ) 2000 Dirk Mueller <mueller@kde.org>
// ( C ) 2001 Martijn Klingens <klingens@kde.org>
// Progressbar code based on KStyle,
// Copyright ( C ) 2001-2002 Karol Szwed <gallium@kde.org>
//
// 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 "oxygenmnemonics.h"
#include "oxygenshadowhelper.h"
#include "oxygenstyleconfigdata.h"
#include "oxygenwidgetexplorer.h"
#include "oxygenwindowmanager.h"
#include "oxygenpropertynames.h"
#include <QtCore/QDebug>
#include <QtGui/QAbstractButton>
#include <QtGui/QAbstractItemView>
#include <QtGui/QApplication>
#include <QtGui/QCheckBox>
#include <QtGui/QComboBox>
#include <QtGui/QDial>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QDockWidget>
#include <QtGui/QDoubleSpinBox>
#include <QtGui/QFormLayout>
#include <QtGui/QFrame>
#include <QtGui/QGraphicsView>
#include <QtGui/QGroupBox>
#include <QtGui/QLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QMainWindow>
#include <QtGui/QPushButton>
#include <QtGui/QRadioButton>
#include <QtGui/QScrollBar>
#include <QtGui/QSpinBox>
#include <QtGui/QSplitter>
#include <QtGui/QStylePlugin>
#include <QtGui/QStyleOption>
#include <QtGui/QTextEdit>
#include <QtGui/QToolBar>
#include <QtGui/QToolBox>
#include <QtGui/QToolButton>
#include <QtGui/QMenuBar>
#include <QtDBus/QDBusConnection>
#include <KColorUtils>
#include <KGlobal>
#include <KGlobalSettings>
#include <KIconLoader>
#include <KIcon>
#include <kdeversion.h>
#include <cmath>
//_____________________________________________
// 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_PLUGIN( 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<QWidget*>( object );
if( event->type() == QEvent::Show && _helper.hasDecoration( widget ) )
{
_helper.setHasBackgroundGradient( widget->winId(), true );
}
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 ) ),
_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() );
shadowHelper().registerWidget( widget );
// scroll areas
if( QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>( widget ) )
{
polishScrollArea( scrollArea );
}
// KTextEdit frames
// static cast is safe here, since isKTextEdit already checks that widget inherits from QFrame
if( isKTextEditFrame( widget ) && static_cast<QFrame*>( 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<QAbstractItemView*>( widget )
|| qobject_cast<QAbstractSpinBox*>( widget )
|| qobject_cast<QCheckBox*>( widget )
|| qobject_cast<QComboBox*>( widget )
|| qobject_cast<QDial*>( widget )
|| qobject_cast<QLineEdit*>( widget )
|| qobject_cast<QPushButton*>( widget )
|| qobject_cast<QRadioButton*>( widget )
|| qobject_cast<QScrollBar*>( widget )
|| qobject_cast<QSlider*>( widget )
|| qobject_cast<QSplitterHandle*>( widget )
|| qobject_cast<QTabBar*>( widget )
|| qobject_cast<QTextEdit*>( widget )
|| qobject_cast<QToolButton*>( widget )
)
{ widget->setAttribute( Qt::WA_Hover ); }
// transparent tooltips
if( widget->inherits( "QTipLabel" ) )
{
widget->setAttribute( Qt::WA_TranslucentBackground );
}
if( QAbstractItemView *itemView = qobject_cast<QAbstractItemView*>( widget ) )
{
// enable hover effects in itemviews' viewport
itemView->viewport()->setAttribute( Qt::WA_Hover );
} else if( QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>( 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<QGroupBox*>( widget ) ) {
// checkable group boxes
if( groupBox->isCheckable() )
{ groupBox->setAttribute( Qt::WA_Hover ); }
} else if( qobject_cast<QAbstractButton*>( widget ) && qobject_cast<QDockWidget*>( widget->parent() ) ) {
widget->setAttribute( Qt::WA_Hover );
} else if( qobject_cast<QAbstractButton*>( widget ) && qobject_cast<QToolBox*>( 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<QToolBar*>( widget->parent() ) )
{ widget->setContentsMargins( 0,0,0,1 ); }
if( qobject_cast<QToolButton*>( widget ) )
{
if( qobject_cast<QToolBar*>( 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<QMenuBar*>( 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<QToolBar*>( widget ) ) {
widget->setBackgroundRole( QPalette::NoRole );
addEventFilter( widget );
} else if( qobject_cast<QTabBar*>( widget ) ) {
addEventFilter( widget );
} else if( widget->inherits( "QTipLabel" ) ) {
widget->setBackgroundRole( QPalette::NoRole );
widget->setAttribute( Qt::WA_TranslucentBackground );
} else if( qobject_cast<QScrollBar*>( 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<QDockWidget*>( widget ) ) {
widget->setBackgroundRole( QPalette::NoRole );
widget->setContentsMargins( 3,3,3,3 );
addEventFilter( widget );
} else if( qobject_cast<QToolBox*>( 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<QToolBox*>( widget->parentWidget()->parentWidget()->parentWidget() ) ) {
widget->setBackgroundRole( QPalette::NoRole );
widget->setAutoFillBackground( false );
widget->parentWidget()->setAutoFillBackground( false );
} else if( qobject_cast<QMenu*>( widget ) ) {
widget->setAttribute( Qt::WA_TranslucentBackground );
} else if( widget->inherits( "QComboBoxPrivateContainer" ) ) {
addEventFilter( widget );
widget->setAttribute( Qt::WA_TranslucentBackground );
} else if( qobject_cast<QFrame*>( widget ) && widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ) {
widget->setAutoFillBackground( false );
widget->setBackgroundRole( QPalette::Window );
} else if( qobject_cast<QProgressBar*>( widget ) ) {
addEventFilter( widget );
}
// base class polishing
QCommonStyle::polish( widget );
}
//_______________________________________________________________
void Style::unpolish( QWidget* widget )
{
// register widget to animations
windowManager().unregisterWidget( widget );
frameShadowFactory().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<QGroupBox*>( widget ) )
{
if( groupBox->isCheckable() )
{ groupBox->setAttribute( Qt::WA_Hover, false ); }
}
// hover flags
if(
qobject_cast<QAbstractItemView*>( widget )
|| qobject_cast<QAbstractSpinBox*>( widget )
|| qobject_cast<QCheckBox*>( widget )
|| qobject_cast<QComboBox*>( widget )
|| qobject_cast<QDial*>( widget )
|| qobject_cast<QLineEdit*>( widget )
|| qobject_cast<QPushButton*>( widget )
|| qobject_cast<QRadioButton*>( widget )
|| qobject_cast<QScrollBar*>( widget )
|| qobject_cast<QSlider*>( widget )
|| qobject_cast<QSplitterHandle*>( widget )
|| qobject_cast<QTabBar*>( widget )
|| qobject_cast<QTextEdit*>( widget )
|| qobject_cast<QToolButton*>( widget )
)
{ widget->setAttribute( Qt::WA_Hover, false ); }
// checkable group boxes
if( QGroupBox* groupBox = qobject_cast<QGroupBox*>( widget ) )
{
if( groupBox->isCheckable() )
{ groupBox->setAttribute( Qt::WA_Hover, false ); }
}
if( qobject_cast<QMenuBar*>( widget )
|| qobject_cast<QToolBar*>( widget )
|| ( widget && qobject_cast<QToolBar *>( widget->parent() ) )
|| qobject_cast<QToolBox*>( widget ) )
{
widget->setBackgroundRole( QPalette::Button );
widget->removeEventFilter( this );
widget->clearMask();
}
if( qobject_cast<QTabBar*>( widget ) )
{
widget->removeEventFilter( this );
} else if( widget->inherits( "QTipLabel" ) ) {
widget->setAttribute( Qt::WA_NoSystemBackground, false );
widget->clearMask();
} else if( qobject_cast<QScrollBar*>( widget ) ) {
widget->setAttribute( Qt::WA_OpaquePaintEvent );
} else if( qobject_cast<QDockWidget*>( widget ) ) {
widget->setContentsMargins( 0,0,0,0 );
widget->clearMask();
} else if( qobject_cast<QToolBox*>( widget ) ) {
widget->setBackgroundRole( QPalette::Button );
widget->setContentsMargins( 0,0,0,0 );
widget->removeEventFilter( this );
} else if( qobject_cast<QMenu*>( widget ) ) {
widget->setAttribute( Qt::WA_NoSystemBackground, false );
widget->clearMask();
} else if( widget->inherits( "QComboBoxPrivateContainer" ) ) {
widget->removeEventFilter( this );
} else if( qobject_cast<QProgressBar*>( 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<const QLineEdit*>( widget ) ) return LineEdit_FrameWidth;
else if( qobject_cast<const QComboBox*>( widget ) ) return ComboBox_FrameWidth;
else if( qobject_cast<const QFrame*>( 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<const QStyleOptionGroupBox *>( 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<const QStyleOptionToolButton*>( 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;
// 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<const QFrame*>( 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<const QStyleOptionRubberBand *>( option );
if( !opt ) return false;
if( QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>( 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<const QAbstractItemView*>( widget->parent() ) ||
qobject_cast<const QGraphicsView*>( widget->parent() ) ||
qobject_cast<const QMainWindow*>( widget->parent() ) ) )
{ return true; }
// also check if widget's parent is some itemView viewport
if( widget && widget->parent() &&
qobject_cast<const QAbstractItemView*>( widget->parent()->parent() ) &&
static_cast<const QAbstractItemView*>( 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<QStyleHintReturnMask *>( 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;
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_PanelScrollAreaCorner: 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_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<QTabBar*>( object ) ) { return eventFilterTabBar( tabBar, event ); }
if( QToolBar* toolBar = qobject_cast<QToolBar*>( object ) ) { return eventFilterToolBar( toolBar, event ); }
if( QDockWidget* dockWidget = qobject_cast<QDockWidget*>( object ) ) { return eventFilterDockWidget( dockWidget, event ); }
if( QToolBox* toolBox = qobject_cast<QToolBox*>( object ) ) { return eventFilterToolBox( toolBox, event ); }
if( QScrollBar* scrollBar = qobject_cast<QScrollBar*>( object ) ) { return eventFilterScrollBar( scrollBar, event ); }
if( QProgressBar* progressBar = qobject_cast<QProgressBar*>( object ) ) { return eventFilterProgressBar( progressBar, event ); }
// cast to QWidget
QWidget *widget = static_cast<QWidget*>( 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<QPaintEvent*>( 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<QPaintEvent*>( 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::eventFilterScrollBar( QWidget* widget, QEvent* event )
{
if( event->type() == QEvent::Paint )
{
QPainter painter( widget );
painter.setClipRegion( static_cast<QPaintEvent*>( 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<QPaintEvent*>( 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<QPaintEvent*>( 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<QTimerEvent*>(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 QStyleOptionProgressBar *pbOpt( qstyleoption_cast<const QStyleOptionProgressBar *>( 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<const QStyleOptionTab*>( 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<const QStyleOptionTabWidgetFrame*>( 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<const QStyleOptionTabWidgetFrame*>( 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<const QStyleOptionTabWidgetFrame *>( option );
if( !tabOpt ) return QRect();
QRect r( option->rect );
const QRect paneRect( subElementRect( SE_TabWidgetTabPane, option, widget ) );
const QTabWidget* tabWidget( qobject_cast<const QTabWidget*>( 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<const QStyleOptionTabWidgetFrame *>( option );
if( !tabOpt ) return QRect();
QRect r( option->rect );
const QRect paneRect( subElementRect( SE_TabWidgetTabPane, option, widget ) );
const QTabWidget* tabWidget( qobject_cast<const QTabWidget*>( 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<const QStyleOptionGroupBox *>( option );
if( !gbOpt ) break;
const bool isFlat( gbOpt->features & QStyleOptionFrame::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<const QStyleOptionGroupBox *>( option );
if( !gbOpt ) break;
const bool isFlat( gbOpt->features & QStyleOptionFrame::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<const QStyleOptionComboBox *>( 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<const QStyleOptionSlider*>( 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<const QStyleOptionSpinBox *>( 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<const QStyleOptionComboBox *>( 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<const QStyleOptionHeader *>( 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<const QStyleOptionMenuItem*>( 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<const QStyleOptionButton*>( 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<const QStyleOptionTab*>( 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<const QTabWidget*>( 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<const QStyleOptionToolButton*>( 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<const QToolButton*>( 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<const QStyleOptionFrame *>( option );
if( !fOpt ) return true;
// no frame for flat groupboxes
if( fOpt->features & QStyleOptionFrame::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<const QToolBar*>( 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<const QStyleOptionTabBarBase*>( 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<const QStyleOptionTabWidgetFrame*>( 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<const QToolButton*>( 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<const QStyleOptionHeader *>( 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<const QTabBar*>( widget->parent() ) );
if( isInTabBar )
{
const QPalette& palette( option->palette );
QRect r( option->rect );
// adjust rect depending on shape
const QTabBar* tabBar( static_cast<const QTabBar*>( 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<const QDockWidget*>( 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<const QToolBar*>( 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<const QToolButton*>( 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 QStyleOptionViewItem *opt = qstyleoption_cast<const QStyleOptionViewItem*>( option );
const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>( 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 & QStyleOptionViewItem::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 & QStyleOptionViewItem::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 == QStyleOptionViewItem::Beginning );
roundedRight = ( opt->viewItemPosition == QStyleOptionViewItem::End );
if( opt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
opt->viewItemPosition == QStyleOptionViewItem::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<const QStyleOptionFrame*>( 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<const QStyleOptionMenuItem*>( 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::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<const QToolButton *>( 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<const QStyleOptionToolButton *>( 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<const QStyleOptionTab*>( option ) );
if( !tabOpt ) return true;
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const bool reverseLayout( option->direction == Qt::RightToLeft );
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<const QStyleOptionProgressBar*>( option ) );
if( !cbOption ) return true;
// draw container
QStyleOptionProgressBar 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<const QStyleOptionComboBox *>( 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<const QStyleOptionDockWidget*>( 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 );
const bool verticalTitleBar( dwOpt->verticalTitleBar );
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<const QStyleOptionHeader *>( 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<const QStyleOptionHeader *>( 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<const QStyleOptionMenuItem*>( 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<const QStyleOptionMenuItem*>( 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<const QStyleOptionProgressBar *>( option ) )
{
// same as QCommonStyle::drawControl, except that it handles animations
QStyleOptionProgressBar 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<const QStyleOptionProgressBar*>( option );
if ( !pbOpt ) return true;
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 = ( pbOpt->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 = 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 QStyleOptionProgressBar *pbOpt = qstyleoption_cast<const QStyleOptionProgressBar *>( 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<const QStyleOptionProgressBar*>( 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 bool horizontal = ( pbOpt->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<const QStyleOptionButton*>( 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<const QStyleOptionRubberBand *>( 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<const QStyleOptionSlider *>( 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<const QStyleOptionSlider*>( 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<const QStyleOptionSlider*>( 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<const QStyleOptionSlider*>( 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<const QStyleOptionSlider*>( 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 QStyleOptionFrame* frameOpt = qstyleoption_cast<const QStyleOptionFrame*>( 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;
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( tabOpt->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 ? tabOpt->rightButtonSize.isEmpty():tabOpt->leftButtonSize.isEmpty() ) );
const bool hasRightButton( !( option->direction == Qt::RightToLeft ? tabOpt->leftButtonSize.isEmpty():tabOpt->rightButtonSize.isEmpty() ) );
if( hasLeftButton )
{ r.setLeft( r.left() + 4 + ( verticalTabs ? tabOpt->leftButtonSize.height() : tabOpt->leftButtonSize.width() ) ); }
// make room for left and right widgets
// left widget
if( hasRightButton )
{ r.setRight( r.right() - 4 - ( verticalTabs ? tabOpt->rightButtonSize.height() : tabOpt->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( tabOpt->icon.isNull() )
{
textRect = r.adjusted( 6, 0, -6, 0 );
} else {
const QSize& iconSize( tabOpt->iconSize );
iconRect = centerRect( r, iconSize );
if( !tabOpt->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( tabOpt->shape == QTabBar::RoundedNorth || tabOpt->shape == QTabBar::TriangularNorth )
{ iconRect.translate( 0, -1 ); }
const QPixmap tabIcon = tabOpt->icon.pixmap(
tabOpt->iconSize,
( tabOpt->state & State_Enabled ) ? QIcon::Normal : QIcon::Disabled,
( tabOpt->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( tabOpt->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<const QStyleOptionTab*>( 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<const QTabBar*>( 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
bool documentMode = tabOpt->documentMode;
const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast<const QTabWidget *>( 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<const QStyleOptionTab*>( 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
bool documentMode = tabOpt->documentMode;
const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast<const QTabWidget *>( 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<const QTabBar*>( 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<const QTabBar*>( widget ) );
if( !tabBar ) return;
// get reverseLayout flag
const bool reverseLayout( tabOpt->direction == Qt::RightToLeft );
// get documentMode flag
bool documentMode = tabOpt->documentMode;
const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast<const QTabWidget *>( 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<const QStyleOptionToolBox *>( 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 and disable paint if tab is first
const QStyleOptionToolBox *toolBoxOption = qstyleoption_cast<const QStyleOptionToolBox *>( option );
if( toolBoxOption && toolBoxOption->position == QStyleOptionToolBox::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<QColor> 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<const QStyleOptionToolButton*>( 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<const QStyleOptionComboBox *>( 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<const QComboBox*>( 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<const QStyleOptionGroupBox *>( option );
if( groupBox && groupBox->features & QStyleOptionFrame::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<const QStyleOptionSlider *>( 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<const QStyleOptionSpinBox *>( 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<const QStyleOptionTitleBar *>( 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<const QStyleOptionToolButton *>( 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() );
// 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();
}
//____________________________________________________________________
QIcon Style::standardIcon(
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:
return QCommonStyle::standardIcon( standardIcon, option, widget );
}
}
//_____________________________________________________________
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<QWidget*> children( viewport->findChildren<QWidget*>() );
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<const QToolButton*>( 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<const QStyleOptionSlider*>( 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<const QStyleOptionMenuItem*>( 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<qreal> 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;
}
}