mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-23 18:32:50 +00:00
8778 lines
335 KiB
C++
8778 lines
335 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 "oxygenblurhelper.h"
|
|
#include "oxygenframeshadow.h"
|
|
#include "oxygenmdiwindowshadow.h"
|
|
#include "oxygenmnemonics.h"
|
|
#include "oxygenshadowhelper.h"
|
|
#include "oxygensplitterproxy.h"
|
|
#include "oxygenstyleconfigdata.h"
|
|
#include "oxygenwidgetexplorer.h"
|
|
#include "oxygenwindowmanager.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/QMdiSubWindow>
|
|
#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>
|
|
|
|
/* These are to link libkio even if 'smart' linker is used */
|
|
#include <kio/authinfo.h>
|
|
extern "C" KIO::AuthInfo* _oxygen_init_kio() { return new KIO::AuthInfo(); }
|
|
|
|
|
|
//_____________________________________________
|
|
// style plugin
|
|
namespace Oxygen
|
|
{
|
|
//! style plugin
|
|
class StylePlugin : public QStylePlugin
|
|
{
|
|
public:
|
|
|
|
//! returns list of valid keys
|
|
QStringList keys() const
|
|
{ return QStringList( QLatin1String( "Oxygen" ) ); }
|
|
|
|
//! create style
|
|
QStyle *create( const QString &key )
|
|
{
|
|
|
|
if( key.toLower() == QLatin1String( "oxygen" ) ) return new Style;
|
|
else return NULL;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
Q_EXPORT_PLUGIN2( oxygen-qt, Oxygen::StylePlugin )
|
|
|
|
namespace Oxygen
|
|
{
|
|
|
|
// hardcoded index offsets for custom widgets
|
|
// copied from e.g. kstyle.cxx
|
|
static const QStyle::StyleHint SH_KCustomStyleElement = ( QStyle::StyleHint )0xff000001;
|
|
static const int X_KdeBase = 0xff000000;
|
|
|
|
//_____________________________________________________________________
|
|
bool TopLevelManager::eventFilter( QObject *object, QEvent *event )
|
|
{
|
|
|
|
// cast to QWidget
|
|
QWidget *widget = static_cast<QWidget*>( object );
|
|
if( event->type() == QEvent::Show && _helper.hasDecoration( widget ) )
|
|
{
|
|
_helper.setHasBackgroundGradient( widget->winId(), true );
|
|
_helper.setHasBackgroundPixmap( widget->winId(), _helper.hasBackgroundPixmap() );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//______________________________________________________________
|
|
Style::Style( void ):
|
|
_kGlobalSettingsInitialized( false ),
|
|
_addLineButtons( DoubleButton ),
|
|
_subLineButtons( SingleButton ),
|
|
_singleButtonHeight( 14 ),
|
|
_doubleButtonHeight( 28 ),
|
|
_helper( new StyleHelper( "oxygen" ) ),
|
|
_shadowHelper( new ShadowHelper( this, *_helper ) ),
|
|
_windowManager( new WindowManager( this ) ),
|
|
_topLevelManager( new TopLevelManager( this, *_helper ) ),
|
|
_frameShadowFactory( new FrameShadowFactory( this ) ),
|
|
_mdiWindowShadowFactory( new MdiWindowShadowFactory( this, *_helper ) ),
|
|
_mnemonics( new Mnemonics( this ) ),
|
|
_blurHelper( new BlurHelper( this, helper() ) ),
|
|
_widgetExplorer( new WidgetExplorer( this ) ),
|
|
_tabBarData( new TabBarData( this ) ),
|
|
_splitterFactory( new SplitterFactory( this ) ),
|
|
_frameFocusPrimitive( 0 ),
|
|
_tabBarTabShapeControl( 0 ),
|
|
_hintCounter( X_KdeBase+1 ),
|
|
_controlCounter( X_KdeBase ),
|
|
_subElementCounter( X_KdeBase ),
|
|
SH_ArgbDndWindow( newStyleHint( "SH_ArgbDndWindow" ) ),
|
|
CE_CapacityBar( newControlElement( "CE_CapacityBar" ) )
|
|
|
|
{
|
|
|
|
// use DBus connection to update on oxygen configuration change
|
|
QDBusConnection dbus = QDBusConnection::sessionBus();
|
|
dbus.connect( QString(), "/OxygenStyle", "org.kde.Oxygen.Style", "reparseConfiguration", this, SLOT(oxygenConfigurationChanged()) );
|
|
|
|
// call the slot directly; this initial call will set up things that also
|
|
// need to be reset when the system palette changes
|
|
oxygenConfigurationChanged();
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
Style::~Style( void )
|
|
{ delete _helper; }
|
|
|
|
//______________________________________________________________
|
|
void Style::polish( QWidget* widget )
|
|
{
|
|
if( !widget ) return;
|
|
|
|
// register widget to animations
|
|
windowManager().registerWidget( widget );
|
|
frameShadowFactory().registerWidget( widget, helper() );
|
|
mdiWindowShadowFactory().registerWidget( widget );
|
|
shadowHelper().registerWidget( widget );
|
|
splitterFactory().registerWidget( widget );
|
|
|
|
// scroll areas
|
|
if( QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>( widget ) )
|
|
{
|
|
|
|
polishScrollArea( scrollArea );
|
|
|
|
}
|
|
|
|
// several widgets set autofill background to false, which effectively breaks the background
|
|
// gradient rendering. Instead of patching all concerned applications,
|
|
// we change the background here
|
|
if( widget->inherits( "MessageList::Core::Widget" ) )
|
|
{ widget->setAutoFillBackground( false ); }
|
|
|
|
// 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 layout for K3B themed headers
|
|
// FIXME: to be removed when fixed upstream
|
|
if( widget->inherits( "K3b::ThemedHeader" ) && widget->layout() )
|
|
{
|
|
widget->layout()->setMargin( 0 );
|
|
frameShadowFactory().setHasContrast( widget, true );
|
|
}
|
|
|
|
// adjust flags for windows and dialogs
|
|
switch( widget->windowFlags() & Qt::WindowType_Mask )
|
|
{
|
|
|
|
case Qt::Window:
|
|
case Qt::Dialog:
|
|
|
|
// set background as styled
|
|
widget->setAttribute( Qt::WA_StyledBackground );
|
|
widget->installEventFilter( _topLevelManager );
|
|
|
|
// 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<QMdiSubWindow*>( widget ) ) {
|
|
|
|
widget->setAutoFillBackground( false );
|
|
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 );
|
|
|
|
}
|
|
|
|
// base class polishing
|
|
QCommonStyle::polish( widget );
|
|
|
|
}
|
|
|
|
//_______________________________________________________________
|
|
void Style::unpolish( QWidget* widget )
|
|
{
|
|
|
|
// register widget to animations
|
|
windowManager().unregisterWidget( widget );
|
|
frameShadowFactory().unregisterWidget( widget );
|
|
mdiWindowShadowFactory().unregisterWidget( widget );
|
|
shadowHelper().unregisterWidget( widget );
|
|
splitterFactory().unregisterWidget( widget );
|
|
blurHelper().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_PaintOnScreen, false );
|
|
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_PaintOnScreen, false );
|
|
widget->setAttribute( Qt::WA_NoSystemBackground, false );
|
|
widget->clearMask();
|
|
|
|
} else if( widget->inherits( "QComboBoxPrivateContainer" ) ) 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;
|
|
#ifndef QT_KATIE
|
|
case PM_CheckListControllerSize: return CheckBox_Size;
|
|
case PM_CheckListButtonSize: return CheckBox_Size;
|
|
#endif
|
|
|
|
// splitters and dock widgets
|
|
case PM_SplitterWidth: return Splitter_Width;
|
|
case PM_DockWidgetFrameWidth: return DockWidget_FrameWidth;
|
|
case PM_DockWidgetSeparatorExtent: return DockWidget_SeparatorExtend;
|
|
case PM_DockWidgetTitleMargin: return DockWidget_TitleMargin;
|
|
|
|
// progress bar
|
|
case PM_ProgressBarChunkWidth: return 1;
|
|
|
|
// menu bars
|
|
case PM_MenuBarPanelWidth: return 0;
|
|
case PM_MenuBarHMargin: return 0;
|
|
case PM_MenuBarVMargin: return 0;
|
|
case PM_MenuBarItemSpacing: return 0;
|
|
case PM_MenuDesktopFrameWidth: return 0;
|
|
case PM_MenuPanelWidth: return 5;
|
|
|
|
case PM_MenuScrollerHeight: return 10;
|
|
case PM_MenuTearoffHeight: return 10;
|
|
|
|
// tabbars
|
|
case PM_TabBarTabHSpace: return 0;
|
|
case PM_TabBarTabVSpace: return 0;
|
|
case PM_TabBarBaseHeight: return TabBar_BaseHeight;
|
|
case PM_TabBarBaseOverlap: return TabBar_BaseOverlap;
|
|
case PM_TabBarTabOverlap: return 0;
|
|
case PM_TabBarScrollButtonWidth: return TabBar_ScrollButtonWidth;
|
|
|
|
/*
|
|
disable shifts: return because last time I checked it did not work well
|
|
for South and East tabs. Instead the shifts are added directly in
|
|
drawTabBarTabLabel. ( Hugo )
|
|
*/
|
|
case PM_TabBarTabShiftVertical: return 0;
|
|
case PM_TabBarTabShiftHorizontal: return 0;
|
|
|
|
// sliders
|
|
case PM_SliderThickness: return 23;
|
|
case PM_SliderControlThickness: return 23;
|
|
case PM_SliderLength: return 21;
|
|
|
|
// spinboxes
|
|
case PM_SpinBoxFrameWidth: return SpinBox_FrameWidth;
|
|
|
|
// comboboxes
|
|
case PM_ComboBoxFrameWidth: return ComboBox_FrameWidth;
|
|
|
|
// tree view header
|
|
case PM_HeaderMarkSize: return 9;
|
|
case PM_HeaderMargin: return 3;
|
|
|
|
// toolbars
|
|
case PM_ToolBarFrameWidth: return 0;
|
|
case PM_ToolBarHandleExtent: return 6;
|
|
case PM_ToolBarSeparatorExtent: return 6;
|
|
|
|
case PM_ToolBarExtensionExtent: return 16;
|
|
|
|
case PM_ToolBarItemMargin: return 0;
|
|
case PM_ToolBarItemSpacing: return 1;
|
|
|
|
// MDI windows titlebars
|
|
case PM_TitleBarHeight: return 20;
|
|
|
|
// spacing between widget and scrollbars
|
|
case PM_ScrollView_ScrollBarSpacing:
|
|
if( const QFrame* frame = qobject_cast<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 );
|
|
return false;
|
|
|
|
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;
|
|
#ifndef QT_KATIE
|
|
case SH_DialogButtonLayout: return QDialogButtonBox::KdeLayout;
|
|
#endif
|
|
case SH_ScrollBar_MiddleClickAbsolutePosition: return true;
|
|
case SH_ItemView_ShowDecorationSelected: return false;
|
|
case SH_ItemView_ArrowKeysNavigateIntoChildren: return true;
|
|
case SH_ScrollView_FrameOnlyAroundContents: return true;
|
|
case SH_FormLayoutFormAlignment: return Qt::AlignLeft | Qt::AlignTop;
|
|
case SH_FormLayoutLabelAlignment: return Qt::AlignRight;
|
|
case SH_FormLayoutFieldGrowthPolicy: return QFormLayout::ExpandingFieldsGrow;
|
|
case SH_FormLayoutWrapPolicy: return QFormLayout::DontWrapRows;
|
|
case SH_MessageBox_TextInteractionFlags: return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse;
|
|
case SH_WindowFrame_Mask: return false;
|
|
case SH_RequestSoftwareInputPanel: return RSIP_OnMouseClick;
|
|
|
|
case SH_ProgressDialog_CenterCancelButton:
|
|
case SH_MessageBox_CenterButtons:
|
|
return false;
|
|
|
|
default: return QCommonStyle::styleHint( hint, option, widget, returnData );
|
|
}
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
QRect Style::subElementRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const
|
|
{
|
|
|
|
|
|
switch( element )
|
|
{
|
|
|
|
// push buttons
|
|
case SE_PushButtonContents: return pushButtonContentsRect( option, widget );
|
|
case SE_PushButtonFocusRect: return defaultSubElementRect( option, widget );
|
|
|
|
// checkboxes
|
|
case SE_CheckBoxContents: return checkBoxContentsRect( option, widget );
|
|
case SE_CheckBoxFocusRect: return defaultSubElementRect( option, widget );
|
|
|
|
// progress bars
|
|
case SE_ProgressBarGroove: return defaultSubElementRect( option, widget );
|
|
case SE_ProgressBarContents: return progressBarContentsRect( option, widget );
|
|
case SE_ProgressBarLabel: return defaultSubElementRect( option, widget );
|
|
|
|
// radio buttons
|
|
case SE_RadioButtonContents: return checkBoxContentsRect( option, widget );
|
|
case SE_RadioButtonFocusRect: return defaultSubElementRect( option, widget );
|
|
|
|
// tab widget
|
|
case SE_TabBarTabLeftButton: return tabBarTabLeftButtonRect( option, widget );
|
|
case SE_TabBarTabRightButton: return tabBarTabRightButtonRect( option, widget );
|
|
case SE_TabBarTabText: return tabBarTabTextRect( option, widget );
|
|
case SE_TabWidgetTabContents: return tabWidgetTabContentsRect( option, widget );
|
|
case SE_TabWidgetTabPane: return tabWidgetTabPaneRect( option, widget );
|
|
case SE_TabWidgetLeftCorner: return tabWidgetLeftCornerRect( option, widget );
|
|
case SE_TabWidgetRightCorner: return tabWidgetRightCornerRect( option, widget );
|
|
|
|
// toolboxes
|
|
case SE_ToolBoxTabContents: return toolBoxTabContentsRect( option, widget );
|
|
|
|
default: return QCommonStyle::subElementRect( element, option, widget );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
QRect Style::subControlRect( ComplexControl element, const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const
|
|
{
|
|
|
|
switch( element )
|
|
{
|
|
|
|
case CC_GroupBox: return groupBoxSubControlRect( option, subControl, widget );
|
|
case CC_ComboBox: return comboBoxSubControlRect( option, subControl, widget );
|
|
case CC_ScrollBar: return scrollBarSubControlRect( option, subControl, widget );
|
|
case CC_SpinBox: return spinBoxSubControlRect( option, subControl, widget );
|
|
default: return QCommonStyle::subControlRect( element, option, subControl, widget );
|
|
}
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
QSize Style::sizeFromContents( ContentsType element, const QStyleOption* option, const QSize& size, const QWidget* widget ) const
|
|
{
|
|
|
|
switch( element )
|
|
{
|
|
case CT_CheckBox: return checkBoxSizeFromContents( option, size, widget );
|
|
case CT_ComboBox: return comboBoxSizeFromContents( option, size, widget );
|
|
case CT_HeaderSection: return headerSectionSizeFromContents( option, size, widget );
|
|
case CT_PushButton: return pushButtonSizeFromContents( option, size, widget );
|
|
case CT_MenuBar: return menuBarSizeFromContents( option, size, widget );
|
|
case CT_MenuBarItem: return menuBarItemSizeFromContents( option, size, widget );
|
|
case CT_MenuItem: return menuItemSizeFromContents( option, size, widget );
|
|
case CT_RadioButton: return checkBoxSizeFromContents( option, size, widget );
|
|
case CT_TabBarTab: return tabBarTabSizeFromContents( option, size, widget );
|
|
case CT_TabWidget: return tabWidgetSizeFromContents( option, size, widget );
|
|
case CT_ToolButton: return toolButtonSizeFromContents( option, size, widget );
|
|
default: return QCommonStyle::sizeFromContents( element, option, size, widget );
|
|
}
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
QStyle::SubControl Style::hitTestComplexControl( ComplexControl control, const QStyleOptionComplex* option, const QPoint& point, const QWidget* widget ) const
|
|
{
|
|
switch( control )
|
|
{
|
|
case CC_ScrollBar:
|
|
{
|
|
|
|
QRect groove = scrollBarSubControlRect( option, SC_ScrollBarGroove, widget );
|
|
if ( groove.contains( point ) )
|
|
{
|
|
//Must be either page up/page down, or just click on the slider.
|
|
//Grab the slider to compare
|
|
QRect slider = scrollBarSubControlRect( option, SC_ScrollBarSlider, widget );
|
|
|
|
if( slider.contains( point ) ) return SC_ScrollBarSlider;
|
|
else if( preceeds( point, slider, option ) ) return SC_ScrollBarSubPage;
|
|
else return SC_ScrollBarAddPage;
|
|
|
|
}
|
|
|
|
//This is one of the up/down buttons. First, decide which one it is.
|
|
if( preceeds( point, groove, option ) )
|
|
{
|
|
|
|
if( _subLineButtons == DoubleButton )
|
|
{
|
|
QRect buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarSubLine );
|
|
return scrollBarHitTest( buttonRect, point, option );
|
|
} else return SC_ScrollBarSubLine;
|
|
|
|
}
|
|
|
|
if( _addLineButtons == DoubleButton )
|
|
{
|
|
|
|
QRect buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarAddLine );
|
|
return scrollBarHitTest( buttonRect, point, option );
|
|
|
|
} else return SC_ScrollBarAddLine;
|
|
}
|
|
|
|
default: return QCommonStyle::hitTestComplexControl( control, option, point, widget );
|
|
}
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
void Style::drawPrimitive( PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
painter->save();
|
|
|
|
StylePrimitive fcn( 0 );
|
|
switch( element )
|
|
{
|
|
|
|
// register primitives for which nothing is done
|
|
case PE_FrameStatusBar: fcn = &Style::emptyPrimitive; break;
|
|
|
|
case PE_Frame: fcn = &Style::drawFramePrimitive; break;
|
|
|
|
// frame focus primitive is set at run time, in oxygenConfigurationChanged
|
|
case PE_FrameFocusRect: fcn = _frameFocusPrimitive; break;
|
|
|
|
case PE_FrameGroupBox: fcn = &Style::drawFrameGroupBoxPrimitive; break;
|
|
case PE_FrameLineEdit: fcn = &Style::drawFramePrimitive; break;
|
|
case PE_FrameMenu: fcn = &Style::drawFrameMenuPrimitive; break;
|
|
|
|
// TabBar
|
|
case PE_FrameTabBarBase: fcn = &Style::drawFrameTabBarBasePrimitive; break;
|
|
case PE_FrameTabWidget: fcn = &Style::drawFrameTabWidgetPrimitive; break;
|
|
case PE_FrameWindow: fcn = &Style::drawFrameWindowPrimitive; break;
|
|
case PE_IndicatorTabClose: fcn = &Style::drawIndicatorTabClose; break;
|
|
|
|
// arrows
|
|
case PE_IndicatorArrowUp: fcn = &Style::drawIndicatorArrowUpPrimitive; break;
|
|
case PE_IndicatorArrowDown: fcn = &Style::drawIndicatorArrowDownPrimitive; break;
|
|
case PE_IndicatorArrowLeft: fcn = &Style::drawIndicatorArrowLeftPrimitive; break;
|
|
case PE_IndicatorArrowRight: fcn = &Style::drawIndicatorArrowRightPrimitive; break;
|
|
|
|
case PE_IndicatorDockWidgetResizeHandle: fcn = &Style::drawIndicatorDockWidgetResizeHandlePrimitive; break;
|
|
case PE_IndicatorHeaderArrow: fcn = &Style::drawIndicatorHeaderArrowPrimitive; break;
|
|
|
|
case PE_PanelButtonCommand: fcn = &Style::drawPanelButtonCommandPrimitive; break;
|
|
case PE_PanelButtonTool: fcn = &Style::drawPanelButtonToolPrimitive; break;
|
|
|
|
case PE_PanelItemViewItem: fcn = &Style::drawPanelItemViewItemPrimitive; break;
|
|
case PE_PanelLineEdit: fcn = &Style::drawPanelLineEditPrimitive; break;
|
|
case PE_PanelMenu: fcn = &Style::drawPanelMenuPrimitive; break;
|
|
case PE_PanelScrollAreaCorner: fcn = &Style::drawPanelScrollAreaCornerPrimitive; break;
|
|
case PE_PanelTipLabel: fcn = &Style::drawPanelTipLabelPrimitive; break;
|
|
|
|
case PE_IndicatorMenuCheckMark: fcn = &Style::drawIndicatorMenuCheckMarkPrimitive; break;
|
|
case PE_IndicatorBranch: fcn = &Style::drawIndicatorBranchPrimitive; break;
|
|
case PE_IndicatorButtonDropDown: fcn = &Style::drawIndicatorButtonDropDownPrimitive; break;
|
|
case PE_IndicatorCheckBox: fcn = &Style::drawIndicatorCheckBoxPrimitive; break;
|
|
case PE_IndicatorRadioButton: fcn = &Style::drawIndicatorRadioButtonPrimitive; break;
|
|
case PE_IndicatorTabTear: fcn = &Style::drawIndicatorTabTearPrimitive; break;
|
|
case PE_IndicatorToolBarHandle: fcn = &Style::drawIndicatorToolBarHandlePrimitive; break;
|
|
case PE_IndicatorToolBarSeparator: fcn = &Style::drawIndicatorToolBarSeparatorPrimitive; break;
|
|
|
|
case PE_Widget: fcn = &Style::drawWidgetPrimitive; break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
// try find primitive in map, and run.
|
|
// exit if result is true, otherwise fallback to generic case
|
|
if( !( fcn && ( this->*fcn )( option, painter, widget ) ) )
|
|
{ QCommonStyle::drawPrimitive( element, option, painter, widget ); }
|
|
|
|
painter->restore();
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
void Style::drawControl( ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
painter->save();
|
|
|
|
StyleControl fcn( 0 );
|
|
if( element == CE_CapacityBar )
|
|
{
|
|
|
|
fcn = &Style::drawCapacityBarControl;
|
|
|
|
} else switch( element ) {
|
|
|
|
case CE_ComboBoxLabel: fcn = &Style::drawComboBoxLabelControl; break;
|
|
case CE_DockWidgetTitle: fcn = &Style::drawDockWidgetTitleControl; break;
|
|
case CE_HeaderEmptyArea: fcn = &Style::drawHeaderEmptyAreaControl; break;
|
|
case CE_HeaderLabel: fcn = &Style::drawHeaderLabelControl; break;
|
|
case CE_HeaderSection: fcn = &Style::drawHeaderSectionControl; break;
|
|
case CE_MenuBarEmptyArea: fcn = &Style::emptyControl; break;
|
|
case CE_MenuBarItem: fcn = &Style::drawMenuBarItemControl; break;
|
|
case CE_MenuItem: fcn = &Style::drawMenuItemControl; break;
|
|
case CE_ProgressBar: fcn = &Style::drawProgressBarControl; break;
|
|
case CE_ProgressBarContents: fcn = &Style::drawProgressBarContentsControl; break;
|
|
case CE_ProgressBarGroove: fcn = &Style::drawProgressBarGrooveControl; break;
|
|
case CE_ProgressBarLabel: fcn = &Style::drawProgressBarLabelControl; break;
|
|
|
|
/*
|
|
for CE_PushButtonBevel the only thing that is done is draw the PanelButtonCommand primitive
|
|
since the prototypes are identical we register the second directly in the control map: fcn = without
|
|
using an intermediate function
|
|
*/
|
|
case CE_PushButtonBevel: fcn = &Style::drawPanelButtonCommandPrimitive; break;
|
|
case CE_PushButtonLabel: fcn = &Style::drawPushButtonLabelControl; break;
|
|
|
|
case CE_RubberBand: fcn = &Style::drawRubberBandControl; break;
|
|
case CE_ScrollBarSlider: fcn = &Style::drawScrollBarSliderControl; break;
|
|
case CE_ScrollBarAddLine: fcn = &Style::drawScrollBarAddLineControl; break;
|
|
case CE_ScrollBarAddPage: fcn = &Style::drawScrollBarAddPageControl; break;
|
|
case CE_ScrollBarSubLine: fcn = &Style::drawScrollBarSubLineControl; break;
|
|
case CE_ScrollBarSubPage: fcn = &Style::drawScrollBarSubPageControl; break;
|
|
|
|
case CE_ShapedFrame: fcn = &Style::drawShapedFrameControl; break;
|
|
case CE_SizeGrip: fcn = &Style::drawSizeGripControl; break;
|
|
case CE_Splitter: fcn = &Style::drawSplitterControl; break;
|
|
case CE_TabBarTabLabel: fcn = &Style::drawTabBarTabLabelControl; break;
|
|
|
|
// default tab style is 'SINGLE'
|
|
case CE_TabBarTabShape: fcn = _tabBarTabShapeControl; break;
|
|
|
|
case CE_ToolBoxTabLabel: fcn = &Style::drawToolBoxTabLabelControl; break;
|
|
case CE_ToolBoxTabShape: fcn = &Style::drawToolBoxTabShapeControl; break;
|
|
case CE_ToolButtonLabel: fcn = &Style::drawToolButtonLabelControl; break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
if( !( fcn && ( this->*fcn )( option, painter, widget ) ) )
|
|
{ QCommonStyle::drawControl( element, option, painter, widget ); }
|
|
|
|
painter->restore();
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
void Style::drawComplexControl( ComplexControl element, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
painter->save();
|
|
|
|
StyleComplexControl fcn( 0 );
|
|
switch( element )
|
|
{
|
|
|
|
case CC_ComboBox: fcn = &Style::drawComboBoxComplexControl; break;
|
|
case CC_Dial: fcn = &Style::drawDialComplexControl; break;
|
|
case CC_GroupBox: fcn = &Style::drawGroupBoxComplexControl; break;
|
|
case CC_Slider: fcn = &Style::drawSliderComplexControl; break;
|
|
case CC_SpinBox: fcn = &Style::drawSpinBoxComplexControl; break;
|
|
case CC_TitleBar: fcn = &Style::drawTitleBarComplexControl; break;
|
|
case CC_ToolButton: fcn = &Style::drawToolButtonComplexControl; break;
|
|
default: break;
|
|
|
|
}
|
|
|
|
if( !( fcn && ( this->*fcn )( option, painter, widget ) ) )
|
|
{ QCommonStyle::drawComplexControl( element, option, painter, widget ); }
|
|
|
|
painter->restore();
|
|
|
|
}
|
|
|
|
|
|
//___________________________________________________________________________________
|
|
void Style::drawItemText(
|
|
QPainter* painter, const QRect& r, int flags, const QPalette& palette, bool enabled,
|
|
const QString &text, QPalette::ColorRole textRole ) const
|
|
{
|
|
|
|
// hide mnemonics if requested
|
|
if( !mnemonics().enabled() && ( flags & Qt::TextShowMnemonic ) && !( flags&Qt::TextHideMnemonic ) )
|
|
{
|
|
flags &= ~Qt::TextShowMnemonic;
|
|
flags |= Qt::TextHideMnemonic;
|
|
}
|
|
|
|
return QCommonStyle::drawItemText( painter, r, flags, palette, enabled, text, textRole );
|
|
|
|
}
|
|
|
|
|
|
//_____________________________________________________________________
|
|
bool Style::eventFilter( QObject *object, QEvent *event )
|
|
{
|
|
|
|
if( QTabBar* tabBar = qobject_cast<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( QMdiSubWindow* subWindow = qobject_cast<QMdiSubWindow*>( object ) ) { return eventFilterMdiSubWindow( subWindow, event ); }
|
|
if( QScrollBar* scrollBar = qobject_cast<QScrollBar*>( object ) ) { return eventFilterScrollBar( scrollBar, 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::eventFilterMdiSubWindow( QMdiSubWindow* subWindow, QEvent* event )
|
|
{
|
|
|
|
if( event->type() == QEvent::Paint )
|
|
{
|
|
|
|
QPainter painter( subWindow );
|
|
QRect clip( static_cast<QPaintEvent*>( event )->rect() );
|
|
if( subWindow->isMaximized() ) helper().renderWindowBackground( &painter, clip, subWindow, subWindow->palette() );
|
|
else {
|
|
|
|
painter.setClipRect( clip );
|
|
|
|
const QRect r( subWindow->rect() );
|
|
TileSet *tileSet( helper().roundCorner( subWindow->palette().color( subWindow->backgroundRole() ) ) );
|
|
tileSet->render( r, &painter );
|
|
|
|
painter.setClipRegion( helper().roundedMask( r.adjusted( 1, 1, -1, -1 ) ), Qt::IntersectClip );
|
|
helper().renderWindowBackground( &painter, clip, subWindow, subWindow, subWindow->palette(), 0, 58 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// continue with normal painting
|
|
return false;
|
|
|
|
}
|
|
|
|
//_________________________________________________________
|
|
bool Style::eventFilterScrollBar( QWidget* widget, QEvent* event )
|
|
{
|
|
|
|
if( event->type() == QEvent::Paint )
|
|
{
|
|
QPainter painter( widget );
|
|
painter.setClipRegion( static_cast<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;
|
|
}
|
|
|
|
//____________________________________________________________________
|
|
QRect Style::progressBarContentsRect( const QStyleOption* option, const QWidget* ) const
|
|
{
|
|
const QRect out( insideMargin( option->rect, ProgressBar_GrooveMargin ) );
|
|
const QStyleOptionProgressBarV2 *pbOpt( qstyleoption_cast<const QStyleOptionProgressBarV2 *>( 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 & QStyleOptionFrameV2::Flat );
|
|
const int th( gbOpt->fontMetrics.height() + 8 );
|
|
const QRect cr( subElementRect( SE_CheckBoxIndicator, option, widget ) );
|
|
const int fw( pixelMetric( PM_DefaultFrameWidth, option, widget ) );
|
|
const bool checkable( gbOpt->subControls & QStyle::SC_GroupBoxCheckBox );
|
|
const bool emptyText( gbOpt->text.isEmpty() );
|
|
|
|
r.adjust( fw, fw, -fw, -fw );
|
|
if( checkable && !emptyText ) r.adjust( 0, qMax( th, cr.height() ), 0, 0 );
|
|
else if( checkable ) r.adjust( 0, cr.height(), 0, 0 );
|
|
else if( !emptyText ) r.adjust( 0, th, 0, 0 );
|
|
|
|
// add additional indentation to flat group boxes
|
|
if( isFlat )
|
|
{
|
|
const int leftMarginExtension( 16 );
|
|
r = visualRect( option->direction, r, r.adjusted( leftMarginExtension,0,0,0 ) );
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
case SC_GroupBoxCheckBox:
|
|
case SC_GroupBoxLabel:
|
|
{
|
|
// cast option and check
|
|
const QStyleOptionGroupBox *gbOpt = qstyleoption_cast<const QStyleOptionGroupBox *>( option );
|
|
if( !gbOpt ) break;
|
|
|
|
const bool isFlat( gbOpt->features & QStyleOptionFrameV2::Flat );
|
|
QFont font;
|
|
if (widget) {
|
|
font = widget->font();
|
|
} else {
|
|
font = QApplication::font();
|
|
}
|
|
// calculate text width assuming bold text in flat group boxes
|
|
if( isFlat ) font.setBold( true );
|
|
|
|
QFontMetrics fontMetrics = QFontMetrics( font );
|
|
const int h( fontMetrics.height() );
|
|
const int tw( fontMetrics.size( Qt::TextShowMnemonic, gbOpt->text + QLatin1String( " " ) ).width() );
|
|
r.setHeight( h );
|
|
|
|
// translate down by 6 pixels in non flat mode,
|
|
// to avoid collision with groupbox frame
|
|
if( !isFlat ) r.moveTop( 6 );
|
|
|
|
QRect cr;
|
|
if( gbOpt->subControls & QStyle::SC_GroupBoxCheckBox )
|
|
{
|
|
cr = subElementRect( SE_CheckBoxIndicator, option, widget );
|
|
QRect gcr( ( gbOpt->rect.width() - tw -cr.width() )/2 , ( h-cr.height() )/2+r.y(), cr.width(), cr.height() );
|
|
if( subControl == SC_GroupBoxCheckBox )
|
|
{
|
|
if( !isFlat ) return visualRect( option->direction, option->rect, gcr );
|
|
else return visualRect( option->direction, option->rect, QRect( 0,0,cr.width(),cr.height() ) );
|
|
}
|
|
}
|
|
|
|
// left align labels in flat group boxes, center align labels in framed group boxes
|
|
if( isFlat ) r = QRect( cr.width(),r.y(),tw,r.height() );
|
|
else r = QRect( ( gbOpt->rect.width() - tw - cr.width() )/2 + cr.width(), r.y(), tw, r.height() );
|
|
|
|
return visualRect( option->direction, option->rect, r );
|
|
}
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
return QCommonStyle::subControlRect( CC_GroupBox, option, subControl, widget );
|
|
}
|
|
|
|
//___________________________________________________________________________________________________________________
|
|
QRect Style::comboBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const
|
|
{
|
|
|
|
const QRect& r( option->rect );
|
|
const QStyleOptionComboBox *cb = qstyleoption_cast<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
|
|
QStyleOptionFrameV2 fOpt2( *fOpt );
|
|
if( fOpt2.features & QStyleOptionFrameV2::Flat ) return true;
|
|
|
|
// normal frame
|
|
const QPalette& palette( option->palette );
|
|
const QRect& r( option->rect );
|
|
const QColor base( helper().backgroundColor( palette.color( QPalette::Window ), widget, r.center() ) );
|
|
|
|
painter->save();
|
|
painter->setRenderHint( QPainter::Antialiasing );
|
|
painter->setPen( Qt::NoPen );
|
|
|
|
QLinearGradient innerGradient( 0, r.top()-r.height()+12, 0, r.bottom()+r.height()-19 );
|
|
QColor light( helper().calcLightColor( base ) );
|
|
light.setAlphaF( 0.4 ); innerGradient.setColorAt( 0.0, light );
|
|
light.setAlphaF( 0.0 ); innerGradient.setColorAt( 1.0, light );
|
|
painter->setBrush( innerGradient );
|
|
painter->setClipRect( r.adjusted( 0, 0, 0, -19 ) );
|
|
helper().fillSlab( *painter, r );
|
|
|
|
painter->setClipping( false );
|
|
helper().slope( base, 0.0 )->render( r, painter );
|
|
|
|
painter->restore();
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawFrameMenuPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
// only draw frame for ( expanded ) toolbars
|
|
// do nothing for other cases
|
|
if( qobject_cast<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 QStyleOptionViewItemV4 *opt = qstyleoption_cast<const QStyleOptionViewItemV4*>( 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 & QStyleOptionViewItemV2::Alternate ) )
|
|
{ return true; }
|
|
|
|
QPalette::ColorGroup cg;
|
|
if( option->state & State_Enabled ) cg = ( option->state & State_Active ) ? QPalette::Normal : QPalette::Inactive;
|
|
else cg = QPalette::Disabled;
|
|
|
|
QColor color;
|
|
if( hasCustomBackground && hasSolidBackground ) color = opt->backgroundBrush.color();
|
|
else color = option->palette.color( cg, QPalette::Highlight );
|
|
|
|
if( hover && !hasCustomBackground )
|
|
{
|
|
if( !( option->state & State_Selected ) ) color.setAlphaF( 0.2 );
|
|
else color = color.lighter( 110 );
|
|
}
|
|
|
|
if( opt && ( opt->features & QStyleOptionViewItemV2::Alternate ) )
|
|
{ painter->fillRect( option->rect, option->palette.brush( cg, QPalette::AlternateBase ) ); }
|
|
|
|
if( !hover && !( option->state & State_Selected ) && !hasCustomBackground )
|
|
{ return true; }
|
|
|
|
if( hasCustomBackground && !hasSolidBackground )
|
|
{
|
|
|
|
const QPointF oldBrushOrigin = painter->brushOrigin();
|
|
painter->setBrushOrigin( opt->rect.topLeft() );
|
|
painter->setBrush( opt->backgroundBrush );
|
|
painter->setPen( Qt::NoPen );
|
|
painter->drawRect( opt->rect );
|
|
painter->setBrushOrigin( oldBrushOrigin );
|
|
|
|
} else {
|
|
|
|
// get selection tileset
|
|
QRect r = option->rect;
|
|
TileSet *tileSet( helper().selection( color, r.height(), hasCustomBackground ) );
|
|
|
|
bool roundedLeft = false;
|
|
bool roundedRight = false;
|
|
if( opt )
|
|
{
|
|
|
|
roundedLeft = ( opt->viewItemPosition == QStyleOptionViewItemV4::Beginning );
|
|
roundedRight = ( opt->viewItemPosition == QStyleOptionViewItemV4::End );
|
|
if( opt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne ||
|
|
opt->viewItemPosition == QStyleOptionViewItemV4::Invalid ||
|
|
( view && view->selectionBehavior() != QAbstractItemView::SelectRows ) )
|
|
{
|
|
roundedLeft = true;
|
|
roundedRight = true;
|
|
}
|
|
|
|
}
|
|
|
|
const bool reverseLayout( option->direction == Qt::RightToLeft );
|
|
|
|
TileSet::Tiles tiles( TileSet::Center );
|
|
if( !reverseLayout ? roundedLeft : roundedRight ) tiles |= TileSet::Left;
|
|
else r.adjust( -8, 0, 0, 0 );
|
|
|
|
if( !reverseLayout ? roundedRight : roundedLeft ) tiles |= TileSet::Right;
|
|
else r.adjust( 0, 0, 8, 0 );
|
|
|
|
if( r.isValid() ) tileSet->render( r, painter, tiles );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawPanelLineEditPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
const QRect& r( option->rect );
|
|
const QPalette& palette( option->palette );
|
|
|
|
// cast option and check
|
|
const QStyleOptionFrame *panel = qstyleoption_cast<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::drawPanelScrollAreaCornerPrimitive( const QStyleOption*, QPainter*, const QWidget* widget ) const
|
|
{
|
|
// disable painting of PE_PanelScrollAreaCorner
|
|
// the default implementation fills the rect with the window background color
|
|
// which does not work for windows that have gradients.
|
|
// unfortunately, this does not work when scrollbars are children of QWebView,
|
|
// in which case, false is returned, in order to fall back to the parent style implementation
|
|
return !( widget && widget->inherits( "QWebView" ) );
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawPanelTipLabelPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
// force registration of widget
|
|
if( widget && widget->window() )
|
|
{ shadowHelper().registerWidget( widget->window(), true ); }
|
|
|
|
// parent style painting if frames should not be styled
|
|
if( !StyleConfigData::toolTipDrawStyledFrames() ) return false;
|
|
|
|
const QRect& r( option->rect );
|
|
const QColor color( option->palette.brush( QPalette::ToolTipBase ).color() );
|
|
QColor topColor( helper().backgroundTopColor( color ) );
|
|
QColor bottomColor( helper().backgroundBottomColor( color ) );
|
|
|
|
// make tooltip semi transparents when possible
|
|
// alpha is copied from "kdebase/apps/dolphin/tooltips/filemetadatatooltip.cpp"
|
|
const bool hasAlpha( helper().hasAlphaChannel( widget ) );
|
|
if( hasAlpha && StyleConfigData::toolTipTransparent() )
|
|
{
|
|
if( widget && widget->window() )
|
|
{ blurHelper().registerWidget( widget->window() ); }
|
|
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;
|
|
|
|
default:
|
|
case StyleConfigData::TE_SMALL:
|
|
size = ArrowSmall;
|
|
break;
|
|
|
|
case StyleConfigData::TE_NORMAL:
|
|
penThickness = 1.6;
|
|
offset = 0.0;
|
|
size = ArrowNormal;
|
|
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 );
|
|
|
|
// in fact with current version of Qt ( 4.6.0 ) the cast fails and document mode is always false
|
|
// this will hopefully be fixed in later versions
|
|
const QStyleOptionTabV3* tabOptV3( qstyleoption_cast<const QStyleOptionTabV3*>( option ) );
|
|
bool documentMode( tabOptV3 ? tabOptV3->documentMode : false );
|
|
|
|
const QTabWidget *tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast<const QTabWidget *>( widget->parentWidget() ) : NULL;
|
|
documentMode |= ( tabWidget ? tabWidget->documentMode() : true );
|
|
|
|
QRect gradientRect( r );
|
|
switch( tabOpt->shape )
|
|
{
|
|
|
|
case QTabBar::TriangularNorth:
|
|
case QTabBar::RoundedNorth:
|
|
gradientRect.adjust( 0, 0, 0, -5 );
|
|
if( !reverseLayout ) gradientRect.translate( -GlowWidth,0 );
|
|
break;
|
|
|
|
case QTabBar::TriangularSouth:
|
|
case QTabBar::RoundedSouth:
|
|
gradientRect.adjust( 0, 5, 0, 0 );
|
|
if( !reverseLayout ) gradientRect.translate( -GlowWidth,0 );
|
|
break;
|
|
|
|
case QTabBar::TriangularWest:
|
|
case QTabBar::RoundedWest:
|
|
gradientRect.adjust( 0, 0, -5, 0 );
|
|
gradientRect.translate( 0,-GlowWidth );
|
|
break;
|
|
|
|
case QTabBar::TriangularEast:
|
|
case QTabBar::RoundedEast:
|
|
gradientRect.adjust( 5, 0, 0, 0 );
|
|
gradientRect.translate( 0,-GlowWidth );
|
|
break;
|
|
|
|
default: return true;
|
|
}
|
|
|
|
// fade tabbar
|
|
QPixmap pm( gradientRect.size() );
|
|
pm.fill( Qt::transparent );
|
|
QPainter pp( &pm );
|
|
|
|
const bool verticalTabs( isVerticalTab( tabOpt ) );
|
|
|
|
int w = 0, h = 0;
|
|
if( verticalTabs ) h = gradientRect.height();
|
|
else w = gradientRect.width();
|
|
|
|
QLinearGradient grad;
|
|
if( reverseLayout && !verticalTabs ) grad = QLinearGradient( 0, 0, w, h );
|
|
else grad = QLinearGradient( w, h, 0, 0 );
|
|
|
|
grad.setColorAt( 0, Qt::transparent );
|
|
grad.setColorAt( 0.6, Qt::black );
|
|
|
|
if( widget )
|
|
helper().renderWindowBackground( &pp, pm.rect(), widget, palette );
|
|
pp.setCompositionMode( QPainter::CompositionMode_DestinationAtop );
|
|
pp.fillRect( pm.rect(), QBrush( grad ) );
|
|
pp.end();
|
|
|
|
// draw pixmap
|
|
painter->drawPixmap( gradientRect.topLeft()+QPoint( 0,-1 ),pm );
|
|
|
|
return true;
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawIndicatorToolBarHandlePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
|
|
{
|
|
const State& flags( option->state );
|
|
const bool horizontal( flags & State_Horizontal );
|
|
const QRect& r( option->rect );
|
|
const QPalette& palette( option->palette );
|
|
int counter( 1 );
|
|
|
|
if( horizontal )
|
|
{
|
|
|
|
const int center( r.left()+r.width()/2 );
|
|
for( int j = r.top()+2; j <= r.bottom()-3; j+=3, ++counter )
|
|
{
|
|
if( counter%2 == 0 ) helper().renderDot( painter, QPoint( center+1, j ), palette.color( QPalette::Background ) );
|
|
else helper().renderDot( painter, QPoint( center-2, j ), palette.color( QPalette::Background ) );
|
|
}
|
|
|
|
} else {
|
|
|
|
const int center( r.top()+r.height()/2 );
|
|
for( int j = r.left()+2; j <= r.right()-3; j+=3, ++counter )
|
|
{
|
|
if( counter%2 == 0 ) helper().renderDot( painter, QPoint( j, center+1 ), palette.color( QPalette::Background ) );
|
|
else helper().renderDot( painter, QPoint( j, center-2 ), palette.color( QPalette::Background ) );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawIndicatorToolBarSeparatorPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
|
|
{
|
|
|
|
const State& flags( option->state );
|
|
const QRect& r( option->rect );
|
|
const QPalette& palette( option->palette );
|
|
if( StyleConfigData::toolBarDrawItemSeparator() )
|
|
{
|
|
const QColor color( palette.color( QPalette::Window ) );
|
|
if( flags & State_Horizontal ) helper().drawSeparator( painter, r, color, Qt::Vertical );
|
|
else helper().drawSeparator( painter, r, color, Qt::Horizontal );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
// check widget and attributes
|
|
if( !widget || !widget->testAttribute( Qt::WA_StyledBackground ) || widget->testAttribute( Qt::WA_NoSystemBackground ) ) return false;
|
|
if( !( ( widget->windowFlags() & Qt::WindowType_Mask ) & ( Qt::Window|Qt::Dialog ) ) ) return false;
|
|
if( !widget->isWindow() ) return false;
|
|
|
|
// normal "window" background
|
|
const QPalette& palette( option->palette );
|
|
|
|
// do not render background if palette brush has a texture (pixmap or image)
|
|
const QBrush brush( palette.brush( widget->backgroundRole() ) );
|
|
if( !( brush.texture().isNull() && brush.textureImage().isNull() ) )
|
|
{ return false; }
|
|
|
|
helper().renderWindowBackground( painter, option->rect, widget, palette );
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawCapacityBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
// cast option
|
|
const QStyleOptionProgressBar* cbOption( qstyleoption_cast<const QStyleOptionProgressBar*>( option ) );
|
|
if( !cbOption ) return true;
|
|
|
|
// draw container
|
|
QStyleOptionProgressBarV2 sub_opt( *cbOption );
|
|
sub_opt.rect = subElementRect( QStyle::SE_ProgressBarGroove, cbOption, widget );
|
|
drawProgressBarGrooveControl( &sub_opt, painter, widget );
|
|
|
|
// draw bar
|
|
sub_opt.rect = subElementRect( QStyle::SE_ProgressBarContents, cbOption, widget );
|
|
drawProgressBarContentsControl( &sub_opt, painter, widget );
|
|
|
|
// draw label
|
|
sub_opt.rect = subElementRect( QStyle::SE_ProgressBarLabel, cbOption, widget );
|
|
drawProgressBarLabelControl( &sub_opt, painter, widget );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawComboBoxLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
//same as CommonStyle, except for filling behind icon
|
|
if( const QStyleOptionComboBox *cb = qstyleoption_cast<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 );
|
|
|
|
// cast to v2 to check vertical bar
|
|
const QStyleOptionDockWidgetV2 *v2 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>( option );
|
|
const bool verticalTitleBar( v2 ? v2->verticalTitleBar : false );
|
|
|
|
const QRect btnr( subElementRect( dwOpt->floatable ? SE_DockWidgetFloatButton : SE_DockWidgetCloseButton, option, widget ) );
|
|
|
|
// get rectangle and adjust to properly accounts for buttons
|
|
QRect r( insideMargin( dwOpt->rect, DockWidget_TitleMargin ) );
|
|
if( verticalTitleBar )
|
|
{
|
|
|
|
if( btnr.isValid() ) r.setTop( btnr.bottom()+1 );
|
|
|
|
} else if( reverseLayout ) {
|
|
|
|
if( btnr.isValid() ) r.setLeft( btnr.right()+1 );
|
|
r.adjust( 0,0,-4,0 );
|
|
|
|
} else {
|
|
|
|
if( btnr.isValid() ) r.setRight( btnr.left()-1 );
|
|
r.adjust( 4,0,0,0 );
|
|
|
|
}
|
|
|
|
QString title( dwOpt->title );
|
|
QString tmpTitle = title;
|
|
|
|
// this is quite suboptimal
|
|
// and does not really work
|
|
if( tmpTitle.contains( "&" ) )
|
|
{
|
|
int pos = tmpTitle.indexOf( "&" );
|
|
if( !( tmpTitle.size()-1 > pos && tmpTitle.at( pos+1 ) == QChar( '&' ) ) ) tmpTitle.remove( pos, 1 );
|
|
|
|
}
|
|
|
|
int tw = dwOpt->fontMetrics.width( tmpTitle );
|
|
int width = verticalTitleBar ? r.height() : r.width();
|
|
if( width < tw ) title = dwOpt->fontMetrics.elidedText( title, Qt::ElideRight, width, Qt::TextShowMnemonic );
|
|
|
|
if( verticalTitleBar )
|
|
{
|
|
|
|
QSize s = r.size();
|
|
s.transpose();
|
|
r.setSize( s );
|
|
|
|
painter->save();
|
|
painter->translate( r.left(), r.top() + r.width() );
|
|
painter->rotate( -90 );
|
|
painter->translate( -r.left(), -r.top() );
|
|
drawItemText( painter, r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette, enabled, title, QPalette::WindowText );
|
|
painter->restore();
|
|
|
|
|
|
} else {
|
|
|
|
drawItemText( painter, r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette, enabled, title, QPalette::WindowText );
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawHeaderEmptyAreaControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
// use the same background as in drawHeaderPrimitive
|
|
QPalette palette( option->palette );
|
|
|
|
const bool horizontal( option->state & QStyle::State_Horizontal );
|
|
const bool reverseLayout( option->direction == Qt::RightToLeft );
|
|
renderHeaderBackground( option->rect, palette, painter, widget, horizontal, reverseLayout );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawHeaderLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const
|
|
{
|
|
const QStyleOptionHeader* headerOpt( qstyleoption_cast<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
|
|
QStyleOptionProgressBarV2 subopt = *pb;
|
|
subopt.rect = subElementRect( SE_ProgressBarGroove, pb, widget );
|
|
drawProgressBarGrooveControl( &subopt, painter, widget );
|
|
|
|
subopt.rect = subElementRect( SE_ProgressBarContents, &subopt, widget );
|
|
drawProgressBarContentsControl( &subopt, painter, widget );
|
|
|
|
if( pb->textVisible )
|
|
{
|
|
subopt.rect = subElementRect( SE_ProgressBarLabel, pb, widget );
|
|
drawProgressBarLabelControl( &subopt, painter, widget );
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawProgressBarContentsControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
Q_UNUSED(widget);
|
|
|
|
const QStyleOptionProgressBar* pbOpt = qstyleoption_cast<const QStyleOptionProgressBar*>( option );
|
|
if ( !pbOpt ) return true;
|
|
|
|
const QStyleOptionProgressBarV2* pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBarV2*>( option );
|
|
|
|
const QRect& r( option->rect );
|
|
const QPalette& palette( option->palette );
|
|
|
|
// check if anything is to be drawn
|
|
qreal progress = pbOpt->progress - pbOpt->minimum;
|
|
const bool busyIndicator = ( pbOpt->minimum == 0 && pbOpt->maximum == 0 );
|
|
#warning "busy indicator"
|
|
#if 0
|
|
if( busyIndicator && widget )
|
|
{
|
|
// load busy value from widget property
|
|
QVariant busyValue( widget->property( ProgressBarEngine::busyValuePropertyName ) );
|
|
if( busyValue.isValid() ) progress = busyValue.toReal();
|
|
}
|
|
#endif
|
|
|
|
if( !( progress || busyIndicator ) ) return true;
|
|
|
|
const int steps = qMax( pbOpt->maximum - pbOpt->minimum, 1 );
|
|
const bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal;
|
|
|
|
//Calculate width fraction
|
|
qreal widthFrac( busyIndicator ? ProgressBar_BusyIndicatorSize/100.0 : progress/steps );
|
|
widthFrac = qMin( (qreal)1.0, widthFrac );
|
|
|
|
// And now the pixel width
|
|
const int indicatorSize( widthFrac*( horizontal ? r.width():r.height() ) );
|
|
|
|
// do nothing if indicator size is too small
|
|
if( indicatorSize < 4 ) return true;
|
|
|
|
QRect indicatorRect;
|
|
if ( busyIndicator )
|
|
{
|
|
|
|
// The space around which we move around...
|
|
int remSize = ( ( 1.0 - widthFrac )*( horizontal ? r.width():r.height() ) );
|
|
remSize = qMax( remSize, 1 );
|
|
|
|
int pstep = int( progress )%( 2*remSize );
|
|
if ( pstep > remSize )
|
|
{ pstep = -( pstep - 2*remSize ); }
|
|
|
|
if ( horizontal ) indicatorRect = QRect( r.x() + pstep, r.y(), indicatorSize, r.height() );
|
|
else indicatorRect = QRect( r.x(), r.y() + pstep, r.width(), indicatorSize );
|
|
|
|
} else {
|
|
|
|
if ( horizontal ) indicatorRect = QRect( r.x(), r.y(), indicatorSize, r.height() );
|
|
else indicatorRect = QRect( r.x(), r.bottom()- indicatorSize + 1, r.width(), indicatorSize );
|
|
|
|
}
|
|
|
|
// handle right to left
|
|
indicatorRect = handleRTL( option, indicatorRect );
|
|
|
|
// make sure rect is large enough
|
|
/* this account for adjustments done here and in StyleHelper::progressBarIndicator */
|
|
if( indicatorRect.adjusted( 2, 1, -2, -1 ).isValid() )
|
|
{
|
|
indicatorRect.adjust( 1, 0, -1, -1 );
|
|
|
|
// calculate dimension
|
|
int dimension( 20 );
|
|
if( pbOpt2 ) dimension = qMax( 5, horizontal ? indicatorRect.height() : indicatorRect.width() );
|
|
TileSet* tileSet( helper().progressBarIndicator( palette, dimension ) );
|
|
tileSet->render( indicatorRect, painter, TileSet::Full );
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawProgressBarGrooveControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const
|
|
{
|
|
|
|
const QStyleOptionProgressBarV2 *pbOpt = qstyleoption_cast<const QStyleOptionProgressBarV2 *>( 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 QStyleOptionProgressBarV2* pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBarV2*>( option );
|
|
const bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal;
|
|
const bool reverseLayout = ( option->direction == Qt::RightToLeft );
|
|
|
|
// rotate label for vertical layout
|
|
if( ! ( horizontal || reverseLayout ) )
|
|
{
|
|
|
|
painter->translate( r.topRight() );
|
|
painter->rotate( 90.0 );
|
|
|
|
} else if( !horizontal ) {
|
|
|
|
painter->translate( r.bottomLeft() );
|
|
painter->rotate( -90.0 );
|
|
|
|
}
|
|
|
|
Qt::Alignment hAlign( ( pbOpt->textAlignment == Qt::AlignLeft ) ? Qt::AlignHCenter : pbOpt->textAlignment );
|
|
|
|
/*
|
|
Figure out the geometry of the indicator.
|
|
This is copied from drawProgressBarContentsControl
|
|
*/
|
|
QRect progressRect;
|
|
const QRect textRect( horizontal? r : QRect( 0, 0, r.height(), r.width() ) );
|
|
const qreal progress = pbOpt->progress - pbOpt->minimum;
|
|
const int steps = qMax( pbOpt->maximum - pbOpt->minimum, 1 );
|
|
const bool busyIndicator = ( steps <= 1 );
|
|
|
|
int indicatorSize( 0 );
|
|
if( !busyIndicator )
|
|
{
|
|
const qreal widthFrac = qMin( (qreal)1.0, progress / steps );
|
|
indicatorSize = widthFrac*( horizontal ? r.width() : r.height() ) - (horizontal ? 2:1);
|
|
}
|
|
|
|
if( indicatorSize > 0 )
|
|
{
|
|
if ( horizontal ) painter->setClipRect( handleRTL( option, QRect( r.x(), r.y(), indicatorSize, r.height() ) ) );
|
|
else if ( !reverseLayout ) painter->setClipRect( QRect( r.height()-indicatorSize, 0, r.height(), r.width() ) );
|
|
else painter->setClipRect( QRect( 0, 0, indicatorSize, r.width() ) );
|
|
|
|
// first pass ( highlighted )
|
|
drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, pbOpt->text, QPalette::HighlightedText );
|
|
|
|
// second pass ( normal )
|
|
if( horizontal ) painter->setClipRect( handleRTL( option, QRect( r.x() + indicatorSize, r.y(), r.width() - indicatorSize, r.height() ) ) );
|
|
else if( !reverseLayout ) painter->setClipRect( QRect( 0, 0, r.height() - indicatorSize, r.width() ) );
|
|
else painter->setClipRect( QRect( indicatorSize, 0, r.height()- indicatorSize, r.width() ) );
|
|
drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, pbOpt->text, QPalette::WindowText );
|
|
|
|
} else {
|
|
|
|
drawItemText( painter, textRect, Qt::AlignVCenter | hAlign, palette, enabled, pbOpt->text, QPalette::WindowText );
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawPushButtonLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const
|
|
{
|
|
|
|
// cast option and check
|
|
const QStyleOptionButton* bOpt = qstyleoption_cast<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 QStyleOptionFrameV3* frameOpt = qstyleoption_cast<const QStyleOptionFrameV3*>( option );
|
|
if( !frameOpt ) return false;
|
|
|
|
switch( frameOpt->frameShape )
|
|
{
|
|
|
|
case QFrame::Box:
|
|
{
|
|
if( option->state & State_Sunken ) return true;
|
|
else break;
|
|
}
|
|
|
|
case QFrame::HLine:
|
|
{
|
|
const QColor color( helper().backgroundColor( option->palette.color( QPalette::Window ), widget, option->rect.center() ) );
|
|
helper().drawSeparator( painter, option->rect, color, Qt::Horizontal );
|
|
return true;
|
|
}
|
|
|
|
case QFrame::VLine:
|
|
{
|
|
const QColor color( helper().backgroundColor( option->palette.color( QPalette::Window ), widget, option->rect.center() ) );
|
|
helper().drawSeparator( painter, option->rect, color, Qt::Vertical );
|
|
return true;
|
|
}
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawTabBarTabLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const
|
|
{
|
|
|
|
const QStyleOptionTab *tabOpt = qstyleoption_cast< const QStyleOptionTab* >( option );
|
|
if( !tabOpt ) return true;
|
|
|
|
// add extra offset for selected tas
|
|
QStyleOptionTabV3 tabOptV3( *tabOpt );
|
|
|
|
const bool selected( option->state&State_Selected );
|
|
|
|
// get rect
|
|
QRect r( option->rect );
|
|
|
|
// handle selection and orientation
|
|
/*
|
|
painter is rotated and translated to deal with various orientations
|
|
rect is translated to 0,0, and possibly transposed
|
|
*/
|
|
switch( tabOptV3.shape )
|
|
{
|
|
|
|
|
|
case QTabBar::RoundedNorth:
|
|
case QTabBar::TriangularNorth:
|
|
{
|
|
if( selected ) r.translate( 0, -1 );
|
|
painter->translate( r.topLeft() );
|
|
r.moveTopLeft( QPoint( 0,0 ) );
|
|
break;
|
|
|
|
}
|
|
|
|
case QTabBar::RoundedSouth:
|
|
case QTabBar::TriangularSouth:
|
|
{
|
|
if( selected ) r.translate( 0, 1 );
|
|
painter->translate( r.topLeft() );
|
|
r.moveTopLeft( QPoint( 0,0 ) );
|
|
break;
|
|
|
|
}
|
|
|
|
case QTabBar::RoundedWest:
|
|
case QTabBar::TriangularWest:
|
|
{
|
|
|
|
if( selected ) r.translate( -1, 0 );
|
|
painter->translate( r.bottomLeft() );
|
|
painter->rotate( -90 );
|
|
r = QRect( QPoint( 0, 0 ), QSize( r.height(), r.width() ) );
|
|
break;
|
|
|
|
}
|
|
|
|
case QTabBar::RoundedEast:
|
|
case QTabBar::TriangularEast:
|
|
{
|
|
|
|
if( selected ) r.translate( 1, 0 );
|
|
painter->translate( r.topRight() );
|
|
painter->rotate( 90 );
|
|
r = QRect( QPoint( 0, 0 ), QSize( r.height(), r.width() ) );
|
|
break;
|
|
|
|
}
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
// make room for left and right widgets
|
|
// left widget
|
|
const bool verticalTabs( isVerticalTab( tabOpt ) );
|
|
const bool hasLeftButton( !( option->direction == Qt::RightToLeft ? tabOptV3.rightButtonSize.isEmpty():tabOptV3.leftButtonSize.isEmpty() ) );
|
|
const bool hasRightButton( !( option->direction == Qt::RightToLeft ? tabOptV3.leftButtonSize.isEmpty():tabOptV3.rightButtonSize.isEmpty() ) );
|
|
|
|
if( hasLeftButton )
|
|
{ r.setLeft( r.left() + 4 + ( verticalTabs ? tabOptV3.leftButtonSize.height() : tabOptV3.leftButtonSize.width() ) ); }
|
|
|
|
// make room for left and right widgets
|
|
// left widget
|
|
if( hasRightButton )
|
|
{ r.setRight( r.right() - 4 - ( verticalTabs ? tabOptV3.rightButtonSize.height() : tabOptV3.rightButtonSize.width() ) ); }
|
|
|
|
// compute textRect and iconRect
|
|
// now that orientation is properly dealt with, everything is handled as a 'north' orientation
|
|
QRect textRect;
|
|
QRect iconRect;
|
|
|
|
if( tabOptV3.icon.isNull() )
|
|
{
|
|
|
|
textRect = r.adjusted( 6, 0, -6, 0 );
|
|
|
|
} else {
|
|
|
|
const QSize& iconSize( tabOptV3.iconSize );
|
|
iconRect = centerRect( r, iconSize );
|
|
if( !tabOptV3.text.isEmpty() )
|
|
{
|
|
|
|
iconRect.moveLeft( r.left() + 8 );
|
|
textRect = r;
|
|
textRect.setLeft( iconRect.right()+3 );
|
|
textRect.setRight( r.right() - 6 );
|
|
}
|
|
|
|
}
|
|
|
|
if( !verticalTabs )
|
|
{
|
|
textRect = visualRect(option->direction, r, textRect );
|
|
iconRect = visualRect(option->direction, r, iconRect );
|
|
}
|
|
|
|
// render icon
|
|
if( !iconRect.isNull() )
|
|
{
|
|
|
|
// not sure why this is necessary
|
|
if( tabOptV3.shape == QTabBar::RoundedNorth || tabOptV3.shape == QTabBar::TriangularNorth )
|
|
{ iconRect.translate( 0, -1 ); }
|
|
|
|
const QPixmap tabIcon = tabOptV3.icon.pixmap(
|
|
tabOptV3.iconSize,
|
|
( tabOptV3.state & State_Enabled ) ? QIcon::Normal : QIcon::Disabled,
|
|
( tabOptV3.state & State_Selected ) ? QIcon::On : QIcon::Off );
|
|
|
|
painter->drawPixmap( iconRect.x(), iconRect.y(), tabIcon );
|
|
}
|
|
|
|
// render text
|
|
if( !textRect.isNull() )
|
|
{
|
|
|
|
const QPalette& palette( option->palette );
|
|
const QString& text( tabOptV3.text );
|
|
const bool enabled( option->state & State_Enabled );
|
|
const int alignment( Qt::AlignCenter|Qt::TextShowMnemonic );
|
|
drawItemText( painter, textRect, alignment, palette, enabled, text, QPalette::WindowText );
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//___________________________________________________________________________________
|
|
bool Style::drawTabBarTabShapeControl_Single( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
|
|
const QStyleOptionTab* tabOpt( qstyleoption_cast<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
|
|
const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>( option );
|
|
bool documentMode = tabOptV3 ? tabOptV3->documentMode : false;
|
|
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
|
|
const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>( option );
|
|
bool documentMode = tabOptV3 ? tabOptV3->documentMode : false;
|
|
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
|
|
const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>( tabOpt );
|
|
bool documentMode = tabOptV3 ? tabOptV3->documentMode : false;
|
|
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 to v2 and disable paint is tab is first
|
|
const QStyleOptionToolBoxV2 *v2 = qstyleoption_cast<const QStyleOptionToolBoxV2 *>( option );
|
|
if( v2 && v2->position == QStyleOptionToolBoxV2::Beginning && selected ) return true;
|
|
|
|
// save colors for shadow
|
|
/* important: option returns a wrong color. We use the widget's palette when widget is set */
|
|
const QColor color( widget ? widget->palette().color( widget->backgroundRole() ) : palette.color( QPalette::Window ) );
|
|
const QColor dark( helper().calcDarkColor( color ) );
|
|
QList<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 & QStyleOptionFrameV2::Flat )
|
|
{
|
|
|
|
// for flat groupboxes, the groupBox title is rendered bold
|
|
/*
|
|
TODO: talk to pinheiro. This is not an optimal design
|
|
I would rather
|
|
1/ keep the font unchanged
|
|
2/ add an horizontal separator next to the title
|
|
( Hugo )
|
|
*/
|
|
const QFont oldFont = painter->font();
|
|
QFont font = oldFont;
|
|
font.setBold( true );
|
|
painter->setFont( font );
|
|
QCommonStyle::drawComplexControl( CC_GroupBox, option, painter, widget );
|
|
painter->setFont( oldFont );
|
|
return true;
|
|
|
|
} else return false;
|
|
}
|
|
|
|
//______________________________________________________________
|
|
bool Style::drawSliderComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const
|
|
{
|
|
const QStyleOptionSlider *sliderOption( qstyleoption_cast<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() );
|
|
|
|
// background pixmap
|
|
helper().setBackgroundPixmap( StyleConfigData::backgroundPixmap() );
|
|
|
|
// reset config
|
|
StyleConfigData::self()->readConfig();
|
|
|
|
// update caches size
|
|
int cacheSize( StyleConfigData::cacheEnabled() ?
|
|
StyleConfigData::maxCacheSize():0 );
|
|
|
|
helper().setMaxCacheSize( cacheSize );
|
|
|
|
// always enable blur helper
|
|
blurHelper().setEnabled( true );
|
|
|
|
// reinitialize engines
|
|
windowManager().initialize();
|
|
shadowHelper().reloadConfig();
|
|
|
|
// mnemonics
|
|
mnemonics().setMode( StyleConfigData::mnemonicsMode() );
|
|
|
|
// widget explorer
|
|
widgetExplorer().setEnabled( StyleConfigData::widgetExplorerEnabled() );
|
|
widgetExplorer().setDrawWidgetRects( StyleConfigData::drawWidgetRects() );
|
|
|
|
// splitter proxy
|
|
splitterFactory().setEnabled( StyleConfigData::splitterProxyEnabled() );
|
|
|
|
// scrollbar button dimentions.
|
|
/* it has to be reinitialized here because scrollbar width might have changed */
|
|
_noButtonHeight = 0;
|
|
_singleButtonHeight = qMax( StyleConfigData::scrollBarWidth() * 7 / 10, 14 );
|
|
_doubleButtonHeight = 2*_singleButtonHeight;
|
|
|
|
// scrollbar buttons
|
|
switch( StyleConfigData::scrollBarAddLineButtons() )
|
|
{
|
|
case 0: _addLineButtons = NoButton; break;
|
|
case 1: _addLineButtons = SingleButton; break;
|
|
|
|
default:
|
|
case 2: _addLineButtons = DoubleButton; break;
|
|
}
|
|
|
|
switch( StyleConfigData::scrollBarSubLineButtons() )
|
|
{
|
|
case 0: _subLineButtons = NoButton; break;
|
|
case 1: _subLineButtons = SingleButton; break;
|
|
|
|
default:
|
|
case 2: _subLineButtons = DoubleButton; break;
|
|
}
|
|
|
|
// tabbar shape
|
|
switch( StyleConfigData::tabStyle() )
|
|
{
|
|
case StyleConfigData::TS_PLAIN:
|
|
_tabBarTabShapeControl = &Style::drawTabBarTabShapeControl_Plain;
|
|
break;
|
|
|
|
default:
|
|
case StyleConfigData::TS_SINGLE:
|
|
_tabBarTabShapeControl = &Style::drawTabBarTabShapeControl_Single;
|
|
break;
|
|
}
|
|
|
|
// frame focus
|
|
if( StyleConfigData::viewDrawFocusIndicator() ) _frameFocusPrimitive = &Style::drawFrameFocusRectPrimitive;
|
|
else _frameFocusPrimitive = &Style::emptyPrimitive;
|
|
}
|
|
|
|
//_____________________________________________________________________
|
|
void Style::globalPaletteChanged( void )
|
|
{
|
|
helper().reloadConfig();
|
|
helper().invalidateCaches();
|
|
}
|
|
|
|
//____________________________________________________________________
|
|
#ifndef QT_KATIE
|
|
QIcon Style::standardIconImplementation(
|
|
#else
|
|
QIcon Style::standardIcon(
|
|
#endif
|
|
StandardPixmap standardIcon,
|
|
const QStyleOption *option,
|
|
const QWidget *widget ) const
|
|
{
|
|
|
|
switch( standardIcon )
|
|
{
|
|
|
|
// copied from kstyle
|
|
case SP_DesktopIcon: return KIcon( "user-desktop" );
|
|
case SP_TrashIcon: return KIcon( "user-trash" );
|
|
case SP_ComputerIcon: return KIcon( "computer" );
|
|
case SP_DriveFDIcon: return KIcon( "media-floppy" );
|
|
case SP_DriveHDIcon: return KIcon( "drive-harddisk" );
|
|
case SP_DriveCDIcon: return KIcon( "drive-optical" );
|
|
case SP_DriveDVDIcon: return KIcon( "drive-optical" );
|
|
case SP_DriveNetIcon: return KIcon( "folder-remote" );
|
|
case SP_DirHomeIcon: return KIcon( "user-home" );
|
|
case SP_DirOpenIcon: return KIcon( "document-open-folder" );
|
|
case SP_DirClosedIcon: return KIcon( "folder" );
|
|
case SP_DirIcon: return KIcon( "folder" );
|
|
|
|
//TODO: generate ( !? ) folder with link emblem
|
|
case SP_DirLinkIcon: return KIcon( "folder" );
|
|
|
|
//TODO: look for a better icon
|
|
case SP_FileIcon: return KIcon( "text-plain" );
|
|
|
|
//TODO: generate ( !? ) file with link emblem
|
|
case SP_FileLinkIcon: return KIcon( "text-plain" );
|
|
|
|
//TODO: find correct icon
|
|
case SP_FileDialogStart: return KIcon( "media-playback-start" );
|
|
|
|
//TODO: find correct icon
|
|
case SP_FileDialogEnd: return KIcon( "media-playback-stop" );
|
|
|
|
case SP_FileDialogToParent: return KIcon( "go-up" );
|
|
case SP_FileDialogNewFolder: return KIcon( "folder-new" );
|
|
case SP_FileDialogDetailedView: return KIcon( "view-list-details" );
|
|
case SP_FileDialogInfoView: return KIcon( "document-properties" );
|
|
case SP_FileDialogContentsView: return KIcon( "view-list-icons" );
|
|
case SP_FileDialogListView: return KIcon( "view-list-text" );
|
|
case SP_FileDialogBack: return KIcon( "go-previous" );
|
|
case SP_MessageBoxInformation: return KIcon( "dialog-information" );
|
|
case SP_MessageBoxWarning: return KIcon( "dialog-warning" );
|
|
case SP_MessageBoxCritical: return KIcon( "dialog-error" );
|
|
case SP_MessageBoxQuestion: return KIcon( "dialog-information" );
|
|
case SP_DialogOkButton: return KIcon( "dialog-ok" );
|
|
case SP_DialogCancelButton: return KIcon( "dialog-cancel" );
|
|
case SP_DialogHelpButton: return KIcon( "help-contents" );
|
|
case SP_DialogOpenButton: return KIcon( "document-open" );
|
|
case SP_DialogSaveButton: return KIcon( "document-save" );
|
|
case SP_DialogCloseButton: return KIcon( "dialog-close" );
|
|
case SP_DialogApplyButton: return KIcon( "dialog-ok-apply" );
|
|
case SP_DialogResetButton: return KIcon( "document-revert" );
|
|
case SP_DialogDiscardButton: return KIcon( "dialog-cancel" );
|
|
case SP_DialogYesButton: return KIcon( "dialog-ok-apply" );
|
|
case SP_DialogNoButton: return KIcon( "dialog-cancel" );
|
|
case SP_ArrowUp: return KIcon( "go-up" );
|
|
case SP_ArrowDown: return KIcon( "go-down" );
|
|
case SP_ArrowLeft: return KIcon( "go-previous-view" );
|
|
case SP_ArrowRight: return KIcon( "go-next-view" );
|
|
case SP_ArrowBack: return KIcon( "go-previous" );
|
|
case SP_ArrowForward: return KIcon( "go-next" );
|
|
case SP_BrowserReload: return KIcon( "view-refresh" );
|
|
case SP_BrowserStop: return KIcon( "process-stop" );
|
|
case SP_MediaPlay: return KIcon( "media-playback-start" );
|
|
case SP_MediaStop: return KIcon( "media-playback-stop" );
|
|
case SP_MediaPause: return KIcon( "media-playback-pause" );
|
|
case SP_MediaSkipForward: return KIcon( "media-skip-forward" );
|
|
case SP_MediaSkipBackward: return KIcon( "media-skip-backward" );
|
|
case SP_MediaSeekForward: return KIcon( "media-seek-forward" );
|
|
case SP_MediaSeekBackward: return KIcon( "media-seek-backward" );
|
|
case SP_MediaVolume: return KIcon( "audio-volume-medium" );
|
|
case SP_MediaVolumeMuted: return KIcon( "audio-volume-muted" );
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
// MDI windows buttons
|
|
// get button color ( unfortunately option and widget might not be set )
|
|
QColor buttonColor;
|
|
QColor iconColor;
|
|
if( option )
|
|
{
|
|
|
|
buttonColor = option->palette.window().color();
|
|
iconColor = option->palette.windowText().color();
|
|
|
|
} else if( widget ) {
|
|
|
|
buttonColor = widget->palette().window().color();
|
|
iconColor = widget->palette().windowText().color();
|
|
|
|
} else if( qApp ) {
|
|
|
|
// might not have a QApplication
|
|
buttonColor = qApp->palette().window().color();
|
|
iconColor = qApp->palette().windowText().color();
|
|
|
|
} else {
|
|
|
|
// KCS is always safe
|
|
buttonColor = KColorScheme( QPalette::Active, KColorScheme::Window, helper().config() ).background().color();
|
|
iconColor = KColorScheme( QPalette::Active, KColorScheme::Window, helper().config() ).foreground().color();
|
|
|
|
}
|
|
|
|
// contrast
|
|
const QColor contrast( helper().calcLightColor( buttonColor ) );
|
|
|
|
switch( standardIcon )
|
|
{
|
|
|
|
case SP_TitleBarNormalButton:
|
|
{
|
|
QPixmap pixmap(
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ),
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) );
|
|
|
|
pixmap.fill( Qt::transparent );
|
|
|
|
QPainter painter( &pixmap );
|
|
renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarNormalButton );
|
|
|
|
return QIcon( pixmap );
|
|
|
|
}
|
|
|
|
case SP_TitleBarShadeButton:
|
|
{
|
|
QPixmap pixmap(
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ),
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) );
|
|
|
|
pixmap.fill( Qt::transparent );
|
|
QPainter painter( &pixmap );
|
|
renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarShadeButton );
|
|
|
|
return QIcon( pixmap );
|
|
}
|
|
|
|
case SP_TitleBarUnshadeButton:
|
|
{
|
|
QPixmap pixmap(
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ),
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) );
|
|
|
|
pixmap.fill( Qt::transparent );
|
|
QPainter painter( &pixmap );
|
|
renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarUnshadeButton );
|
|
|
|
return QIcon( pixmap );
|
|
}
|
|
|
|
case SP_TitleBarCloseButton:
|
|
case SP_DockWidgetCloseButton:
|
|
{
|
|
QPixmap pixmap(
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ),
|
|
pixelMetric( QStyle::PM_SmallIconSize, 0, 0 ) );
|
|
|
|
pixmap.fill( Qt::transparent );
|
|
QPainter painter( &pixmap );
|
|
renderTitleBarButton( &painter, pixmap.rect(), buttonColor, iconColor, SC_TitleBarCloseButton );
|
|
|
|
return QIcon( pixmap );
|
|
|
|
}
|
|
|
|
case SP_ToolBarHorizontalExtensionButton:
|
|
{
|
|
|
|
QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize,0,0 ), pixelMetric( QStyle::PM_SmallIconSize,0,0 ) );
|
|
pixmap.fill( Qt::transparent );
|
|
QPainter painter( &pixmap );
|
|
painter.setRenderHints( QPainter::Antialiasing );
|
|
painter.setBrush( Qt::NoBrush );
|
|
|
|
painter.translate( qreal( pixmap.width() )/2.0, qreal( pixmap.height() )/2.0 );
|
|
|
|
const bool reverseLayout( option && option->direction == Qt::RightToLeft );
|
|
QPolygonF a = genericArrow( reverseLayout ? ArrowLeft:ArrowRight, ArrowTiny );
|
|
|
|
const qreal width( 1.1 );
|
|
painter.translate( 0, 0.5 );
|
|
painter.setBrush( Qt::NoBrush );
|
|
painter.setPen( QPen( helper().calcLightColor( buttonColor ), width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
|
|
painter.drawPolyline( a );
|
|
|
|
painter.translate( 0,-1 );
|
|
painter.setBrush( Qt::NoBrush );
|
|
painter.setPen( QPen( iconColor, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
|
|
painter.drawPolyline( a );
|
|
|
|
return QIcon( pixmap );
|
|
}
|
|
|
|
case SP_ToolBarVerticalExtensionButton:
|
|
{
|
|
QPixmap pixmap( pixelMetric( QStyle::PM_SmallIconSize,0,0 ), pixelMetric( QStyle::PM_SmallIconSize,0,0 ) );
|
|
pixmap.fill( Qt::transparent );
|
|
QPainter painter( &pixmap );
|
|
painter.setRenderHints( QPainter::Antialiasing );
|
|
painter.setBrush( Qt::NoBrush );
|
|
|
|
painter.translate( qreal( pixmap.width() )/2.0, qreal( pixmap.height() )/2.0 );
|
|
|
|
QPolygonF a = genericArrow( ArrowDown, ArrowTiny );
|
|
|
|
const qreal width( 1.1 );
|
|
painter.translate( 0, 0.5 );
|
|
painter.setBrush( Qt::NoBrush );
|
|
painter.setPen( QPen( helper().calcLightColor( buttonColor ), width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
|
|
painter.drawPolyline( a );
|
|
|
|
painter.translate( 0,-1 );
|
|
painter.setBrush( Qt::NoBrush );
|
|
painter.setPen( QPen( iconColor, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
|
|
painter.drawPolyline( a );
|
|
|
|
return QIcon( pixmap );
|
|
}
|
|
|
|
default:
|
|
#ifndef QT_KATIE
|
|
return QCommonStyle::standardIconImplementation( standardIcon, option, widget );
|
|
#else
|
|
return QCommonStyle::standardIcon( standardIcon, option, widget );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//_____________________________________________________________
|
|
void Style::initializeKGlobalSettings( void )
|
|
{
|
|
|
|
if( qApp && !qApp->inherits( "KApplication" ) )
|
|
{
|
|
/*
|
|
for Qt, non-KDE applications, needs to explicitly activate KGlobalSettings.
|
|
On the other hand, it is done internally in kApplication constructor,
|
|
so no need to duplicate here.
|
|
*/
|
|
KGlobalSettings::self()->activate( KGlobalSettings::ListenForChanges );
|
|
}
|
|
|
|
// connect palette changes to local slot, to make sure caches are cleared
|
|
connect( KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(globalPaletteChanged()) );
|
|
|
|
// update flag
|
|
_kGlobalSettingsInitialized = true;
|
|
|
|
}
|
|
|
|
//______________________________________________________________
|
|
void Style::polishScrollArea( QAbstractScrollArea* scrollArea ) const
|
|
{
|
|
|
|
if( !scrollArea ) return;
|
|
|
|
// HACK: add exception for KPIM transactionItemView, which is an overlay widget
|
|
// and must have filled background. This is a temporary workaround until a more
|
|
// robust solution is found.
|
|
if( scrollArea->inherits( "KPIM::TransactionItemView" ) )
|
|
{
|
|
// also need to make the scrollarea background plain ( using autofill background )
|
|
// so that optional vertical scrollbar background is not transparent either.
|
|
// TODO: possibly add an event filter to use the "normal" window background
|
|
// instead of something flat.
|
|
scrollArea->setAutoFillBackground( true );
|
|
return;
|
|
}
|
|
|
|
// check frame style and background role
|
|
if( !(scrollArea->frameShape() == QFrame::NoFrame || scrollArea->backgroundRole() == QPalette::Window ) )
|
|
{ return; }
|
|
|
|
// get viewport and check background role
|
|
QWidget* viewport( scrollArea->viewport() );
|
|
if( !( viewport && viewport->backgroundRole() == QPalette::Window ) ) return;
|
|
|
|
// change viewport autoFill background.
|
|
// do the same for children if the background role is QPalette::Window
|
|
viewport->setAutoFillBackground( false );
|
|
QList<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;
|
|
|
|
}
|
|
|
|
}
|