You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1008 lines
36 KiB
1008 lines
36 KiB
// krazy:excludeall=qclasses |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
// breezestyle.cpp |
|
// Breeze widget style for KDE Frameworks |
|
// ------------------- |
|
// |
|
// Copyright (C) 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr> |
|
// |
|
// 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 "breezestyle.h" |
|
#include "breezestyle.moc" |
|
|
|
#include "breezehelper.h" |
|
#include "breezemetrics.h" |
|
#include "breezestyleconfigdata.h" |
|
#include "breezewindowmanager.h" |
|
|
|
#include <KColorUtils> |
|
|
|
#include <QApplication> |
|
#include <QAbstractItemView> |
|
#include <QCheckBox> |
|
#include <QComboBox> |
|
#include <QDial> |
|
#include <QDBusConnection> |
|
#include <QDockWidget> |
|
#include <QGroupBox> |
|
#include <QLineEdit> |
|
#include <QPainter> |
|
#include <QPushButton> |
|
#include <QRadioButton> |
|
#include <QScrollBar> |
|
#include <QSplitterHandle> |
|
#include <QTextEdit> |
|
#include <QToolBox> |
|
#include <QToolButton> |
|
|
|
Q_LOGGING_CATEGORY(BREEZE, "breeze") |
|
|
|
namespace Breeze |
|
{ |
|
|
|
//_________________________________________________ |
|
QStyle* Breeze::StylePlugin::create( const QString &key ) |
|
{ |
|
if( key.toLower() == QStringLiteral( "breeze" ) ) return new Style(); |
|
else return nullptr; |
|
} |
|
|
|
//_________________________________________________ |
|
Breeze::StylePlugin::~StylePlugin() |
|
{ |
|
// Delete style when using ::exit() otherwise it'll outlive the unloaded plugin and we'll get a crash |
|
if (qApp) delete qApp->style(); |
|
} |
|
|
|
//______________________________________________________________ |
|
Style::Style( void ): |
|
_addLineButtons( SingleButton ), |
|
_subLineButtons( SingleButton ), |
|
_helper( new Helper( StyleConfigData::self()->sharedConfig() ) ), |
|
_windowManager( new WindowManager( this ) ), |
|
SH_ArgbDndWindow( newStyleHint( QStringLiteral( "SH_ArgbDndWindow" ) ) ), |
|
CE_CapacityBar( newControlElement( QStringLiteral( "CE_CapacityBar" ) ) ) |
|
|
|
{ |
|
|
|
// use DBus connection to update on breeze configuration change |
|
QDBusConnection dbus = QDBusConnection::sessionBus(); |
|
dbus.connect( QString(), |
|
QStringLiteral( "/BreezeStyle" ), |
|
QStringLiteral( "org.kde.Breeze.Style" ), |
|
QStringLiteral( "reparseConfiguration" ), this, SLOT(configurationChanged()) ); |
|
|
|
// enable debugging |
|
QLoggingCategory::setFilterRules(QStringLiteral("breeze.debug = false")); |
|
|
|
// call the slot directly; this initial call will set up things that also |
|
// need to be reset when the system palette changes |
|
loadConfiguration(); |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
Style::~Style( void ) |
|
{ delete _helper; } |
|
|
|
//______________________________________________________________ |
|
void Style::polish( QWidget* widget ) |
|
{ |
|
if( !widget ) return; |
|
|
|
// register widget to animations |
|
windowManager().registerWidget( widget ); |
|
|
|
// enable hover effects for all necessary widgets |
|
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 ); } |
|
|
|
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 ); |
|
|
|
} |
|
|
|
// remove opaque painting for scrollbars |
|
if( qobject_cast<QScrollBar*>( widget ) ) |
|
{ |
|
|
|
widget->setAttribute( Qt::WA_OpaquePaintEvent, false ); |
|
|
|
} |
|
|
|
// base class polishing |
|
KStyle::polish( widget ); |
|
|
|
} |
|
|
|
//_______________________________________________________________ |
|
void Style::unpolish( QWidget* widget ) |
|
{ |
|
|
|
// register widget to animations |
|
windowManager().unregisterWidget( widget ); |
|
|
|
KStyle::unpolish( widget ); |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
int Style::pixelMetric( PixelMetric metric, const QStyleOption* option, const QWidget* widget ) const |
|
{ |
|
|
|
// handle special cases |
|
switch( metric ) |
|
{ |
|
|
|
|
|
case PM_ScrollBarExtent: return Metrics::ScrollBar_Extend; |
|
case PM_ScrollBarSliderMin: return Metrics::ScrollBar_MinSliderHeight; |
|
|
|
// fallback |
|
default: return KStyle::pixelMetric( metric, option, widget ); |
|
|
|
} |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
int Style::styleHint( StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData ) const |
|
{ |
|
switch( hint ) |
|
{ |
|
|
|
case SH_ScrollBar_MiddleClickAbsolutePosition: return true; |
|
|
|
// fallback |
|
default: return KStyle::styleHint( hint, option, widget, returnData ); |
|
|
|
} |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
QRect Style::subElementRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const |
|
{ |
|
switch( element ) |
|
{ |
|
|
|
// fallback |
|
default: return KStyle::subElementRect( element, option, widget ); |
|
|
|
} |
|
} |
|
|
|
//______________________________________________________________ |
|
QRect Style::subControlRect( ComplexControl element, const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const |
|
{ |
|
switch( element ) |
|
{ |
|
|
|
case CC_ScrollBar: return scrollBarSubControlRect( option, subControl, widget ); |
|
|
|
// fallback |
|
default: return KStyle::subControlRect( element, option, subControl, widget ); |
|
|
|
} |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
QSize Style::sizeFromContents( ContentsType element, const QStyleOption* option, const QSize& size, const QWidget* widget ) const |
|
{ |
|
|
|
switch( element ) |
|
{ |
|
|
|
// fallback |
|
default: return KStyle::sizeFromContents( element, option, size, widget ); |
|
|
|
} |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
QStyle::SubControl Style::hitTestComplexControl( ComplexControl control, const QStyleOptionComplex* option, const QPoint& point, const QWidget* widget ) const |
|
{ |
|
switch( control ) |
|
{ |
|
case CC_ScrollBar: |
|
{ |
|
|
|
QRect 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; |
|
} |
|
|
|
// fallback |
|
default: return KStyle::hitTestComplexControl( control, option, point, widget ); |
|
|
|
} |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
void Style::drawPrimitive( PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const |
|
{ |
|
|
|
switch( element ) |
|
{ |
|
|
|
// fallback |
|
default: return KStyle::drawPrimitive( element, option, painter, widget ); |
|
|
|
} |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
void Style::drawControl( ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const |
|
{ |
|
|
|
StyleControl fcn( nullptr ); |
|
switch( element ) |
|
{ |
|
|
|
// scrollbars |
|
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; |
|
|
|
// fallback |
|
default: break; |
|
|
|
} |
|
|
|
painter->save(); |
|
|
|
// call function if implemented |
|
if( !( fcn && ( this->*fcn )( option, painter, widget ) ) ) |
|
{ KStyle::drawControl( element, option, painter, widget ); } |
|
|
|
painter->restore(); |
|
|
|
} |
|
|
|
//______________________________________________________________ |
|
void Style::drawComplexControl( ComplexControl element, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const |
|
{ |
|
|
|
switch( element ) |
|
{ |
|
|
|
// fallback |
|
default: return KStyle::drawComplexControl( element, option, painter, widget ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
//___________________________________________________________________________________ |
|
void Style::drawItemText( |
|
QPainter* painter, const QRect& r, int flags, const QPalette& palette, bool enabled, |
|
const QString &text, QPalette::ColorRole textRole ) const |
|
{ |
|
|
|
// fallback |
|
return KStyle::drawItemText( painter, r, flags, palette, enabled, text, textRole ); |
|
|
|
} |
|
|
|
|
|
//_____________________________________________________________________ |
|
bool Style::eventFilter( QObject *object, QEvent *event ) |
|
{ |
|
// fallback |
|
return KStyle::eventFilter( object, event ); |
|
} |
|
|
|
//_____________________________________________________________________ |
|
void Style::configurationChanged() |
|
{ |
|
// reparse breezerc |
|
StyleConfigData::self()->readConfig(); |
|
|
|
// reload configuration |
|
loadConfiguration(); |
|
} |
|
|
|
//_____________________________________________________________________ |
|
void Style::loadConfiguration() |
|
{ |
|
|
|
// load helper configuration |
|
_helper->loadConfig(); |
|
|
|
// reinitialize engines |
|
windowManager().initialize(); |
|
|
|
} |
|
|
|
//___________________________________________________________________________________________________________________ |
|
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, static_cast<int>(Metrics::ScrollBar_MinSliderHeight ) ); |
|
sliderSize = qMin( sliderSize, space ); |
|
|
|
space -= sliderSize; |
|
if( space <= 0 ) return groove; |
|
|
|
int pos = qRound( qreal( sliderOption->sliderPosition - sliderOption->minimum )/ ( sliderOption->maximum - sliderOption->minimum )*space ); |
|
if( sliderOption->upsideDown ) pos = space - pos; |
|
if( horizontal ) return 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(); |
|
} |
|
} |
|
|
|
|
|
//___________________________________________________________________________________ |
|
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; |
|
|
|
painter->setClipRect( option->rect ); |
|
|
|
// define handle rect |
|
QRect handleRect; |
|
const State& flags( option->state ); |
|
const bool horizontal( flags & State_Horizontal ); |
|
if( horizontal ) handleRect = centerRect( option->rect, option->rect.width(), Metrics::ScrollBar_SliderWidth ); |
|
else handleRect = centerRect( option->rect, Metrics::ScrollBar_SliderWidth, option->rect.height() ); |
|
|
|
if( widget ) |
|
{ |
|
// render background |
|
// it is necessary to retrive the complete widget rect, in order to properly handle overlaps |
|
// at the scrollbar boundary |
|
// define color |
|
const QPalette& palette( option->palette ); |
|
const QColor color( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.3 ) ); |
|
|
|
// adjust rect |
|
QStyleOptionSlider copy( *sliderOption ); |
|
copy.rect = widget->rect(); |
|
QRect backgroundRect( scrollBarSubControlRect( ©, SC_ScrollBarGroove, widget ) ); |
|
if( horizontal ) backgroundRect = centerRect( backgroundRect, backgroundRect.width(), Metrics::ScrollBar_SliderWidth ); |
|
else backgroundRect = centerRect( backgroundRect, Metrics::ScrollBar_SliderWidth, backgroundRect.height() ); |
|
|
|
_helper->scrollBarHole( color )->render( backgroundRect, painter, TileSet::Full ); |
|
|
|
} |
|
|
|
{ |
|
// render handle |
|
// define colors |
|
QColor color; |
|
const QPalette& palette( option->palette ); |
|
const bool enabled( flags&State_Enabled ); |
|
const bool mouseOver( enabled && ( flags&State_MouseOver ) ); |
|
const bool focus( enabled && ( flags&State_HasFocus ) ); |
|
if( focus || mouseOver ) color = palette.color( QPalette::Highlight ); |
|
else { |
|
|
|
color = _helper->alphaColor( palette.color( QPalette::WindowText ), 0.5 ); |
|
|
|
} |
|
|
|
// render |
|
_helper->scrollBarHandle( color, QColor() )->render( handleRect, painter, TileSet::Full ); |
|
|
|
} |
|
|
|
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; |
|
|
|
if( false ) |
|
{ |
|
painter->save(); |
|
painter->setPen( Qt::red ); |
|
painter->setBrush( Qt::NoBrush ); |
|
painter->setRenderHint( QPainter::Antialiasing ); |
|
painter->drawRect( QRectF( option->rect ).adjusted( 0.5, 0.5, -0.5, -0.5 ) ); |
|
painter->restore(); |
|
} |
|
|
|
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 ) ); |
|
|
|
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 ) |
|
{ |
|
|
|
if( reverseLayout ) renderScrollBarArrow( painter, r, color, background, ArrowLeft ); |
|
else renderScrollBarArrow( painter, r.translated( 1, 0 ), color, background, ArrowRight ); |
|
|
|
} else renderScrollBarArrow( painter, r.translated( 0, 1 ), 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; |
|
|
|
painter->setClipRect( option->rect ); |
|
|
|
const QPalette& palette( option->palette ); |
|
const QColor color( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.3 ) ); |
|
const State& flags( option->state ); |
|
|
|
// define tiles and adjust rect |
|
TileSet::Tiles tiles; |
|
QRect backgroundRect; |
|
const bool horizontal( flags & State_Horizontal ); |
|
const bool reverseLayout( sliderOption->direction == Qt::RightToLeft ); |
|
|
|
if( horizontal ) |
|
{ |
|
|
|
backgroundRect = centerRect( option->rect, option->rect.width(), Metrics::ScrollBar_SliderWidth ); |
|
tiles = TileSet::Vertical; |
|
if( reverseLayout ) |
|
{ |
|
tiles |= TileSet::Left; |
|
backgroundRect.adjust( 0, 0, Metrics::ScrollBar_SliderWidth/2, 0 ); |
|
|
|
} else { |
|
|
|
tiles |= TileSet::Right; |
|
backgroundRect.adjust( -Metrics::ScrollBar_SliderWidth/2, 0, 0, 0 ); |
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
backgroundRect = centerRect( option->rect, Metrics::ScrollBar_SliderWidth, option->rect.height() ); |
|
tiles = TileSet::Horizontal|TileSet::Bottom; |
|
backgroundRect.adjust( 0, -Metrics::ScrollBar_SliderWidth/2, 0, 0 ); |
|
|
|
} |
|
|
|
// render |
|
_helper->scrollBarHole( color )->render( backgroundRect, painter, 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; |
|
|
|
if( false ) |
|
{ |
|
painter->save(); |
|
painter->setPen( Qt::red ); |
|
painter->setBrush( Qt::NoBrush ); |
|
painter->setRenderHint( QPainter::Antialiasing ); |
|
painter->drawRect( QRectF( option->rect ).adjusted( 0.5, 0.5, -0.5, -0.5 ) ); |
|
painter->restore(); |
|
} |
|
|
|
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 ) ); |
|
|
|
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 ) |
|
{ |
|
|
|
if( reverseLayout ) renderScrollBarArrow( painter, r.translated( 1, 0 ), color, background, ArrowRight ); |
|
else renderScrollBarArrow( painter, r, color, background, 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; |
|
|
|
painter->setClipRect( option->rect ); |
|
|
|
const QPalette& palette( option->palette ); |
|
const QColor color( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.3 ) ); |
|
const State& flags( option->state ); |
|
|
|
// define tiles and adjust rect |
|
TileSet::Tiles tiles; |
|
QRect backgroundRect; |
|
const bool horizontal( flags & State_Horizontal ); |
|
const bool reverseLayout( sliderOption->direction == Qt::RightToLeft ); |
|
|
|
if( horizontal ) |
|
{ |
|
|
|
backgroundRect = centerRect( option->rect, option->rect.width(), Metrics::ScrollBar_SliderWidth ); |
|
tiles = TileSet::Vertical; |
|
if( reverseLayout ) |
|
{ |
|
tiles |= TileSet::Right; |
|
backgroundRect.adjust( -Metrics::ScrollBar_SliderWidth/2, 0, 0, 0 ); |
|
|
|
} else { |
|
|
|
tiles |= TileSet::Left; |
|
backgroundRect.adjust( 0, 0, Metrics::ScrollBar_SliderWidth/2-1, 0 ); |
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
backgroundRect = centerRect( option->rect, Metrics::ScrollBar_SliderWidth, option->rect.height() ); |
|
tiles = TileSet::Horizontal|TileSet::Top; |
|
backgroundRect.adjust( 0, 0, 0, Metrics::ScrollBar_SliderWidth/2-1 ); |
|
|
|
} |
|
|
|
// render |
|
_helper->scrollBarHole( color )->render( backgroundRect, painter, tiles ); |
|
|
|
return true; |
|
|
|
} |
|
|
|
//______________________________________________________________________________ |
|
void Style::renderScrollBarArrow( |
|
QPainter* painter, const QRect& r, const QColor& color, const QColor& background, |
|
ArrowOrientation orientation ) const |
|
{ |
|
|
|
Q_UNUSED( background ); |
|
|
|
const qreal penThickness( 1.5 ); |
|
QPolygonF a( genericArrow( orientation, ArrowNormal ) ); |
|
|
|
const QColor base( color ); |
|
|
|
painter->save(); |
|
painter->translate( QRectF(r).center() ); |
|
painter->setRenderHint( QPainter::Antialiasing ); |
|
|
|
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 QRect& r( option->rect ); |
|
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 ); |
|
|
|
} |
|
|
|
// const bool hover( animations().scrollBarEngine().isHovered( widget, control ) ); |
|
// const bool animated( animations().scrollBarEngine().isAnimated( widget, control ) ); |
|
// const qreal opacity( animations().scrollBarEngine().opacity( widget, control ) ); |
|
|
|
const bool hover( false ); |
|
const bool animated( false ); |
|
const qreal opacity( 1.0 ); |
|
|
|
// retrieve mouse position from engine |
|
// QPoint position( hover ? animations().scrollBarEngine().position( widget ) : QPoint( -1, -1 ) ); |
|
QPoint position; |
|
if( hover && r.contains( position ) ) |
|
{ |
|
// need to update the arrow controlRect on fly because there is no |
|
// way to get it from the styles directly, outside of repaint events |
|
// animations().scrollBarEngine().setSubControlRect( widget, control, r ); |
|
} |
|
|
|
|
|
// if( r.intersects( animations().scrollBarEngine().subControlRect( widget, control ) ) ) |
|
if( false ) |
|
{ |
|
|
|
QColor highlight = _helper->viewHoverBrush().brush( palette ).color(); |
|
if( animated ) |
|
{ |
|
color = KColorUtils::mix( color, highlight, opacity ); |
|
|
|
} else if( hover ) { |
|
|
|
color = highlight; |
|
|
|
} |
|
|
|
} |
|
|
|
return color; |
|
|
|
} |
|
|
|
//____________________________________________________________________________________ |
|
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( -4,2 ) << QPointF( 0, -2 ) << QPointF( 4,2 ); |
|
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( -4,-2 ) << QPointF( 0, 2 ) << QPointF( 4,-2 ); |
|
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, -4 ) << QPointF( -2, 0 ) << QPointF( 2, 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( -2,-4 ) << QPointF( 2, 0 ) << QPointF( -2, 4 ); |
|
break; |
|
} |
|
|
|
default: break; |
|
|
|
} |
|
|
|
return a; |
|
|
|
} |
|
|
|
}
|
|
|