diff --git a/kstyle/animations/breezeanimation.h b/kstyle/animations/breezeanimation.h index 523ddf52..266cfff9 100644 --- a/kstyle/animations/breezeanimation.h +++ b/kstyle/animations/breezeanimation.h @@ -1,63 +1,60 @@ #ifndef breezeanimation_h #define breezeanimation_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breeze.h" #include #include namespace Breeze { class Animation: public QPropertyAnimation { Q_OBJECT public: //* convenience using Pointer = WeakPointer; //* constructor Animation( int duration, QObject* parent ): QPropertyAnimation( parent ) { setDuration( duration ); } - //* destructor - virtual ~Animation() = default; - //* true if running bool isRunning() const { return state() == Animation::Running; } //* restart void restart() { if( isRunning() ) stop(); start(); } }; } #endif diff --git a/kstyle/animations/breezeanimationdata.h b/kstyle/animations/breezeanimationdata.h index f8a1eb66..f44ecf5e 100644 --- a/kstyle/animations/breezeanimationdata.h +++ b/kstyle/animations/breezeanimationdata.h @@ -1,106 +1,101 @@ #ifndef breeze_animationdata_h #define breeze_animationdata_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeanimation.h" #include #include #include #include namespace Breeze { //* base class class AnimationData: public QObject { Q_OBJECT public: //* constructor AnimationData( QObject* parent, QWidget* target ): - QObject( parent ), - _target( target ), - _enabled( true ) - { Q_ASSERT( _target ); } - - //* destructor - virtual ~AnimationData() + QObject( parent ), + _target( target ) {} //* duration virtual void setDuration( int ) = 0; //* steps static void setSteps( int value ) { _steps = value; } //* enability virtual bool enabled() const { return _enabled; } //* enability virtual void setEnabled( bool value ) { _enabled = value; } //* target const WeakPointer& target() const { return _target; } //* invalid opacity static const qreal OpacityInvalid; protected: //* setup animation virtual void setupAnimation( const Animation::Pointer& animation, const QByteArray& property ); //* apply step virtual qreal digitize( const qreal& value ) const { if( _steps > 0 ) return std::floor( value*_steps )/_steps; else return value; } //* trigger target update virtual void setDirty() const { if( _target ) _target.data()->update(); } private: //* guarded target WeakPointer _target; //* enability - bool _enabled; + bool _enabled = true; //* steps static int _steps; }; } #endif diff --git a/kstyle/animations/breezebaseengine.h b/kstyle/animations/breezebaseengine.h index 8d4c0267..15bf8c4a 100644 --- a/kstyle/animations/breezebaseengine.h +++ b/kstyle/animations/breezebaseengine.h @@ -1,91 +1,85 @@ #ifndef breezebaseengine_h #define breezebaseengine_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breeze.h" #include #include namespace Breeze { //* base class for all animation engines /** it is used to store configuration values used by all animations stored in the engine */ class BaseEngine: public QObject { Q_OBJECT public: using Pointer = WeakPointer; //* constructor explicit BaseEngine( QObject* parent ): - QObject( parent ), - _enabled( true ), - _duration( 200 ) - {} - - //* destructor - virtual ~BaseEngine() + QObject( parent ) {} //* enability virtual void setEnabled( bool value ) { _enabled = value; } //* enability virtual bool enabled() const { return _enabled; } //* duration virtual void setDuration( int value ) { _duration = value; } //* duration virtual int duration() const { return _duration; } //* unregister widget virtual bool unregisterWidget( QObject* object ) = 0; //* list of widgets using WidgetList = QSet; //* returns registered widgets virtual WidgetList registeredWidgets() const { return WidgetList(); } private: //* engine enability - bool _enabled; + bool _enabled = true; //* animation duration - int _duration; + int _duration = 200; }; } #endif diff --git a/kstyle/animations/breezebusyindicatorengine.h b/kstyle/animations/breezebusyindicatorengine.h index cc4d1c1d..5f5ff454 100644 --- a/kstyle/animations/breezebusyindicatorengine.h +++ b/kstyle/animations/breezebusyindicatorengine.h @@ -1,103 +1,99 @@ #ifndef breezebusyindicatorengine_h #define breezebusyindicatorengine_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeanimation.h" #include "breezebaseengine.h" #include "breezebusyindicatordata.h" #include "breezedatamap.h" namespace Breeze { //* handles progress bar animations class BusyIndicatorEngine: public BaseEngine { Q_OBJECT //* declare opacity property Q_PROPERTY( int value READ value WRITE setValue ) public: //* constructor explicit BusyIndicatorEngine( QObject* ); - //* destructor - virtual ~BusyIndicatorEngine() - {} - //*@name accessors //@{ //* true if widget is animated - virtual bool isAnimated( const QObject* ); + bool isAnimated( const QObject* ); //* value - virtual int value() const + int value() const { return _value; } //@} //*@name modifiers //@{ //* register progressbar - virtual bool registerWidget( QObject* ); + bool registerWidget( QObject* ); //* duration - virtual void setDuration( int ); + void setDuration( int ) override; //* set object as animated - virtual void setAnimated( const QObject*, bool ); + void setAnimated( const QObject*, bool ); //* opacity - virtual void setValue( int value ); + void setValue( int value ); //@} public Q_SLOTS: //* remove widget from map - virtual bool unregisterWidget( QObject* ); + bool unregisterWidget( QObject* ) override; protected: //* returns data associated to widget DataMap::Value data( const QObject* ); private: //* map widgets to progressbar data DataMap _data; //* animation Animation::Pointer _animation; //* value int _value = 0; }; } #endif diff --git a/kstyle/animations/breezedialdata.h b/kstyle/animations/breezedialdata.h index ec23cf75..72f7c9c6 100644 --- a/kstyle/animations/breezedialdata.h +++ b/kstyle/animations/breezedialdata.h @@ -1,74 +1,68 @@ #ifndef breezedial_data_h #define breezedial_data_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezewidgetstatedata.h" namespace Breeze { //* dial data class DialData: public WidgetStateData { Q_OBJECT public: //* constructor DialData( QObject* parent, QWidget* target, int ); - //* destructor - virtual ~DialData() - {} - //* event filter - virtual bool eventFilter( QObject*, QEvent* ); + bool eventFilter( QObject*, QEvent* ) override; //* subcontrol rect - virtual void setHandleRect( const QRect& rect ) + void setHandleRect( const QRect& rect ) { _handleRect = rect; } //* mouse position QPoint position() const { return _position; } - protected: + private: //* hoverMoveEvent - virtual void hoverMoveEvent( QObject*, QEvent* ); + void hoverMoveEvent( QObject*, QEvent* ); //* hoverMoveEvent - virtual void hoverLeaveEvent( QObject*, QEvent* ); - - private: + void hoverLeaveEvent( QObject*, QEvent* ); //* rect QRect _handleRect; //* mouse position QPoint _position; }; } #endif diff --git a/kstyle/animations/breezeenabledata.h b/kstyle/animations/breezeenabledata.h index fe671994..15578787 100644 --- a/kstyle/animations/breezeenabledata.h +++ b/kstyle/animations/breezeenabledata.h @@ -1,52 +1,48 @@ #ifndef breezeenable_data_h #define breezeenable_data_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezewidgetstatedata.h" namespace Breeze { //* Enable data class EnableData: public WidgetStateData { Q_OBJECT public: //* constructor EnableData( QObject* parent, QWidget* target, int duration, bool state = true ): - WidgetStateData( parent, target, duration, state ) + WidgetStateData( parent, target, duration, state ) { target->installEventFilter( this ); } - //* destructor - virtual ~EnableData() - {} - //* event filter - virtual bool eventFilter( QObject*, QEvent* ); + bool eventFilter( QObject*, QEvent* ) override; }; } #endif diff --git a/kstyle/animations/breezegenericdata.h b/kstyle/animations/breezegenericdata.h index d33c4c62..abdfdb47 100644 --- a/kstyle/animations/breezegenericdata.h +++ b/kstyle/animations/breezegenericdata.h @@ -1,86 +1,82 @@ #ifndef breezegeneric_data_h #define breezegeneric_data_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeanimationdata.h" #include "breezeanimation.h" #include #include namespace Breeze { //* generic data class GenericData: public AnimationData { Q_OBJECT //* declare opacity property Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity ) public: //* constructor GenericData( QObject* parent, QWidget* widget, int duration ); - //* destructor - virtual ~GenericData() - {} - //* return animation object - virtual const Animation::Pointer& animation() const + const Animation::Pointer& animation() const { return _animation; } //* duration - virtual void setDuration( int duration ) + void setDuration( int duration ) override { _animation.data()->setDuration( duration ); } //* opacity - virtual qreal opacity() const + qreal opacity() const { return _opacity; } //* opacity - virtual void setOpacity( qreal value ) + void setOpacity( qreal value ) { value = digitize( value ); if( _opacity == value ) return; _opacity = value; setDirty(); } private: //* animation handling Animation::Pointer _animation; //* opacity variable - qreal _opacity; + qreal _opacity = 0; }; } #endif diff --git a/kstyle/animations/breezeheaderviewdata.h b/kstyle/animations/breezeheaderviewdata.h index 549a26d4..404f8409 100644 --- a/kstyle/animations/breezeheaderviewdata.h +++ b/kstyle/animations/breezeheaderviewdata.h @@ -1,157 +1,153 @@ #ifndef breezeheaderview_data_h #define breezeheaderview_data_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeanimationdata.h" #include namespace Breeze { //* headerviews class HeaderViewData: public AnimationData { Q_OBJECT //* declare opacity property Q_PROPERTY( qreal currentOpacity READ currentOpacity WRITE setCurrentOpacity ) Q_PROPERTY( qreal previousOpacity READ previousOpacity WRITE setPreviousOpacity ) public: //* constructor HeaderViewData( QObject* parent, QWidget* target, int duration ); - //* destructor - virtual ~HeaderViewData() - {} - //* duration - void setDuration( int duration ) + void setDuration( int duration ) override { currentIndexAnimation().data()->setDuration( duration ); previousIndexAnimation().data()->setDuration( duration ); } //* update state bool updateState( const QPoint&, bool ); //*@name current index handling //@{ //* current opacity - virtual qreal currentOpacity() const + qreal currentOpacity() const { return _current._opacity; } //* current opacity - virtual void setCurrentOpacity( qreal value ) + void setCurrentOpacity( qreal value ) { value = digitize( value ); if( _current._opacity == value ) return; _current._opacity = value; setDirty(); } //* current index - virtual int currentIndex() const + int currentIndex() const { return _current._index; } //* current index - virtual void setCurrentIndex( int index ) + void setCurrentIndex( int index ) { _current._index = index; } //* current index animation - virtual const Animation::Pointer& currentIndexAnimation() const + const Animation::Pointer& currentIndexAnimation() const { return _current._animation; } //@} //*@name previous index handling //@{ //* previous opacity - virtual qreal previousOpacity() const + qreal previousOpacity() const { return _previous._opacity; } //* previous opacity - virtual void setPreviousOpacity( qreal value ) + void setPreviousOpacity( qreal value ) { value = digitize( value ); if( _previous._opacity == value ) return; _previous._opacity = value; setDirty(); } //* previous index - virtual int previousIndex() const + int previousIndex() const { return _previous._index; } //* previous index - virtual void setPreviousIndex( int index ) + void setPreviousIndex( int index ) { _previous._index = index; } //* previous index Animation - virtual const Animation::Pointer& previousIndexAnimation() const + const Animation::Pointer& previousIndexAnimation() const { return _previous._animation; } //@} //* return Animation associated to action at given position, if any - virtual Animation::Pointer animation( const QPoint& position ) const; + Animation::Pointer animation( const QPoint& position ) const; //* return opacity associated to action at given position, if any - virtual qreal opacity( const QPoint& position ) const; + qreal opacity( const QPoint& position ) const; protected: //* dirty - virtual void setDirty() const; + void setDirty() const override; private: //* container for needed animation data class Data { public: //* default constructor Data(): _opacity(0), _index(-1) {} Animation::Pointer _animation; qreal _opacity; int _index; }; //* current tab animation data (for hover enter animations) Data _current; //* previous tab animations data (for hover leave animations) Data _previous; }; } #endif diff --git a/kstyle/animations/breezeheaderviewengine.h b/kstyle/animations/breezeheaderviewengine.h index b3860128..f96f9f19 100644 --- a/kstyle/animations/breezeheaderviewengine.h +++ b/kstyle/animations/breezeheaderviewengine.h @@ -1,94 +1,90 @@ #ifndef breezeheaderviewengine_h #define breezeheaderviewengine_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezebaseengine.h" #include "breezedatamap.h" #include "breezeheaderviewdata.h" namespace Breeze { //* stores headerview hovered action and timeLine class HeaderViewEngine: public BaseEngine { Q_OBJECT public: //* constructor explicit HeaderViewEngine( QObject* parent ): BaseEngine( parent ) {} - //* destructor - virtual ~HeaderViewEngine() - {} - //* register headerview - virtual bool registerWidget( QWidget* ); + bool registerWidget( QWidget* ); //* true if widget hover state is changed - virtual bool updateState( const QObject*, const QPoint&, bool ); + bool updateState( const QObject*, const QPoint&, bool ); //* true if widget is animated - virtual bool isAnimated( const QObject* object, const QPoint& point ) + bool isAnimated( const QObject* object, const QPoint& point ) { if( DataMap::Value data = _data.find( object ) ) { if( Animation::Pointer animation = data.data()->animation( point ) ) return animation.data()->isRunning(); } return false; } //* animation opacity - virtual qreal opacity( const QObject* object, const QPoint& point ) + qreal opacity( const QObject* object, const QPoint& point ) { return isAnimated( object, point ) ? _data.find( object ).data()->opacity( point ) : AnimationData::OpacityInvalid; } //* enability - virtual void setEnabled( bool value ) + void setEnabled( bool value ) override { BaseEngine::setEnabled( value ); _data.setEnabled( value ); } //* duration - virtual void setDuration( int value ) + void setDuration( int value ) override { BaseEngine::setDuration( value ); _data.setDuration( value ); } public Q_SLOTS: //* remove widget from map - virtual bool unregisterWidget( QObject* object ) + bool unregisterWidget( QObject* object ) override { return _data.unregisterWidget( object ); } private: //* data map DataMap _data; }; } #endif diff --git a/kstyle/animations/breezescrollbardata.h b/kstyle/animations/breezescrollbardata.h index 3e62fbc5..149c3031 100644 --- a/kstyle/animations/breezescrollbardata.h +++ b/kstyle/animations/breezescrollbardata.h @@ -1,266 +1,260 @@ #ifndef breezescrollbar_data_h #define breezescrollbar_data_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezewidgetstatedata.h" #include namespace Breeze { //* scrollbar data class ScrollBarData: public WidgetStateData { Q_OBJECT Q_PROPERTY( qreal addLineOpacity READ addLineOpacity WRITE setAddLineOpacity ) Q_PROPERTY( qreal subLineOpacity READ subLineOpacity WRITE setSubLineOpacity ) Q_PROPERTY( qreal grooveOpacity READ grooveOpacity WRITE setGrooveOpacity ) public: //* constructor ScrollBarData( QObject* parent, QWidget* target, int ); - //* destructor - virtual ~ScrollBarData() - {} - //* event filter - virtual bool eventFilter( QObject*, QEvent* ); + bool eventFilter( QObject*, QEvent* ) override; //* needed to avoid warning about virtual function being hidden using WidgetStateData::animation; using WidgetStateData::opacity; //* return animation for a given subcontrol - virtual const Animation::Pointer& animation( QStyle::SubControl ) const; + const Animation::Pointer& animation( QStyle::SubControl ) const; //* return default opacity for a given subcontrol - virtual qreal opacity( QStyle::SubControl ) const; + qreal opacity( QStyle::SubControl ) const; //* return default opacity for a given subcontrol - virtual bool isHovered( QStyle::SubControl control ) const + bool isHovered( QStyle::SubControl control ) const { switch( control ) { case QStyle::SC_ScrollBarAddLine: return addLineArrowHovered(); case QStyle::SC_ScrollBarSubLine: return subLineArrowHovered(); case QStyle::SC_ScrollBarGroove: return grooveHovered(); default: return false; } } //* subControlRect - virtual QRect subControlRect( QStyle::SubControl control ) const + QRect subControlRect( QStyle::SubControl control ) const { switch( control ) { case QStyle::SC_ScrollBarAddLine: return _addLineData._rect; case QStyle::SC_ScrollBarSubLine: return _subLineData._rect; default: return QRect(); } } //* subcontrol rect - virtual void setSubControlRect( QStyle::SubControl control, const QRect& rect ) + void setSubControlRect( QStyle::SubControl control, const QRect& rect ) { switch( control ) { case QStyle::SC_ScrollBarAddLine: _addLineData._rect = rect; break; case QStyle::SC_ScrollBarSubLine: _subLineData._rect = rect; break; default: break; } } //* duration - virtual void setDuration( int duration ) + void setDuration( int duration ) override { WidgetStateData::setDuration( duration ); addLineAnimation().data()->setDuration( duration ); subLineAnimation().data()->setDuration( duration ); grooveAnimation().data()->setDuration( duration ); } //* addLine opacity - virtual void setAddLineOpacity( qreal value ) + void setAddLineOpacity( qreal value ) { value = digitize( value ); if( _addLineData._opacity == value ) return; _addLineData._opacity = value; setDirty(); } //* addLine opacity - virtual qreal addLineOpacity() const + qreal addLineOpacity() const { return _addLineData._opacity; } //* subLine opacity - virtual void setSubLineOpacity( qreal value ) + void setSubLineOpacity( qreal value ) { value = digitize( value ); if( _subLineData._opacity == value ) return; _subLineData._opacity = value; setDirty(); } //* subLine opacity - virtual qreal subLineOpacity() const + qreal subLineOpacity() const { return _subLineData._opacity; } //* groove opacity - virtual void setGrooveOpacity( qreal value ) + void setGrooveOpacity( qreal value ) { value = digitize( value ); if( _grooveData._opacity == value ) return; _grooveData._opacity = value; setDirty(); } //* groove opacity - virtual qreal grooveOpacity() const + qreal grooveOpacity() const { return _grooveData._opacity; } //* mouse position QPoint position() const { return _position; } protected Q_SLOTS: //* clear addLineRect void clearAddLineRect() { if( addLineAnimation().data()->direction() == Animation::Backward ) { _addLineData._rect = QRect(); } } //* clear subLineRect void clearSubLineRect() { if( subLineAnimation().data()->direction() == Animation::Backward ) { _subLineData._rect = QRect(); } } - protected: + private: //* hoverMoveEvent - virtual void hoverMoveEvent( QObject*, QEvent* ); + void hoverMoveEvent( QObject*, QEvent* ); //* hoverMoveEvent - virtual void hoverLeaveEvent( QObject*, QEvent* ); + void hoverLeaveEvent( QObject*, QEvent* ); //*@name hover flags //@{ - virtual bool addLineArrowHovered() const + bool addLineArrowHovered() const { return _addLineData._hovered; } - virtual void setAddLineArrowHovered( bool value ) + void setAddLineArrowHovered( bool value ) { _addLineData._hovered = value; } - virtual bool subLineArrowHovered() const + bool subLineArrowHovered() const { return _subLineData._hovered; } - virtual void setSubLineArrowHovered( bool value ) + void setSubLineArrowHovered( bool value ) { _subLineData._hovered = value; } - virtual bool grooveHovered() const + bool grooveHovered() const { return _grooveData._hovered; } - virtual void setGrooveHovered( bool value ) + void setGrooveHovered( bool value ) { _grooveData._hovered = value; } //@} //* update add line arrow - virtual void updateAddLineArrow( QStyle::SubControl ); + void updateAddLineArrow( QStyle::SubControl ); //* update sub line arrow - virtual void updateSubLineArrow( QStyle::SubControl ); + void updateSubLineArrow( QStyle::SubControl ); //*@name timelines //@{ - virtual const Animation::Pointer& addLineAnimation() const + const Animation::Pointer& addLineAnimation() const { return _addLineData._animation; } - virtual const Animation::Pointer& subLineAnimation() const + const Animation::Pointer& subLineAnimation() const { return _subLineData._animation; } - virtual const Animation::Pointer& grooveAnimation() const + const Animation::Pointer& grooveAnimation() const { return _grooveData._animation; } - private: - //* stores sub control data class Data { public: //* constructor Data(): _hovered( false ), _opacity( AnimationData::OpacityInvalid ) {} //* true if hovered bool _hovered; //* animation Animation::Pointer _animation; //* opacity qreal _opacity; //* rect QRect _rect; }; //* add line data (down arrow) Data _addLineData; //* subtract line data (up arrow) Data _subLineData; //* groove data Data _grooveData; //* mouse position QPoint _position; }; } #endif diff --git a/kstyle/animations/breezespinboxdata.h b/kstyle/animations/breezespinboxdata.h index c8d7f64c..e45d5cca 100644 --- a/kstyle/animations/breezespinboxdata.h +++ b/kstyle/animations/breezespinboxdata.h @@ -1,163 +1,159 @@ #ifndef breezespinbox_data_h #define breezespinbox_data_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeanimationdata.h" #include namespace Breeze { //* handles spinbox arrows hover class SpinBoxData: public AnimationData { Q_OBJECT //* declare opacity property Q_PROPERTY( qreal upArrowOpacity READ upArrowOpacity WRITE setUpArrowOpacity ) Q_PROPERTY( qreal downArrowOpacity READ downArrowOpacity WRITE setDownArrowOpacity ) public: //* constructor SpinBoxData( QObject*, QWidget*, int ); - //* destructor - virtual ~SpinBoxData() - {} - //* animation state - virtual bool updateState( QStyle::SubControl subControl, bool value ) + bool updateState( QStyle::SubControl subControl, bool value ) { if( subControl == QStyle::SC_SpinBoxUp ) return _upArrowData.updateState( value ); else if( subControl == QStyle::SC_SpinBoxDown ) return _downArrowData.updateState( value ); else return false; } //* animation state - virtual bool isAnimated( QStyle::SubControl subControl ) const + bool isAnimated( QStyle::SubControl subControl ) const { return( ( subControl == QStyle::SC_SpinBoxUp && upArrowAnimation().data()->isRunning() ) || ( subControl == QStyle::SC_SpinBoxDown && downArrowAnimation().data()->isRunning() ) ); } //* opacity - virtual qreal opacity( QStyle::SubControl subControl ) const + qreal opacity( QStyle::SubControl subControl ) const { if( subControl == QStyle::SC_SpinBoxUp ) return upArrowOpacity(); else if( subControl == QStyle::SC_SpinBoxDown ) return downArrowOpacity(); else return OpacityInvalid; } //* duration - virtual void setDuration( int duration ) + void setDuration( int duration ) override { upArrowAnimation().data()->setDuration( duration ); downArrowAnimation().data()->setDuration( duration ); } //*@name up arrow animation //@{ //* opacity qreal upArrowOpacity() const { return _upArrowData._opacity; } //* opacity void setUpArrowOpacity( qreal value ) { value = digitize( value ); if( _upArrowData._opacity == value ) return; _upArrowData._opacity = value; setDirty(); } //* animation Animation::Pointer upArrowAnimation() const { return _upArrowData._animation; } //@} //*@name down arrow animation //@{ //* opacity qreal downArrowOpacity() const { return _downArrowData._opacity; } //* opacity void setDownArrowOpacity( qreal value ) { value = digitize( value ); if( _downArrowData._opacity == value ) return; _downArrowData._opacity = value; setDirty(); } //* animation Animation::Pointer downArrowAnimation() const { return _downArrowData._animation; } //@} private: //* container for needed animation data class Data { public: //* default constructor Data(): _state( false ), _opacity(0) {} //* state bool updateState( bool ); //* arrow state bool _state; //* animation Animation::Pointer _animation; //* opacity qreal _opacity; }; //* up arrow data Data _upArrowData; //* down arrow data Data _downArrowData; }; } #endif diff --git a/kstyle/animations/breezespinboxengine.h b/kstyle/animations/breezespinboxengine.h index 4592f1de..c195d659 100644 --- a/kstyle/animations/breezespinboxengine.h +++ b/kstyle/animations/breezespinboxengine.h @@ -1,108 +1,104 @@ #ifndef breezespinboxengine_h #define breezespinboxengine_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezebaseengine.h" #include "breezedatamap.h" #include "breezespinboxdata.h" namespace Breeze { //* handle spinbox arrows hover effect class SpinBoxEngine: public BaseEngine { Q_OBJECT public: //* constructor explicit SpinBoxEngine( QObject* parent ): BaseEngine( parent ) {} - //* destructor - virtual ~SpinBoxEngine() - {} - //* register widget - virtual bool registerWidget( QWidget* ); + bool registerWidget( QWidget* ); //* state - virtual bool updateState( const QObject* object, QStyle::SubControl subControl, bool value ) + bool updateState( const QObject* object, QStyle::SubControl subControl, bool value ) { if( DataMap::Value data = _data.find( object ) ) { return data.data()->updateState( subControl, value ); } else return false; } //* true if widget is animated - virtual bool isAnimated( const QObject* object, QStyle::SubControl subControl ) + bool isAnimated( const QObject* object, QStyle::SubControl subControl ) { if( DataMap::Value data = _data.find( object ) ) { return data.data()->isAnimated( subControl ); } else return false; } //* animation opacity - virtual qreal opacity( const QObject* object, QStyle::SubControl subControl ) + qreal opacity( const QObject* object, QStyle::SubControl subControl ) { if( DataMap::Value data = _data.find( object ) ) { return data.data()->opacity( subControl ); } else return AnimationData::OpacityInvalid; } //* enability - virtual void setEnabled( bool value ) + void setEnabled( bool value ) override { BaseEngine::setEnabled( value ); _data.setEnabled( value ); } //* duration - virtual void setDuration( int value ) + void setDuration( int value ) override { BaseEngine::setDuration( value ); _data.setDuration( value ); } public Q_SLOTS: //* remove widget from map - virtual bool unregisterWidget( QObject* object ) + bool unregisterWidget( QObject* object ) override { return _data.unregisterWidget( object ); } private: //* data map DataMap _data; }; } #endif diff --git a/kstyle/animations/breezestackedwidgetdata.h b/kstyle/animations/breezestackedwidgetdata.h index d00e4bf6..15c6de74 100644 --- a/kstyle/animations/breezestackedwidgetdata.h +++ b/kstyle/animations/breezestackedwidgetdata.h @@ -1,78 +1,74 @@ #ifndef breezestackedwidget_datah #define breezestackedwidget_datah ////////////////////////////////////////////////////////////////////////////// // breezestackedwidgetdata.h // data container for QStackedWidget transition // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "breezetransitiondata.h" #include namespace Breeze { - //! generic data + //* generic data class StackedWidgetData: public TransitionData { Q_OBJECT public: - //! constructor + //* constructor StackedWidgetData( QObject*, QStackedWidget*, int ); - //! destructor - virtual ~StackedWidgetData() - {} - protected Q_SLOTS: - //! initialize animation - virtual bool initializeAnimation(); + //* initialize animation + bool initializeAnimation() override; - //! animate - virtual bool animate(); + //* animate + bool animate() override; - //! finish animation - virtual void finishAnimation(); + //* finish animation + void finishAnimation(); - //! called when target is destroyed - virtual void targetDestroyed(); + //* called when target is destroyed + void targetDestroyed(); private: - //! target + //* target WeakPointer _target; - //! current index + //* current index int _index; }; } #endif diff --git a/kstyle/animations/breezestackedwidgetengine.h b/kstyle/animations/breezestackedwidgetengine.h index 5099493e..d8260cb4 100644 --- a/kstyle/animations/breezestackedwidgetengine.h +++ b/kstyle/animations/breezestackedwidgetengine.h @@ -1,86 +1,82 @@ #ifndef breezestackedwidgetengine_h #define breezestackedwidgetengine_h ////////////////////////////////////////////////////////////////////////////// // breezestackedwidgetengine.h // stores event filters and maps widgets to animations // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "breezebaseengine.h" #include "breezedatamap.h" #include "breezestackedwidgetdata.h" namespace Breeze { - //! used for simple widgets + //* used for simple widgets class StackedWidgetEngine: public BaseEngine { Q_OBJECT public: - //! constructor + //* constructor explicit StackedWidgetEngine( QObject* parent ): BaseEngine( parent ) {} - //! destructor - virtual ~StackedWidgetEngine() - {} - - //! register widget - virtual bool registerWidget( QStackedWidget* ); + //* register widget + bool registerWidget( QStackedWidget* ); - //! duration - virtual void setEnabled( bool value ) + //* duration + void setEnabled( bool value ) override { BaseEngine::setEnabled( value ); _data.setEnabled( value ); } - //! duration - virtual void setDuration( int value ) + //* duration + void setDuration( int value ) override { BaseEngine::setDuration( value ); _data.setDuration( value ); } public Q_SLOTS: - //! remove widget from map - virtual bool unregisterWidget( QObject* object ) + //* remove widget from map + bool unregisterWidget( QObject* object ) override { return _data.unregisterWidget( object ); } private: - //! maps + //* maps DataMap _data; }; } #endif diff --git a/kstyle/animations/breezetabbardata.h b/kstyle/animations/breezetabbardata.h index 1f488be4..0764b1b9 100644 --- a/kstyle/animations/breezetabbardata.h +++ b/kstyle/animations/breezetabbardata.h @@ -1,151 +1,147 @@ #ifndef breezetabbar_data_h #define breezetabbar_data_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeanimationdata.h" #include namespace Breeze { //* tabbars class TabBarData: public AnimationData { Q_OBJECT //* declare opacity property Q_PROPERTY( qreal currentOpacity READ currentOpacity WRITE setCurrentOpacity ) Q_PROPERTY( qreal previousOpacity READ previousOpacity WRITE setPreviousOpacity ) public: //* constructor TabBarData( QObject* parent, QWidget* target, int duration ); - //* destructor - virtual ~TabBarData() - {} - //* duration - void setDuration( int duration ) + void setDuration( int duration ) override { currentIndexAnimation().data()->setDuration( duration ); previousIndexAnimation().data()->setDuration( duration ); } //* update state bool updateState( const QPoint&, bool ); //*@name current index handling //@{ //* current opacity - virtual qreal currentOpacity() const + qreal currentOpacity() const { return _current._opacity; } //* current opacity - virtual void setCurrentOpacity( qreal value ) + void setCurrentOpacity( qreal value ) { if( _current._opacity == value ) return; _current._opacity = value; setDirty(); } //* current index - virtual int currentIndex() const + int currentIndex() const { return _current._index; } //* current index - virtual void setCurrentIndex( int index ) + void setCurrentIndex( int index ) { _current._index = index; } //* current index animation - virtual const Animation::Pointer& currentIndexAnimation() const + const Animation::Pointer& currentIndexAnimation() const { return _current._animation; } //@} //*@name previous index handling //@{ //* previous opacity - virtual qreal previousOpacity() const + qreal previousOpacity() const { return _previous._opacity; } //* previous opacity - virtual void setPreviousOpacity( qreal value ) + void setPreviousOpacity( qreal value ) { if( _previous._opacity == value ) return; _previous._opacity = value; setDirty(); } //* previous index - virtual int previousIndex() const + int previousIndex() const { return _previous._index; } //* previous index - virtual void setPreviousIndex( int index ) + void setPreviousIndex( int index ) { _previous._index = index; } //* previous index Animation - virtual const Animation::Pointer& previousIndexAnimation() const + const Animation::Pointer& previousIndexAnimation() const { return _previous._animation; } //@} //* return Animation associated to action at given position, if any - virtual Animation::Pointer animation( const QPoint& position ) const; + Animation::Pointer animation( const QPoint& position ) const; //* return opacity associated to action at given position, if any - virtual qreal opacity( const QPoint& position ) const; + qreal opacity( const QPoint& position ) const; private: //* container for needed animation data class Data { public: //* default constructor Data(): _opacity(0), _index(-1) {} Animation::Pointer _animation; qreal _opacity; int _index; }; //* current tab animation data (for hover enter animations) Data _current; //* previous tab animations data (for hover leave animations) Data _previous; }; } #endif diff --git a/kstyle/animations/breezetabbarengine.h b/kstyle/animations/breezetabbarengine.h index 4fa7d6b8..68d74e9c 100644 --- a/kstyle/animations/breezetabbarengine.h +++ b/kstyle/animations/breezetabbarengine.h @@ -1,102 +1,98 @@ #ifndef breezetabbarengine_h #define breezetabbarengine_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breeze.h" #include "breezebaseengine.h" #include "breezedatamap.h" #include "breezetabbardata.h" namespace Breeze { //* stores tabbar hovered action and timeLine class TabBarEngine: public BaseEngine { Q_OBJECT public: //* constructor explicit TabBarEngine( QObject* parent ): BaseEngine( parent ) {} - //* destructor - virtual ~TabBarEngine() - {} - //* register tabbar - virtual bool registerWidget( QWidget* ); + bool registerWidget( QWidget* ); //* true if widget hover state is changed - virtual bool updateState( const QObject*, const QPoint&, AnimationMode, bool ); + bool updateState( const QObject*, const QPoint&, AnimationMode, bool ); //* true if widget is animated - virtual bool isAnimated( const QObject* object, const QPoint& point, AnimationMode ); + bool isAnimated( const QObject* object, const QPoint& point, AnimationMode ); //* animation opacity - virtual qreal opacity( const QObject* object, const QPoint& point, AnimationMode mode ) + qreal opacity( const QObject* object, const QPoint& point, AnimationMode mode ) { return isAnimated( object, point, mode ) ? data( object, mode ).data()->opacity( point ) : AnimationData::OpacityInvalid; } //* enability - virtual void setEnabled( bool value ) + void setEnabled( bool value ) override { BaseEngine::setEnabled( value ); _hoverData.setEnabled( value ); _focusData.setEnabled( value ); } //* duration - virtual void setDuration( int value ) + void setDuration( int value ) override { BaseEngine::setDuration( value ); _hoverData.setDuration( value ); _focusData.setDuration( value ); } public Q_SLOTS: //* remove widget from map - virtual bool unregisterWidget( QObject* object ) + bool unregisterWidget( QObject* object ) override { if( !object ) return false; bool found = false; if( _hoverData.unregisterWidget( object ) ) found = true; if( _focusData.unregisterWidget( object ) ) found = true; return found; } private: //* returns data associated to widget DataMap::Value data( const QObject*, AnimationMode ); //* data map DataMap _hoverData; DataMap _focusData; }; } #endif diff --git a/kstyle/animations/breezetoolboxengine.h b/kstyle/animations/breezetoolboxengine.h index db5c09bc..3880d700 100644 --- a/kstyle/animations/breezetoolboxengine.h +++ b/kstyle/animations/breezetoolboxengine.h @@ -1,103 +1,99 @@ #ifndef breezetoolboxengine_h #define breezetoolboxengine_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezebaseengine.h" #include "breezedatamap.h" #include "breezewidgetstatedata.h" namespace Breeze { //* QToolBox animation engine class ToolBoxEngine: public BaseEngine { Q_OBJECT public: //* constructor explicit ToolBoxEngine( QObject* parent ): BaseEngine( parent ) {} - //* destructor - virtual ~ToolBoxEngine() - {} - //* enability - virtual void setEnabled( bool value ) + void setEnabled( bool value ) override { BaseEngine::setEnabled( value ); _data.setEnabled( value ); } //* duration - virtual void setDuration( int value ) + void setDuration( int value ) override { BaseEngine::setDuration( value ); _data.setDuration( value ); } //* register widget - virtual bool registerWidget( QWidget* ); + bool registerWidget( QWidget* ); //* true if widget hover state is changed - virtual bool updateState( const QPaintDevice*, bool ); + bool updateState( const QPaintDevice*, bool ); //* true if widget is animated - virtual bool isAnimated( const QPaintDevice* ); + bool isAnimated( const QPaintDevice* ); //* animation opacity - virtual qreal opacity( const QPaintDevice* object ) + qreal opacity( const QPaintDevice* object ) { return isAnimated( object ) ? data( object ).data()->opacity(): AnimationData::OpacityInvalid; } public Q_SLOTS: //* remove widget from map - virtual bool unregisterWidget( QObject* data ) + bool unregisterWidget( QObject* data ) override { if( !data ) return false; // reinterpret_cast is safe here since only the address is used to find // data in the map return _data.unregisterWidget( reinterpret_cast(data) ); } protected: //* returns data associated to widget PaintDeviceDataMap::Value data( const QPaintDevice* object ) { return _data.find( object ).data(); } private: //* map PaintDeviceDataMap _data; }; } #endif diff --git a/kstyle/animations/breezetransitionwidget.h b/kstyle/animations/breezetransitionwidget.h index c3e2443e..0c68774f 100644 --- a/kstyle/animations/breezetransitionwidget.h +++ b/kstyle/animations/breezetransitionwidget.h @@ -1,235 +1,232 @@ #ifndef breezetransitionwidget_h #define breezetransitionwidget_h ////////////////////////////////////////////////////////////////////////////// // breezetransitionwidget.h // stores event filters and maps widgets to transitions for transitions // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "breezeanimation.h" #include "breeze.h" #include #include namespace Breeze { //* temporary widget used to perform smooth transition between one widget state and another class TransitionWidget: public QWidget { Q_OBJECT //* declare opacity property Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity ) public: //* shortcut to painter typedef WeakPointer Pointer; //* constructor TransitionWidget( QWidget* parent, int duration ); - //* destructor - virtual ~TransitionWidget() = default; - //*@name flags //@{ enum Flag { None = 0, GrabFromWindow = 1<<0, Transparent = 1<<1, PaintOnWidget = 1<<2 }; Q_DECLARE_FLAGS(Flags, Flag) void setFlags( Flags value ) { _flags = value; } void setFlag( Flag flag, bool value = true ) { if( value ) _flags |= flag; else _flags &= (~flag); } bool testFlag( Flag flag ) const { return _flags.testFlag( flag ); } //@} //* duration void setDuration( int duration ) { if( _animation ) { _animation.data()->setDuration( duration ); } } //* duration int duration() const { return ( _animation ) ? _animation.data()->duration() : 0; } //* steps static void setSteps( int value ) { _steps = value; } //*@name opacity //@{ - virtual qreal opacity() const + qreal opacity() const { return _opacity; } - virtual void setOpacity( qreal value ) + void setOpacity( qreal value ) { value = digitize( value ); if( _opacity == value ) return; _opacity = value; update(); } //@} //@name pixmaps handling //@{ //* start void resetStartPixmap() { setStartPixmap( QPixmap() ); } //* start void setStartPixmap( QPixmap pixmap ) { _startPixmap = pixmap; } //* start const QPixmap& startPixmap() const { return _startPixmap; } //* end void resetEndPixmap() { setEndPixmap( QPixmap() ); } //* end void setEndPixmap( QPixmap pixmap ) { _endPixmap = pixmap; _currentPixmap = pixmap; } //* start const QPixmap& endPixmap() const { return _endPixmap; } //* current const QPixmap& currentPixmap() const { return _currentPixmap; } //@} //* grap pixmap QPixmap grab( QWidget* = nullptr, QRect = QRect() ); //* true if animated - virtual bool isAnimated() const + bool isAnimated() const { return _animation.data()->isRunning(); } //* end animation - virtual void endAnimation() + void endAnimation() { if( _animation.data()->isRunning() ) _animation.data()->stop(); } //* animate transition - virtual void animate() + void animate() { if( _animation.data()->isRunning() ) _animation.data()->stop(); _animation.data()->start(); } //* true if paint is enabled static bool paintEnabled(); protected: //* generic event filter - virtual bool event( QEvent* ); + bool event( QEvent* ) override; //* paint event - virtual void paintEvent( QPaintEvent* ); + void paintEvent( QPaintEvent* ) override; //* grab widget background /*! Background is not rendered properly using QWidget::render. Use home-made grabber instead. This is directly inspired from bespin. Copyright (C) 2007 Thomas Luebking */ - virtual void grabBackground( QPixmap&, QWidget*, QRect& ) const; + void grabBackground( QPixmap&, QWidget*, QRect& ) const; //* grab widget - virtual void grabWidget( QPixmap&, QWidget*, QRect& ) const; + void grabWidget( QPixmap&, QWidget*, QRect& ) const; //* fade pixmap - virtual void fade( const QPixmap& source, QPixmap& target, qreal opacity, const QRect& ) const; + void fade( const QPixmap& source, QPixmap& target, qreal opacity, const QRect& ) const; //* apply step - virtual qreal digitize( const qreal& value ) const + qreal digitize( const qreal& value ) const { if( _steps > 0 ) return std::floor( value*_steps )/_steps; else return value; } private: //* Flags Flags _flags = None; //* paint enabled static bool _paintEnabled; //* internal transition animation Animation::Pointer _animation; //* animation starting pixmap QPixmap _startPixmap; //* animation starting pixmap QPixmap _localStartPixmap; //* animation starting pixmap QPixmap _endPixmap; //* current pixmap QPixmap _currentPixmap; //* current state opacity qreal _opacity = 0; //* steps static int _steps; }; } #endif diff --git a/kstyle/animations/breezewidgetstateengine.h b/kstyle/animations/breezewidgetstateengine.h index e7881c78..b8324ca4 100644 --- a/kstyle/animations/breezewidgetstateengine.h +++ b/kstyle/animations/breezewidgetstateengine.h @@ -1,160 +1,156 @@ #ifndef breezewidgetstateengine_h #define breezewidgetstateengine_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breeze.h" #include "breezebaseengine.h" #include "breezedatamap.h" #include "breezewidgetstatedata.h" namespace Breeze { //* used for simple widgets class WidgetStateEngine: public BaseEngine { Q_OBJECT public: //* constructor explicit WidgetStateEngine( QObject* parent ): BaseEngine( parent ) {} - //* destructor - virtual ~WidgetStateEngine() - {} - //* register widget - virtual bool registerWidget( QWidget*, AnimationModes ); + bool registerWidget( QWidget*, AnimationModes ); //* returns registered widgets - virtual WidgetList registeredWidgets( AnimationModes ) const; + WidgetList registeredWidgets( AnimationModes ) const; using BaseEngine::registeredWidgets; //* true if widget hover state is changed - virtual bool updateState( const QObject*, AnimationMode, bool ); + bool updateState( const QObject*, AnimationMode, bool ); //* true if widget is animated - virtual bool isAnimated( const QObject*, AnimationMode ); + bool isAnimated( const QObject*, AnimationMode ); //* animation opacity - virtual qreal opacity( const QObject* object, AnimationMode mode ) + qreal opacity( const QObject* object, AnimationMode mode ) { return isAnimated( object, mode ) ? data( object, mode ).data()->opacity(): AnimationData::OpacityInvalid; } //* animation mode /** precedence on focus */ - virtual AnimationMode frameAnimationMode( const QObject* object ) + AnimationMode frameAnimationMode( const QObject* object ) { if( isAnimated( object, AnimationEnable ) ) return AnimationEnable; else if( isAnimated( object, AnimationFocus ) ) return AnimationFocus; else if( isAnimated( object, AnimationHover ) ) return AnimationHover; else return AnimationNone; } //* animation opacity /** precedence on focus */ - virtual qreal frameOpacity( const QObject* object ) + qreal frameOpacity( const QObject* object ) { if( isAnimated( object, AnimationEnable ) ) return data( object, AnimationEnable ).data()->opacity(); else if( isAnimated( object, AnimationFocus ) ) return data( object, AnimationFocus ).data()->opacity(); else if( isAnimated( object, AnimationHover ) ) return data( object, AnimationHover ).data()->opacity(); else return AnimationData::OpacityInvalid; } //* animation mode /** precedence on mouseOver */ - virtual AnimationMode buttonAnimationMode( const QObject* object ) + AnimationMode buttonAnimationMode( const QObject* object ) { if( isAnimated( object, AnimationEnable ) ) return AnimationEnable; else if( isAnimated( object, AnimationHover ) ) return AnimationHover; else if( isAnimated( object, AnimationFocus ) ) return AnimationFocus; else return AnimationNone; } //* animation opacity /** precedence on mouseOver */ - virtual qreal buttonOpacity( const QObject* object ) + qreal buttonOpacity( const QObject* object ) { if( isAnimated( object, AnimationEnable ) ) return data( object, AnimationEnable ).data()->opacity(); else if( isAnimated( object, AnimationHover ) ) return data( object, AnimationHover ).data()->opacity(); else if( isAnimated( object, AnimationFocus ) ) return data( object, AnimationFocus ).data()->opacity(); else return AnimationData::OpacityInvalid; } //* duration - virtual void setEnabled( bool value ) + void setEnabled( bool value ) override { BaseEngine::setEnabled( value ); _hoverData.setEnabled( value ); _focusData.setEnabled( value ); _enableData.setEnabled( value ); _pressedData.setEnabled( value ); } //* duration - virtual void setDuration( int value ) + void setDuration( int value ) override { BaseEngine::setDuration( value ); _hoverData.setDuration( value ); _focusData.setDuration( value ); _enableData.setDuration( value ); _pressedData.setDuration( value/2 ); } public Q_SLOTS: //* remove widget from map - virtual bool unregisterWidget( QObject* object ) + bool unregisterWidget( QObject* object ) override { if( !object ) return false; bool found = false; if( _hoverData.unregisterWidget( object ) ) found = true; if( _focusData.unregisterWidget( object ) ) found = true; if( _enableData.unregisterWidget( object ) ) found = true; if( _pressedData.unregisterWidget( object ) ) found = true; return found; } protected: //* returns data associated to widget DataMap::Value data( const QObject*, AnimationMode ); //* returns data map associated to animation mode DataMap& dataMap( AnimationMode ); private: //* maps DataMap _hoverData; DataMap _focusData; DataMap _enableData; DataMap _pressedData; }; } #endif diff --git a/kstyle/breezeaddeventfilter.h b/kstyle/breezeaddeventfilter.h index 61012c4f..d7175286 100644 --- a/kstyle/breezeaddeventfilter.h +++ b/kstyle/breezeaddeventfilter.h @@ -1,54 +1,50 @@ #ifndef breezeaddeventfilter_h #define breezeaddeventfilter_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include #include namespace Breeze { class AddEventFilter: public QObject { Q_OBJECT public: //* constructor AddEventFilter(): QObject() {} - //* destructor - virtual ~AddEventFilter() - {} - //* event filter /** blocks all AddChild events */ - virtual bool eventFilter( QObject*, QEvent* event ) + bool eventFilter( QObject*, QEvent* event ) override { return event->type() == QEvent::ChildAdded; } }; } #endif diff --git a/kstyle/breezeblurhelper.h b/kstyle/breezeblurhelper.h index ed7cbd1c..c2ae336d 100644 --- a/kstyle/breezeblurhelper.h +++ b/kstyle/breezeblurhelper.h @@ -1,84 +1,80 @@ #ifndef breezeblurhelper_h #define breezeblurhelper_h ////////////////////////////////////////////////////////////////////////////// // breezeblurhelper.h // handle regions passed to kwin for blurring // ------------------- // // Copyright (C) 2018 Alex Nemeth // // Largely rewritten from Oxygen widget style // Copyright (C) 2007 Thomas Luebking // Copyright (c) 2010 Hugo Pereira Da Costa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "breeze.h" #include "breezehelper.h" #include #include #if BREEZE_HAVE_X11 #include #endif namespace Breeze { class BlurHelper: public QObject { Q_OBJECT public: //! constructor BlurHelper( QObject* ); - //! destructor - virtual ~BlurHelper() - {} - //! register widget void registerWidget( QWidget* ); //! register widget void unregisterWidget( QWidget* ); //! event filter - bool eventFilter( QObject*, QEvent* ) ; + bool eventFilter( QObject*, QEvent* ) override; protected: //! install event filter to object, in a unique way void addEventFilter( QObject* object ) { object->removeEventFilter( this ); object->installEventFilter( this ); } //! update blur regions for given widget void update( QWidget* ) const; }; } #endif diff --git a/kstyle/breezeframeshadow.cpp b/kstyle/breezeframeshadow.cpp index c8b73b56..1d220ea1 100644 --- a/kstyle/breezeframeshadow.cpp +++ b/kstyle/breezeframeshadow.cpp @@ -1,359 +1,355 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeframeshadow.h" #include "breeze.h" #include #include #include #include #include #include #include #include namespace Breeze { //____________________________________________________________________________________ bool FrameShadowFactory::registerWidget( QWidget* widget, Helper& helper ) { if( !widget ) return false; if( isRegistered( widget ) ) return false; // check whether widget is a frame, and has the proper shape bool accepted = false; // cast to frame and check QFrame* frame( qobject_cast( widget ) ); if( frame ) { // also do not install on QSplitter /* due to Qt, splitters are set with a frame style that matches the condition below, though no shadow should be installed, obviously */ if( qobject_cast( widget ) ) return false; // further checks on frame shape, and parent if( frame->frameStyle() == (QFrame::StyledPanel | QFrame::Sunken) ) accepted = true; } else if( widget->inherits( "KTextEditor::View" ) ) accepted = true; if( !accepted ) return false; // make sure that the widget is not embedded into a KHTMLView QWidget* parent( widget->parentWidget() ); while( parent && !parent->isTopLevel() ) { if( parent->inherits( "KHTMLView" ) ) return false; parent = parent->parentWidget(); } // store in set _registeredWidgets.insert( widget ); // catch object destruction connect( widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDestroyed(QObject*)) ); // install shadow installShadows( widget, helper ); return true; } //____________________________________________________________________________________ void FrameShadowFactory::unregisterWidget( QWidget* widget ) { if( !isRegistered( widget ) ) return; _registeredWidgets.remove( widget ); removeShadows( widget ); } //____________________________________________________________________________________ bool FrameShadowFactory::eventFilter( QObject* object, QEvent* event ) { switch( event->type() ) { // TODO: possibly implement ZOrderChange event, to make sure that // the shadow is always painted on top case QEvent::ZOrderChange: { raiseShadows( object ); break; } default: break; } return QObject::eventFilter( object, event ); } //____________________________________________________________________________________ void FrameShadowFactory::installShadows( QWidget* widget, Helper& helper ) { removeShadows(widget); widget->installEventFilter(this); widget->installEventFilter( &_addEventFilter ); installShadow( widget, helper, SideTop ); installShadow( widget, helper, SideBottom ); widget->removeEventFilter( &_addEventFilter ); } //____________________________________________________________________________________ void FrameShadowFactory::removeShadows( QWidget* widget ) { widget->removeEventFilter( this ); const QList children = widget->children(); foreach( QObject *child, children ) { if( FrameShadow* shadow = qobject_cast(child) ) { shadow->hide(); shadow->setParent(nullptr); shadow->deleteLater(); } } } //____________________________________________________________________________________ void FrameShadowFactory::updateShadowsGeometry( const QObject* object, QRect rect ) const { const QList children = object->children(); foreach( QObject *child, children ) { if( FrameShadow* shadow = qobject_cast(child) ) { shadow->updateGeometry( rect ); } } } //____________________________________________________________________________________ void FrameShadowFactory::raiseShadows( QObject* object ) const { const QList children = object->children(); foreach( QObject *child, children ) { if( FrameShadow* shadow = qobject_cast(child) ) { shadow->raise(); } } } //____________________________________________________________________________________ void FrameShadowFactory::update( QObject* object ) const { const QList children = object->children(); foreach( QObject *child, children ) { if( FrameShadow* shadow = qobject_cast(child) ) { shadow->update();} } } //____________________________________________________________________________________ void FrameShadowFactory::updateState( const QWidget* widget, bool focus, bool hover, qreal opacity, AnimationMode mode ) const { const QList children = widget->children(); foreach( QObject *child, children ) { if( FrameShadow* shadow = qobject_cast(child) ) { shadow->updateState( focus, hover, opacity, mode ); } } } //____________________________________________________________________________________ void FrameShadowFactory::installShadow( QWidget* widget, Helper& helper, Side area ) const { FrameShadow *shadow(nullptr); shadow = new FrameShadow( area, helper ); shadow->setParent(widget); shadow->hide(); } //____________________________________________________________________________________ void FrameShadowFactory::widgetDestroyed( QObject* object ) { _registeredWidgets.remove( object ); } //____________________________________________________________________________________ FrameShadow::FrameShadow( Side area, Helper& helper ): _helper( helper ), - _area( area ), - _hasFocus( false ), - _mouseOver( false ), - _opacity( -1 ), - _mode( AnimationNone ) + _area( area ) { setAttribute(Qt::WA_OpaquePaintEvent, false); setFocusPolicy(Qt::NoFocus); setAttribute(Qt::WA_TransparentForMouseEvents, true); setContextMenuPolicy(Qt::NoContextMenu); // grab viewport widget QWidget *viewport( this->viewport() ); // set cursor from viewport if (viewport) setCursor(viewport->cursor()); } //____________________________________________________________________________________ void FrameShadow::updateGeometry( QRect rect ) { // show on first call if( isHidden() ) show(); // store offsets between passed rect and parent widget rect QRect parentRect( parentWidget()->contentsRect() ); _margins = QMargins( rect.left() - parentRect.left(), rect.top() - parentRect.top(), rect.right() - parentRect.right(), rect.bottom() - parentRect.bottom() ); // for efficiency, take out the part for which nothing is rendered rect.adjust( 1, 1, -1, -1 ); // adjust geometry const int shadowSize( Metrics::Frame_FrameRadius ); switch( _area ) { case SideTop: rect.setHeight( shadowSize ); break; case SideBottom: rect.setTop( rect.bottom() - shadowSize + 1 ); break; case SideLeft: rect.setWidth(shadowSize); rect.adjust(0, shadowSize, 0, -shadowSize ); break; case SideRight: rect.setLeft(rect.right() - shadowSize + 1 ); rect.adjust(0, shadowSize, 0, -shadowSize ); break; default: return; } setGeometry(rect); } //____________________________________________________________________________________ void FrameShadow::updateState( bool focus, bool hover, qreal opacity, AnimationMode mode ) { bool changed( false ); if( _hasFocus != focus ) { _hasFocus = focus; changed |= true; } if( _mouseOver != hover ) { _mouseOver = hover; changed |= !_hasFocus; } if( _mode != mode ) { _mode = mode; changed |= (_mode == AnimationNone) || (_mode == AnimationFocus) || (_mode == AnimationHover && !_hasFocus ); } if( _opacity != opacity ) { _opacity = opacity; changed |= (_mode != AnimationNone ); } if( changed ) { if( QWidget* viewport = this->viewport() ) { // need to disable viewport updates to avoid some redundant painting // besides it fixes one visual glitch (from Qt) in QTableViews viewport->setUpdatesEnabled( false ); update() ; viewport->setUpdatesEnabled( true ); } else update(); } } //____________________________________________________________________________________ void FrameShadow::paintEvent(QPaintEvent *event ) { // this fixes shadows in frames that change frameStyle() after polish() if( QFrame *frame = qobject_cast( parentWidget() ) ) { if (frame->frameStyle() != (QFrame::StyledPanel | QFrame::Sunken)) return; } const QRect parentRect( parentWidget()->contentsRect().translated( mapFromParent( QPoint( 0, 0 ) ) ) ); const QRect rect( parentRect.adjusted( _margins.left(), _margins.top(), _margins.right(), _margins.bottom() ) ); // render QPainter painter(this); painter.setClipRegion( event->region() ); painter.setRenderHint( QPainter::Antialiasing ); const QColor outline( _helper.frameOutlineColor( palette(), _mouseOver, _hasFocus, _opacity, _mode ) ); painter.setCompositionMode( QPainter::CompositionMode_SourceOver ); _helper.renderFrame( &painter, rect, QColor(), outline ); } //____________________________________________________________________________________ QWidget* FrameShadow::viewport() const { if( !parentWidget() ) return nullptr; else if( QAbstractScrollArea *widget = qobject_cast(parentWidget()) ) { return widget->viewport(); } else return nullptr; } } diff --git a/kstyle/breezeframeshadow.h b/kstyle/breezeframeshadow.h index 233e36d0..45559664 100644 --- a/kstyle/breezeframeshadow.h +++ b/kstyle/breezeframeshadow.h @@ -1,158 +1,150 @@ #ifndef breezeframeshadow_h #define breezeframeshadow_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breeze.h" #include "breezeaddeventfilter.h" #include "breezehelper.h" #include #include #include #include #include #include namespace Breeze { //* shadow manager class FrameShadowFactory: public QObject { Q_OBJECT public: //* constructor explicit FrameShadowFactory( QObject* parent ): QObject( parent ) {} - //* destructor - virtual ~FrameShadowFactory() - {} - //* register widget bool registerWidget( QWidget*, Helper& ); //* unregister void unregisterWidget( QWidget* ); //* true if widget is registered bool isRegistered( const QWidget* widget ) const { return _registeredWidgets.contains( widget ); } //* event filter - virtual bool eventFilter( QObject*, QEvent*); + bool eventFilter( QObject*, QEvent*) override; //* update state void updateState( const QWidget*, bool focus, bool hover, qreal opacity, AnimationMode ) const; //* update shadows geometry void updateShadowsGeometry( const QObject*, QRect ) const; protected: //* install shadows on given widget void installShadows( QWidget*, Helper& ); //* remove shadows from widget void removeShadows( QWidget* ); //* raise shadows void raiseShadows( QObject* ) const; //* update shadows void update( QObject* ) const; //* install shadow on given side void installShadow( QWidget*, Helper&, Side ) const; protected Q_SLOTS: //* triggered by object destruction void widgetDestroyed( QObject* ); private: //* needed to block ChildAdded events when creating shadows AddEventFilter _addEventFilter; //* set of registered widgets QSet _registeredWidgets; }; //* frame shadow /** this allows the shadow to be painted over the widgets viewport */ class FrameShadow : public QWidget { Q_OBJECT public: //* constructor FrameShadow( Side, Helper& ); - //* destructor - virtual ~FrameShadow() - {} - //* update geometry virtual void updateGeometry( QRect ); //* update state void updateState( bool focus, bool hover, qreal opacity, AnimationMode ); protected: //* painting - virtual void paintEvent(QPaintEvent *); + void paintEvent( QPaintEvent* ) override; //* return viewport associated to parent widget - virtual QWidget* viewport() const; + QWidget* viewport() const; private: //* helper Helper& _helper; //* shadow area Side _area; //* margins /** offsets between update rect and parent widget rect. It is set via updateGeometry */ QMargins _margins; //*@name widget state //@{ - bool _hasFocus; - bool _mouseOver; - qreal _opacity; - AnimationMode _mode; + bool _hasFocus = false; + bool _mouseOver = false; + qreal _opacity = -1; + AnimationMode _mode = AnimationNone; //@} }; } #endif diff --git a/kstyle/breezemdiwindowshadow.h b/kstyle/breezemdiwindowshadow.h index e0389ea5..6846bf6b 100644 --- a/kstyle/breezemdiwindowshadow.h +++ b/kstyle/breezemdiwindowshadow.h @@ -1,173 +1,169 @@ #ifndef breezemdiwindowshadow_h #define breezemdiwindowshadow_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include #include #include #include #include #include #include "breezetileset.h" namespace Breeze { class ShadowHelper; //* frame shadow /** this allows the shadow to be painted over the widgets viewport */ class MdiWindowShadow: public QWidget { Q_OBJECT public: //* constructor explicit MdiWindowShadow( QWidget*, TileSet ); //* update geometry void updateGeometry(); //* update ZOrder void updateZOrder(); //* set associated window void setWidget( QWidget* value ) { _widget = value; } //* associated window QWidget* widget() const { return _widget; } protected: //* painting - virtual void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; private: //* associated widget QWidget* _widget = nullptr; //* tileset rect, used for painting QRect _shadowTilesRect; //* tileset used to draw shadow TileSet _shadowTiles; }; //* shadow manager class MdiWindowShadowFactory: public QObject { Q_OBJECT public: //* constructor explicit MdiWindowShadowFactory( QObject* ); - //* destructor - virtual ~MdiWindowShadowFactory() - {} - //* set shadow helper void setShadowHelper( ShadowHelper* shadowHelper ) { _shadowHelper = shadowHelper; } //* register widget bool registerWidget( QWidget* ); //* unregister void unregisterWidget( QWidget* ); //* true if widget is registered bool isRegistered( const QObject* widget ) const { return _registeredWidgets.contains( widget ); } //* event filter - virtual bool eventFilter( QObject*, QEvent*); + bool eventFilter( QObject*, QEvent*) override; protected: //* find shadow matching a given object MdiWindowShadow* findShadow( QObject* ) const; //* install shadows on given widget void installShadow( QObject* ); //* remove shadows from widget void removeShadow( QObject* ); //* hide shadows void hideShadows( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { windowShadow->hide(); } } //* update ZOrder void updateShadowZOrder( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { if( !windowShadow->isVisible() ) windowShadow->show(); windowShadow->updateZOrder(); } } //* update shadows geometry void updateShadowGeometry( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { windowShadow->updateGeometry(); } } //* update shadows void update( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { windowShadow->update(); } } protected Q_SLOTS: //* triggered by object destruction void widgetDestroyed( QObject* ); private: //* set of registered widgets QSet _registeredWidgets; //* shadow helper used to generate the shadows QPointer _shadowHelper; }; } #endif diff --git a/kstyle/breezemnemonics.h b/kstyle/breezemnemonics.h index 35e4e737..a9524853 100644 --- a/kstyle/breezemnemonics.h +++ b/kstyle/breezemnemonics.h @@ -1,77 +1,72 @@ #ifndef breezemnemonics_h #define breezemnemonics_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include #include #include #include "breezestyleconfigdata.h" namespace Breeze { class Mnemonics: public QObject { Q_OBJECT public: //* constructor explicit Mnemonics( QObject* parent ): - QObject( parent ), - _enabled( true ) + QObject( parent ) {} - //* destructor - virtual ~Mnemonics() - {} - //* set mode void setMode( int ); //* event filter - virtual bool eventFilter( QObject*, QEvent* ); + bool eventFilter( QObject*, QEvent* ) override; //* true if mnemonics are enabled - const bool& enabled() const + bool enabled() const { return _enabled; } //* alignment flag int textFlags() const { return _enabled ? Qt::TextShowMnemonic : Qt::TextHideMnemonic; } protected: //* set enable state void setEnabled( bool ); private: //* enable state - bool _enabled; + bool _enabled = true; }; } #endif diff --git a/kstyle/breezeshadowhelper.cpp b/kstyle/breezeshadowhelper.cpp index 38c4cb27..d462fd96 100644 --- a/kstyle/breezeshadowhelper.cpp +++ b/kstyle/breezeshadowhelper.cpp @@ -1,669 +1,661 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * Copyright (C) 2018 by Vlad Zagorodniy * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeshadowhelper.h" #include "breeze.h" #include "breezeboxshadowrenderer.h" #include "breezehelper.h" #include "breezepropertynames.h" #include "breezestyleconfigdata.h" #include #include #include #include #include #include #include #include #if BREEZE_HAVE_X11 #include #endif #if BREEZE_HAVE_KWAYLAND #include #include #include #include #include #include #endif namespace { using Breeze::CompositeShadowParams; using Breeze::ShadowParams; const CompositeShadowParams s_shadowParams[] = { // None CompositeShadowParams(), // Small CompositeShadowParams( QPoint(0, 3), ShadowParams(QPoint(0, 0), 12, 0.26), ShadowParams(QPoint(0, -2), 6, 0.16)), // Medium CompositeShadowParams( QPoint(0, 4), ShadowParams(QPoint(0, 0), 16, 0.24), ShadowParams(QPoint(0, -2), 8, 0.14)), // Large CompositeShadowParams( QPoint(0, 5), ShadowParams(QPoint(0, 0), 20, 0.22), ShadowParams(QPoint(0, -3), 10, 0.12)), // Very Large CompositeShadowParams( QPoint(0, 6), ShadowParams(QPoint(0, 0), 24, 0.2), ShadowParams(QPoint(0, -3), 12, 0.1)) }; } namespace Breeze { const char ShadowHelper::netWMShadowAtomName[] ="_KDE_NET_WM_SHADOW"; //_____________________________________________________ CompositeShadowParams ShadowHelper::lookupShadowParams(int shadowSizeEnum) { switch (shadowSizeEnum) { case StyleConfigData::ShadowNone: return s_shadowParams[0]; case StyleConfigData::ShadowSmall: return s_shadowParams[1]; case StyleConfigData::ShadowMedium: return s_shadowParams[2]; case StyleConfigData::ShadowLarge: return s_shadowParams[3]; case StyleConfigData::ShadowVeryLarge: return s_shadowParams[4]; default: // Fallback to the Large size. return s_shadowParams[3]; } } //_____________________________________________________ ShadowHelper::ShadowHelper( QObject* parent, Helper& helper ): QObject( parent ), _helper( helper ) - #if BREEZE_HAVE_X11 - ,_gc( 0 ), - _atom( 0 ) - #endif - #if BREEZE_HAVE_KWAYLAND - , _shadowManager( nullptr ) - , _shmPool( nullptr ) - #endif { // delay till event dispatcher is running as Wayland is highly async QMetaObject::invokeMethod(this, "initializeWayland", Qt::QueuedConnection); } //_______________________________________________________ ShadowHelper::~ShadowHelper() { #if BREEZE_HAVE_X11 if( Helper::isX11() ) { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( Helper::connection(), value ); } #endif } //_______________________________________________________ void ShadowHelper::initializeWayland() { #if BREEZE_HAVE_KWAYLAND if( !Helper::isWayland() ) return; using namespace KWayland::Client; auto connection = ConnectionThread::fromApplication( this ); if( !connection ) { return; } auto registry = new Registry( connection ); registry->create( connection ); connect(registry, &Registry::interfacesAnnounced, this, [registry, this] { const auto interface = registry->interface( Registry::Interface::Shadow ); if( interface.name != 0 ) { _shadowManager = registry->createShadowManager( interface.name, interface.version, registry ); } const auto shmInterface = registry->interface( Registry::Interface::Shm ); if( shmInterface.name != 0 ) { _shmPool = registry->createShmPool( shmInterface.name, shmInterface.version, registry ); } } ); registry->setup(); connection->roundtrip(); #endif } //______________________________________________ void ShadowHelper::reset() { #if BREEZE_HAVE_X11 if( Helper::isX11() ) { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( Helper::connection(), value ); } #endif _pixmaps.clear(); _shadowTiles = TileSet(); } //_______________________________________________________ bool ShadowHelper::registerWidget( QWidget* widget, bool force ) { // make sure widget is not already registered if( _widgets.contains( widget ) ) return false; // check if widget qualifies if( !( force || acceptWidget( widget ) ) ) { return false; } // try create shadow directly if( installShadows( widget ) ) _widgets.insert( widget, widget->winId() ); else _widgets.insert( widget, 0 ); // install event filter widget->removeEventFilter( this ); widget->installEventFilter( this ); // connect destroy signal connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) ); return true; } //_______________________________________________________ void ShadowHelper::unregisterWidget( QWidget* widget ) { if( _widgets.remove( widget ) ) { uninstallShadows( widget ); } } //_______________________________________________________ void ShadowHelper::loadConfig() { // reset reset(); // update property for registered widgets for( QMap::const_iterator iter = _widgets.constBegin(); iter != _widgets.constEnd(); ++iter ) { installShadows( iter.key() ); } } //_______________________________________________________ bool ShadowHelper::eventFilter( QObject* object, QEvent* event ) { if( Helper::isWayland() ) { #if BREEZE_HAVE_KWAYLAND QWidget* widget( static_cast( object ) ); if( event->type() == QEvent::Paint ) { auto iter = _widgetSurfaces.constFind( widget ); if( iter == _widgetSurfaces.constEnd() ) { // install shadows and update winId installShadows( widget ); } } else if( event->type() == QEvent::Hide ) { auto iter = _widgetSurfaces.find( widget ); if( iter != _widgetSurfaces.end() ) { _widgetSurfaces.erase( iter ); } } #endif } else if( Helper::isX11() ) { // check event type if( event->type() != QEvent::WinIdChange ) return false; // cast widget QWidget* widget( static_cast( object ) ); // install shadows and update winId if( installShadows( widget ) ) { _widgets.insert( widget, widget->winId() ); } } return false; } //_______________________________________________________ TileSet ShadowHelper::shadowTiles() { const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); if (params.isNone()) { return TileSet(); } else if (_shadowTiles.isValid()) { return _shadowTiles; } auto withOpacity = [](const QColor &color, qreal opacity) -> QColor { QColor c(color); c.setAlphaF(opacity); return c; }; const QColor color = StyleConfigData::shadowColor(); const qreal strength = static_cast(StyleConfigData::shadowStrength()) / 255.0; const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius) .expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius)); #if QT_VERSION >= 0x050300 const qreal dpr = qApp->devicePixelRatio(); #else const qreal dpr = 1.0; #endif const qreal frameRadius = _helper.frameRadius(); BoxShadowRenderer shadowRenderer; shadowRenderer.setBorderRadius(frameRadius); shadowRenderer.setBoxSize(boxSize); shadowRenderer.setDevicePixelRatio(dpr); shadowRenderer.addShadow(params.shadow1.offset, params.shadow1.radius, withOpacity(color, params.shadow1.opacity * strength)); shadowRenderer.addShadow(params.shadow2.offset, params.shadow2.radius, withOpacity(color, params.shadow2.opacity * strength)); QImage shadowTexture = shadowRenderer.render(); const QRect outerRect(QPoint(0, 0), shadowTexture.size() / dpr); QRect boxRect(QPoint(0, 0), boxSize); boxRect.moveCenter(outerRect.center()); // Mask out inner rect. QPainter painter(&shadowTexture); painter.setRenderHint(QPainter::Antialiasing); const QMargins margins = QMargins( boxRect.left() - outerRect.left() - Metrics::Shadow_Overlap - params.offset.x(), boxRect.top() - outerRect.top() - Metrics::Shadow_Overlap - params.offset.y(), outerRect.right() - boxRect.right() - Metrics::Shadow_Overlap + params.offset.x(), outerRect.bottom() - boxRect.bottom() - Metrics::Shadow_Overlap + params.offset.y()); painter.setPen(Qt::NoPen); painter.setBrush(Qt::black); painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); painter.drawRoundedRect( #if BREEZE_USE_KDE4 outerRect.adjusted(margins.left(), margins.top(), -margins.right(), -margins.bottom()), #else outerRect - margins, #endif frameRadius, frameRadius); // We're done. painter.end(); const QPoint innerRectTopLeft = outerRect.center(); _shadowTiles = TileSet( QPixmap::fromImage(shadowTexture), innerRectTopLeft.x(), innerRectTopLeft.y(), 1, 1); return _shadowTiles; } //_______________________________________________________ void ShadowHelper::objectDeleted( QObject* object ) { _widgets.remove( static_cast( object ) ); } //_______________________________________________________ bool ShadowHelper::isMenu( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::isToolTip( QWidget* widget ) const { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } //_______________________________________________________ bool ShadowHelper::isDockWidget( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::isToolBar( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::acceptWidget( QWidget* widget ) const { // flags if( widget->property( PropertyNames::netWMSkipShadow ).toBool() ) return false; if( widget->property( PropertyNames::netWMForceShadow ).toBool() ) return true; // menus if( isMenu( widget ) ) return true; // combobox dropdown lists if( widget->inherits( "QComboBoxPrivateContainer" ) ) return true; // tooltips if( isToolTip( widget ) && !widget->inherits( "Plasma::ToolTip" ) ) { return true; } // detached widgets if( isDockWidget( widget ) || isToolBar( widget ) ) { return true; } // reject return false; } //______________________________________________ const QVector& ShadowHelper::createPixmapHandles() { /** shadow atom and property specification available at http://community.kde.org/KWin/Shadow */ // create atom #if BREEZE_HAVE_X11 if( !_atom && Helper::isX11() ) _atom = _helper.createAtom( QLatin1String( netWMShadowAtomName ) ); #endif // make sure size is valid if( _pixmaps.empty() ) { _pixmaps = QVector { createPixmap( _shadowTiles.pixmap( 1 ) ), createPixmap( _shadowTiles.pixmap( 2 ) ), createPixmap( _shadowTiles.pixmap( 5 ) ), createPixmap( _shadowTiles.pixmap( 8 ) ), createPixmap( _shadowTiles.pixmap( 7 ) ), createPixmap( _shadowTiles.pixmap( 6 ) ), createPixmap( _shadowTiles.pixmap( 3 ) ), createPixmap( _shadowTiles.pixmap( 0 ) ) }; } // return relevant list of pixmap handles return _pixmaps; } //______________________________________________ quint32 ShadowHelper::createPixmap( const QPixmap& source ) { // do nothing for invalid pixmaps if( source.isNull() ) return 0; if( !Helper::isX11() ) return 0; /* in some cases, pixmap handle is invalid. This is the case notably when Qt uses to RasterEngine. In this case, we create an X11 Pixmap explicitly and draw the source pixmap on it. */ #if BREEZE_HAVE_X11 const int width( source.width() ); const int height( source.height() ); // create X11 pixmap xcb_pixmap_t pixmap = xcb_generate_id( Helper::connection() ); xcb_create_pixmap( Helper::connection(), 32, pixmap, QX11Info::appRootWindow(), width, height ); // create gc if( !_gc ) { _gc = xcb_generate_id( Helper::connection() ); xcb_create_gc( Helper::connection(), _gc, pixmap, 0, nullptr ); } // create image from QPixmap and assign to pixmap QImage image( source.toImage() ); xcb_put_image( Helper::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.byteCount(), image.constBits()); return pixmap; #else return 0; #endif } //_______________________________________________________ bool ShadowHelper::installShadows( QWidget* widget ) { if( !widget ) return false; /* From bespin code. Supposibly prevent playing with some 'pseudo-widgets' that have winId matching some other -random- window */ if( !(widget->testAttribute(Qt::WA_WState_Created) && widget->internalWinId() )) { return false; } // create shadow tiles if needed shadowTiles(); if( !_shadowTiles.isValid() ) return false; if( Helper::isX11() ) return installX11Shadows( widget ); if( Helper::isWayland() ) return installWaylandShadows( widget ); return false; } //_______________________________________________________ bool ShadowHelper::installX11Shadows( QWidget* widget ) { #if BREEZE_HAVE_X11 #ifndef QT_NO_XRENDER // create pixmap handles if needed QVector data( createPixmapHandles() ); if( data.size() != numPixmaps ) return false; const QMargins margins = shadowMargins( widget ); const quint32 topSize = margins.top(); const quint32 bottomSize = margins.bottom(); const quint32 leftSize( margins.left() ); const quint32 rightSize( margins.right() ); // assign to data and xcb property data << QVector{topSize, rightSize, bottomSize, leftSize}; xcb_change_property( Helper::connection(), XCB_PROP_MODE_REPLACE, widget->winId(), _atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData() ); xcb_flush( Helper::connection() ); return true; #endif #endif return false; } //_______________________________________________________ bool ShadowHelper::installWaylandShadows( QWidget* widget ) { #if BREEZE_HAVE_KWAYLAND if( widget->windowHandle()->parent() ) return false; if( !_shadowManager || !_shmPool ) return false; // create shadow using namespace KWayland::Client; auto s = Surface::fromWindow( widget->windowHandle() ); if( !s ) return false; auto shadow = _shadowManager->createShadow( s, widget ); if( !shadow->isValid() ) return false; // add the shadow elements shadow->attachTop( _shmPool->createBuffer( _shadowTiles.pixmap( 1 ).toImage() ) ); shadow->attachTopRight( _shmPool->createBuffer( _shadowTiles.pixmap( 2 ).toImage() ) ); shadow->attachRight( _shmPool->createBuffer( _shadowTiles.pixmap( 5 ).toImage() ) ); shadow->attachBottomRight( _shmPool->createBuffer( _shadowTiles.pixmap( 8 ).toImage() ) ); shadow->attachBottom( _shmPool->createBuffer( _shadowTiles.pixmap( 7 ).toImage() ) ); shadow->attachBottomLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 6 ).toImage() ) ); shadow->attachLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 3 ).toImage() ) ); shadow->attachTopLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 0 ).toImage() ) ); shadow->setOffsets( shadowMargins( widget ) ); shadow->commit(); s->commit( Surface::CommitFlag::None ); _widgetSurfaces.insert(widget, s); return true; #else Q_UNUSED( widget ); #endif return false; } //_______________________________________________________ QMargins ShadowHelper::shadowMargins( QWidget* widget ) const { const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); if (params.isNone()) { return QMargins(); } const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius) .expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius)); const QSize shadowSize = BoxShadowRenderer::calculateMinimumShadowTextureSize(boxSize, params.shadow1.radius, params.shadow1.offset) .expandedTo(BoxShadowRenderer::calculateMinimumShadowTextureSize(boxSize, params.shadow2.radius, params.shadow2.offset)); const QRect shadowRect(QPoint(0, 0), shadowSize); QRect boxRect(QPoint(0, 0), boxSize); boxRect.moveCenter(shadowRect.center()); QMargins margins( boxRect.left() - shadowRect.left() - Metrics::Shadow_Overlap - params.offset.x(), boxRect.top() - shadowRect.top() - Metrics::Shadow_Overlap - params.offset.y(), shadowRect.right() - boxRect.right() - Metrics::Shadow_Overlap + params.offset.x(), shadowRect.bottom() - boxRect.bottom() - Metrics::Shadow_Overlap + params.offset.y()); if (widget->inherits("QBalloonTip")) { // Balloon tip needs special margins to deal with the arrow. int top = 0; int bottom = 0; widget->getContentsMargins(nullptr, &top, nullptr, &bottom); // Need to decrement default size further due to extra hard coded round corner. #if BREEZE_USE_KDE4 margins.setLeft(margins.left() - 1); margins.setTop(margins.top() - 1); margins.setRight(margins.right() - 1); margins.setBottom(margins.bottom() - 1); #else margins -= 1; #endif // Arrow can be either to the top or the bottom. Adjust margins accordingly. const int diff = qAbs(top - bottom); if (top > bottom) { margins.setTop(margins.top() - diff); } else { margins.setBottom(margins.bottom() - diff); } } #if BREEZE_USE_KDE4 const qreal dpr = _helper.devicePixelRatio(_shadowTiles.pixmap(0)); margins.setLeft(margins.left() * dpr); margins.setTop(margins.top() * dpr); margins.setRight(margins.right() * dpr); margins.setBottom(margins.bottom() * dpr); #else margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); #endif return margins; } //_______________________________________________________ void ShadowHelper::uninstallShadows( QWidget* widget ) const { if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; if( Helper::isX11() ) uninstallX11Shadows( widget ); if( Helper::isWayland() ) uninstallWaylandShadows( widget ); } //_______________________________________________________ void ShadowHelper::uninstallX11Shadows( QWidget* widget ) const { #if BREEZE_HAVE_X11 xcb_delete_property( Helper::connection(), widget->winId(), _atom); #else Q_UNUSED( widget ) #endif } //_______________________________________________________ void ShadowHelper::uninstallWaylandShadows( QWidget* widget ) const { #if BREEZE_HAVE_KWAYLAND if( widget->windowHandle() && widget->windowHandle()->parent() ) return; if( !_shadowManager ) return; using namespace KWayland::Client; auto s = Surface::fromWindow( widget->windowHandle() ); if( !s ) return; _shadowManager->removeShadow( s ); s->commit( Surface::CommitFlag::None ); #else Q_UNUSED( widget ) #endif } } diff --git a/kstyle/breezeshadowhelper.h b/kstyle/breezeshadowhelper.h index 89a2439d..4d971e0c 100644 --- a/kstyle/breezeshadowhelper.h +++ b/kstyle/breezeshadowhelper.h @@ -1,237 +1,228 @@ #ifndef breezeshadowhelper_h #define breezeshadowhelper_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezetileset.h" #include "config-breeze.h" #include #include #include #include #if BREEZE_HAVE_X11 #include #endif #if BREEZE_HAVE_KWAYLAND namespace KWayland { namespace Client { class ShadowManager; class ShmPool; class Surface; } } #endif namespace Breeze { //* forward declaration class Helper; struct ShadowParams { - ShadowParams() - : offset(QPoint(0, 0)) - , radius(0) - , opacity(0) {} + ShadowParams() = default; - ShadowParams(const QPoint &offset, int radius, qreal opacity) - : offset(offset) - , radius(radius) - , opacity(opacity) {} + ShadowParams(const QPoint &offset, int radius, qreal opacity): + offset(offset), + radius(radius), + opacity(opacity) + {} QPoint offset; - int radius; - qreal opacity; + int radius = 0; + qreal opacity = 0; }; struct CompositeShadowParams { CompositeShadowParams() = default; CompositeShadowParams( const QPoint &offset, const ShadowParams &shadow1, const ShadowParams &shadow2) : offset(offset) , shadow1(shadow1) , shadow2(shadow2) {} bool isNone() const { return qMax(shadow1.radius, shadow2.radius) == 0; } QPoint offset; ShadowParams shadow1; ShadowParams shadow2; }; //* handle shadow pixmaps passed to window manager via X property class ShadowHelper: public QObject { Q_OBJECT public: //*@name property names //@{ static const char netWMShadowAtomName[]; //@} //* constructor ShadowHelper( QObject*, Helper& ); //* destructor - virtual ~ShadowHelper(); - - //* true if supported - bool isSupported() const - { return _supported; } + ~ShadowHelper() override; //* shadow params from size enum static CompositeShadowParams lookupShadowParams( int shadowSizeEnum ); //* reset void reset(); //* load config void loadConfig(); //* register widget bool registerWidget( QWidget*, bool force = false ); //* unregister widget void unregisterWidget( QWidget* ); //* event filter - virtual bool eventFilter( QObject*, QEvent* ); + bool eventFilter( QObject*, QEvent* ) override; //* shadow tiles /** is public because it is also needed for mdi windows */ TileSet shadowTiles(); protected Q_SLOTS: //* unregister widget void objectDeleted( QObject* ); //* initializes the Wayland specific parts void initializeWayland(); protected: //* true if widget is a menu bool isMenu( QWidget* ) const; //* true if widget is a tooltip bool isToolTip( QWidget* ) const; //* dock widget bool isDockWidget( QWidget* ) const; //* toolbar bool isToolBar( QWidget* ) const; //* accept widget bool acceptWidget( QWidget* ) const; // create pixmap handles from tileset const QVector& createPixmapHandles(); // create pixmap handle from pixmap quint32 createPixmap( const QPixmap& ); //* installs shadow on given widget in a platform independent way bool installShadows( QWidget * ); //* uninstalls shadow on given widget in a platform independent way void uninstallShadows( QWidget * ) const; //* install shadow X11 property on given widget /** shadow atom and property specification available at http://community.kde.org/KWin/Shadow */ bool installX11Shadows( QWidget* ); //* uninstall shadow X11 property on given widget void uninstallX11Shadows( QWidget* ) const; //* install shadow on given widget for Wayland bool installWaylandShadows( QWidget * ); //* uninstall shadow on given widget for Wayland void uninstallWaylandShadows( QWidget* ) const; //* gets the shadow margins for the given widget QMargins shadowMargins( QWidget* ) const; private: //* helper Helper& _helper; - //* true if supported - bool _supported; - //* registered widgets QMap _widgets; //* tileset TileSet _shadowTiles; //* number of pixmaps enum { numPixmaps = 8 }; //* pixmaps QVector _pixmaps; #if BREEZE_HAVE_X11 //* graphical context - xcb_gcontext_t _gc; + xcb_gcontext_t _gc = 0; //* shadow atom - xcb_atom_t _atom; + xcb_atom_t _atom = 0; #endif #if BREEZE_HAVE_KWAYLAND //* registered widgets to wayland surface mappings QMap _widgetSurfaces; //* The Wayland shadow manager to create Shadows for Surfaces (QWindow) QPointer _shadowManager; //* The Wayland Shared memory pool to share the shadow pixmaps with compositor QPointer _shmPool; #endif }; } #endif diff --git a/kstyle/breezesplitterproxy.cpp b/kstyle/breezesplitterproxy.cpp index effd74c5..280202b1 100644 --- a/kstyle/breezesplitterproxy.cpp +++ b/kstyle/breezesplitterproxy.cpp @@ -1,386 +1,382 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezesplitterproxy.h" #include "breeze.h" #include "breezestyleconfigdata.h" #include #include #include // Q_FALLTHROUGH() for Qt < 5.8 #ifndef Q_FALLTHROUGH #if defined(__has_cpp_attribute) #if __has_cpp_attribute(fallthrough) #define Q_FALLTHROUGH() [[fallthrough]] #elif __has_cpp_attribute(clang::fallthrough) #define Q_FALLTHROUGH() [[clang::fallthrough]] #elif __has_cpp_attribute(gnu::fallthrough) #define Q_FALLTHROUGH() [[gnu::fallthrough]] #endif #endif #ifndef Q_FALLTHROUGH #if __GNUC__ >= 7 #define Q_FALLTHROUGH() __attribute__((fallthrough)) #elif (__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 5) #define Q_FALLTHROUGH() [[clang::fallthrough]] #else #define Q_FALLTHROUGH() #endif #endif #endif namespace Breeze { //____________________________________________________________________ void SplitterFactory::setEnabled( bool value ) { if( _enabled != value ) { // store _enabled = value; // assign to existing splitters for( WidgetMap::iterator iter = _widgets.begin(); iter != _widgets.end(); ++iter ) { if( iter.value() ) iter.value().data()->setEnabled( value ); } } } //____________________________________________________________________ bool SplitterFactory::registerWidget( QWidget *widget ) { // check widget type if( qobject_cast( widget ) ) { WidgetMap::iterator iter( _widgets.find( widget ) ); if( iter == _widgets.end() || !iter.value() ) { widget->installEventFilter( &_addEventFilter ); SplitterProxy* proxy( new SplitterProxy( widget, _enabled ) ); widget->removeEventFilter( &_addEventFilter ); widget->installEventFilter( proxy ); _widgets.insert( widget, proxy ); } else { widget->removeEventFilter( iter.value().data() ); widget->installEventFilter( iter.value().data() ); } return true; } else if( qobject_cast( widget ) ) { QWidget* window( widget->window() ); WidgetMap::iterator iter( _widgets.find( window ) ); if( iter == _widgets.end() || !iter.value() ) { window->installEventFilter( &_addEventFilter ); SplitterProxy* proxy( new SplitterProxy( window, _enabled ) ); window->removeEventFilter( &_addEventFilter ); widget->installEventFilter( proxy ); _widgets.insert( window, proxy ); } else { widget->removeEventFilter( iter.value().data() ); widget->installEventFilter( iter.value().data() ); } return true; } else return false; } //____________________________________________________________________ void SplitterFactory::unregisterWidget( QWidget *widget ) { WidgetMap::iterator iter( _widgets.find( widget ) ); if( iter != _widgets.end() ) { if( iter.value() ) iter.value().data()->deleteLater(); _widgets.erase( iter ); } } //____________________________________________________________________ SplitterProxy::SplitterProxy( QWidget* parent, bool enabled ): QWidget( parent ), _enabled( enabled ), _timerId( 0 ) { setAttribute( Qt::WA_TranslucentBackground, true ); setAttribute( Qt::WA_OpaquePaintEvent, false ); hide(); } - //____________________________________________________________________ - SplitterProxy::~SplitterProxy() - {} - //____________________________________________________________________ void SplitterProxy::setEnabled( bool value ) { // make sure status has changed if( _enabled != value ) { _enabled = value; if( _enabled ) clearSplitter(); } } //____________________________________________________________________ bool SplitterProxy::eventFilter( QObject* object, QEvent* event ) { // do nothing if disabled if( !_enabled ) return false; // do nothing in case of mouse grab if( mouseGrabber() ) return false; switch( event->type() ) { case QEvent::HoverEnter: if( !isVisible() ) { // cast to splitter handle if( QSplitterHandle* handle = qobject_cast( object ) ) { setSplitter( handle ); } } return false; case QEvent::HoverMove: case QEvent::HoverLeave: return isVisible() && object == _splitter.data(); case QEvent::MouseMove: case QEvent::Timer: case QEvent::Move: return false; case QEvent::CursorChange: if( QWidget *window = qobject_cast( object ) ) { if( window->cursor().shape() == Qt::SplitHCursor || window->cursor().shape() == Qt::SplitVCursor ) { setSplitter( window ); } } return false; case QEvent::WindowDeactivate: case QEvent::MouseButtonRelease: clearSplitter(); return false; default: return false; } } //____________________________________________________________________ bool SplitterProxy::event( QEvent *event ) { switch( event->type() ) { #if 0 case QEvent::Paint: { QPainter painter( this ); painter.setClipRegion( static_cast( event )->region() ); painter.setRenderHints( QPainter::Antialiasing ); painter.setPen( Qt::red ); painter.drawRect( QRectF( rect() ).adjusted( 0.5, 0.5, -0.5, -0.5 ) ); return true; } #endif case QEvent::MouseMove: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: { // check splitter if( !_splitter ) return false; event->accept(); // grab on mouse press if( event->type() == QEvent::MouseButtonPress) { grabMouse(); resize(1,1); } // cast to mouse event QMouseEvent *mouseEvent( static_cast( event ) ); // get relevant position to post mouse drag event to application if( event->type() == QEvent::MouseButtonPress ) { // use hook, to make sure splitter is properly dragged QMouseEvent copy( mouseEvent->type(), _hook, _splitter.data()->mapToGlobal(_hook), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); QCoreApplication::sendEvent( _splitter.data(), © ); } else { // map event position to current splitter and post. QMouseEvent copy( mouseEvent->type(), _splitter.data()->mapFromGlobal( mouseEvent->globalPos() ), mouseEvent->globalPos(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); QCoreApplication::sendEvent( _splitter.data(), © ); } // release grab on mouse-Release if( event->type() == QEvent::MouseButtonRelease && mouseGrabber() == this ) { releaseMouse(); } return true; } case QEvent::Timer: if( static_cast( event )->timerId() != _timerId ) { return QWidget::event( event ); } /* Fall through is intended. We somehow lost a QEvent::Leave before timeout. We fix it from here */ Q_FALLTHROUGH(); case QEvent::HoverLeave: case QEvent::Leave: { if( mouseGrabber() == this ) { return true; } // reset splitter if( isVisible() && !rect().contains( mapFromGlobal( QCursor::pos() ) ) ) { clearSplitter(); } return true; } default: return QWidget::event( event ); } } //____________________________________________________________________ void SplitterProxy::setSplitter( QWidget* widget ) { // check if changed if( _splitter.data() == widget ) return; // get cursor position const QPoint position( QCursor::pos() ); // store splitter and hook _splitter = widget; _hook = _splitter.data()->mapFromGlobal( position ); // adjust rect QRect rect( 0, 0, 2*StyleConfigData::splitterProxyWidth(), 2*StyleConfigData::splitterProxyWidth() ); rect.moveCenter( parentWidget()->mapFromGlobal( position ) ); setGeometry( rect ); setCursor( _splitter.data()->cursor().shape() ); // show raise(); show(); // timer used to automatically hide proxy in case leave events are lost if( !_timerId ) _timerId = startTimer(150); } //____________________________________________________________________ void SplitterProxy::clearSplitter() { // check if changed if( !_splitter ) return; // release mouse if( mouseGrabber() == this ) releaseMouse(); // hide parentWidget()->setUpdatesEnabled(false); hide(); parentWidget()->setUpdatesEnabled(true); // send hover event if( _splitter ) { QHoverEvent hoverEvent( qobject_cast(_splitter.data()) ? QEvent::HoverLeave : QEvent::HoverMove, _splitter.data()->mapFromGlobal(QCursor::pos()), _hook); QCoreApplication::sendEvent( _splitter.data(), &hoverEvent ); _splitter.clear(); } // kill timer if any if( _timerId ) { killTimer( _timerId ); _timerId = 0; } } } diff --git a/kstyle/breezesplitterproxy.h b/kstyle/breezesplitterproxy.h index a675bab7..de47eb2e 100644 --- a/kstyle/breezesplitterproxy.h +++ b/kstyle/breezesplitterproxy.h @@ -1,138 +1,131 @@ #ifndef breezesplitterproxy_h #define breezesplitterproxy_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breeze.h" #include "breezeaddeventfilter.h" #include #include #include #include #include #include #include namespace Breeze { class SplitterProxy; //* factory class SplitterFactory: public QObject { Q_OBJECT public: //* constructor explicit SplitterFactory( QObject* parent ): QObject( parent ), _enabled( false ) {} - //* destructor - virtual ~SplitterFactory() - {} - //* enabled state void setEnabled( bool ); //* register widget bool registerWidget( QWidget* ); //* unregister widget void unregisterWidget( QWidget* ); private: //* enabled state bool _enabled; //* needed to block ChildAdded events when creating proxy AddEventFilter _addEventFilter; //* pointer to SplitterProxy using SplitterProxyPointer = WeakPointer; //* registered widgets using WidgetMap = QMap; WidgetMap _widgets; }; //* splitter 'proxy' widget, with extended hit area class SplitterProxy : public QWidget { Q_OBJECT public: //* constructor explicit SplitterProxy( QWidget*, bool = false ); - //* destructor - virtual ~SplitterProxy(); - //* event filter - virtual bool eventFilter( QObject*, QEvent* ); + bool eventFilter( QObject*, QEvent* ) override; //* enable state void setEnabled( bool ); //* enable state bool enabled() const { return _enabled; } protected: //* event handler - virtual bool event( QEvent* ); + bool event( QEvent* ) override; protected: //* reset 'true' splitter widget void clearSplitter(); //* keep track of 'true' splitter widget void setSplitter( QWidget* ); private: //* enabled state bool _enabled; //* splitter object WeakPointer _splitter; //* hook QPoint _hook; //* timer id int _timerId; }; } #endif diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp index f03b9b2f..3a77a7bb 100644 --- a/kstyle/breezestyle.cpp +++ b/kstyle/breezestyle.cpp @@ -1,7292 +1,7289 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezestyle.h" #include "breeze.h" #include "breezeanimations.h" #include "breezeframeshadow.h" #include "breezemdiwindowshadow.h" #include "breezemnemonics.h" #include "breezepropertynames.h" #include "breezeshadowhelper.h" #include "breezesplitterproxy.h" #include "breezestyleconfigdata.h" #include "breezewidgetexplorer.h" #include "breezewindowmanager.h" #include "breezeblurhelper.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if BREEZE_HAVE_QTQUICK #include #endif namespace BreezePrivate { // needed to keep track of tabbars when being dragged class TabBarData: public QObject { public: //* constructor explicit TabBarData( QObject* parent ): QObject( parent ) {} //* assign target tabBar void lock( const QWidget* widget ) { _tabBar = widget; } //* true if tabbar is locked bool isLocked( const QWidget* widget ) const { return _tabBar && _tabBar.data() == widget; } //* release void release() { _tabBar.clear(); } private: //* pointer to target tabBar Breeze::WeakPointer _tabBar; }; //* needed to have spacing added to items in combobox class ComboBoxItemDelegate: public QItemDelegate { public: //* constructor explicit ComboBoxItemDelegate( QAbstractItemView* parent ): QItemDelegate( parent ), _proxy( parent->itemDelegate() ), _itemMargin( Breeze::Metrics::ItemView_ItemMarginWidth ) {} //* paint - void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const + void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { // call either proxy or parent class if( _proxy ) _proxy.data()->paint( painter, option, index ); else QItemDelegate::paint( painter, option, index ); } //* size hint for index - virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const + QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override { // get size from either proxy or parent class auto size( _proxy ? _proxy.data()->sizeHint( option, index ): QItemDelegate::sizeHint( option, index ) ); // adjust and return if( size.isValid() ) { size.rheight() += _itemMargin*2; } return size; } private: //* proxy Breeze::WeakPointer _proxy; //* margin int _itemMargin; }; //_______________________________________________________________ - #if !BREEZE_USE_KDE4 bool isProgressBarHorizontal( const QStyleOptionProgressBar* option ) { return option && ( (option->state & QStyle::State_Horizontal ) || option->orientation == Qt::Horizontal ); } #endif } namespace Breeze { //______________________________________________________________ Style::Style(): - _addLineButtons( SingleButton ) - , _subLineButtons( SingleButton ) #if BREEZE_USE_KDE4 - , _helper( new Helper( "breeze" ) ) + _helper( new Helper( "breeze" ) ) #else - , _helper( new Helper( StyleConfigData::self()->sharedConfig() ) ) + _helper( new Helper( StyleConfigData::self()->sharedConfig() ) ) #endif , _shadowHelper( new ShadowHelper( this, *_helper ) ) , _animations( new Animations( this ) ) , _mnemonics( new Mnemonics( this ) ) #if !BREEZE_USE_KDE4 , _blurHelper( new BlurHelper( this ) ) #endif , _windowManager( new WindowManager( this ) ) , _frameShadowFactory( new FrameShadowFactory( this ) ) , _mdiWindowShadowFactory( new MdiWindowShadowFactory( this ) ) , _splitterFactory( new SplitterFactory( this ) ) , _widgetExplorer( new WidgetExplorer( this ) ) , _tabBarData( new BreezePrivate::TabBarData( this ) ) #if BREEZE_HAVE_KSTYLE||BREEZE_USE_KDE4 , SH_ArgbDndWindow( newStyleHint( QStringLiteral( "SH_ArgbDndWindow" ) ) ) , CE_CapacityBar( newControlElement( QStringLiteral( "CE_CapacityBar" ) ) ) #endif { // use DBus connection to update on breeze configuration change auto dbus = QDBusConnection::sessionBus(); dbus.connect( QString(), QStringLiteral( "/BreezeStyle" ), QStringLiteral( "org.kde.Breeze.Style" ), QStringLiteral( "reparseConfiguration" ), this, SLOT(configurationChanged()) ); dbus.connect( QString(), QStringLiteral( "/BreezeDecoration" ), QStringLiteral( "org.kde.Breeze.Style" ), QStringLiteral( "reparseConfiguration" ), this, SLOT(configurationChanged()) ); #if !BREEZE_USE_KDE4 connect(qApp, &QApplication::paletteChanged, this, &Style::configurationChanged); #endif // 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() { delete _shadowHelper; delete _helper; } //______________________________________________________________ void Style::polish( QWidget* widget ) { if( !widget ) return; // register widget to animations _animations->registerWidget( widget ); _windowManager->registerWidget( widget ); _frameShadowFactory->registerWidget( widget, *_helper ); _mdiWindowShadowFactory->registerWidget( widget ); _shadowHelper->registerWidget( widget ); _splitterFactory->registerWidget( widget ); // enable mouse over effects for all necessary widgets if( qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || widget->inherits( "KTextEditor::View" ) ) { widget->setAttribute( Qt::WA_Hover ); } // enforce translucency for drag and drop window if( widget->testAttribute( Qt::WA_X11NetWmWindowTypeDND ) && _helper->compositingActive() ) { widget->setAttribute( Qt::WA_TranslucentBackground ); widget->clearMask(); } // scrollarea polishing is somewhat complex. It is moved to a dedicated method polishScrollArea( qobject_cast( widget ) ); if( auto itemView = qobject_cast( widget ) ) { // enable mouse over effects in itemviews' viewport itemView->viewport()->setAttribute( Qt::WA_Hover ); } else if( auto groupBox = qobject_cast( widget ) ) { // checkable group boxes if( groupBox->isCheckable() ) { groupBox->setAttribute( Qt::WA_Hover ); } } else if( qobject_cast( widget ) && qobject_cast( widget->parent() ) ) { widget->setAttribute( Qt::WA_Hover ); } else if( qobject_cast( widget ) && qobject_cast( widget->parent() ) ) { widget->setAttribute( Qt::WA_Hover ); } else if( qobject_cast( widget ) && widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ) { widget->setAutoFillBackground( false ); if( !StyleConfigData::titleWidgetDrawFrame() ) { widget->setBackgroundRole( QPalette::Window ); } } if( qobject_cast( widget ) ) { // remove opaque painting for scrollbars widget->setAttribute( Qt::WA_OpaquePaintEvent, false ); } else if( widget->inherits( "KTextEditor::View" ) ) { addEventFilter( widget ); } else if( auto toolButton = qobject_cast( widget ) ) { if( toolButton->autoRaise() ) { // for flat toolbuttons, adjust foreground and background role accordingly widget->setBackgroundRole( QPalette::NoRole ); widget->setForegroundRole( QPalette::WindowText ); } if( widget->parentWidget() && widget->parentWidget()->parentWidget() && widget->parentWidget()->parentWidget()->inherits( "Gwenview::SideBarGroup" ) ) { widget->setProperty( PropertyNames::toolButtonAlignment, Qt::AlignLeft ); } } else if( qobject_cast( widget ) ) { // add event filter on dock widgets // and alter palette widget->setAutoFillBackground( false ); widget->setContentsMargins( Metrics::Frame_FrameWidth, Metrics::Frame_FrameWidth, Metrics::Frame_FrameWidth, Metrics::Frame_FrameWidth ); addEventFilter( widget ); } else if( qobject_cast( widget ) ) { widget->setAutoFillBackground( false ); addEventFilter( widget ); } else if( qobject_cast( widget ) ) { widget->setBackgroundRole( QPalette::NoRole ); widget->setAutoFillBackground( false ); } else if( widget->parentWidget() && widget->parentWidget()->parentWidget() && qobject_cast( widget->parentWidget()->parentWidget()->parentWidget() ) ) { widget->setBackgroundRole( QPalette::NoRole ); widget->setAutoFillBackground( false ); widget->parentWidget()->setAutoFillBackground( false ); } else if( qobject_cast( widget ) ) { setTranslucentBackground( widget ); #if !BREEZE_USE_KDE4 if ( _helper->hasAlphaChannel( widget ) && StyleConfigData::menuOpacity() < 100 ) { _blurHelper->registerWidget( widget->window() ); } #endif #if QT_VERSION >= 0x050000 } else if( qobject_cast( widget ) ) { addEventFilter( widget ); #endif } else if( auto comboBox = qobject_cast( widget ) ) { if( !hasParent( widget, "QWebView" ) ) { auto itemView( comboBox->view() ); if( itemView && itemView->itemDelegate() && itemView->itemDelegate()->inherits( "QComboBoxDelegate" ) ) { itemView->setItemDelegate( new BreezePrivate::ComboBoxItemDelegate( itemView ) ); } } } else if( widget->inherits( "QComboBoxPrivateContainer" ) ) { addEventFilter( widget ); setTranslucentBackground( widget ); } else if( widget->inherits( "QTipLabel" ) ) { setTranslucentBackground( widget ); } // base class polishing ParentStyleClass::polish( widget ); } //______________________________________________________________ void Style::polishScrollArea( QAbstractScrollArea* scrollArea ) { // check argument if( !scrollArea ) return; // enable mouse over effect in sunken scrollareas that support focus if( scrollArea->frameShadow() == QFrame::Sunken && scrollArea->focusPolicy()&Qt::StrongFocus ) { scrollArea->setAttribute( Qt::WA_Hover ); } if( scrollArea->viewport() && scrollArea->inherits( "KItemListContainer" ) && scrollArea->frameShape() == QFrame::NoFrame ) { scrollArea->viewport()->setBackgroundRole( QPalette::Window ); scrollArea->viewport()->setForegroundRole( QPalette::WindowText ); } // add event filter, to make sure proper background is rendered behind scrollbars addEventFilter( scrollArea ); // force side panels as flat, on option if( scrollArea->inherits( "KDEPrivate::KPageListView" ) || scrollArea->inherits( "KDEPrivate::KPageTreeView" ) ) { scrollArea->setProperty( PropertyNames::sidePanelView, true ); } // for all side view panels, unbold font (design choice) if( scrollArea->property( PropertyNames::sidePanelView ).toBool() ) { // upbold list font auto font( scrollArea->font() ); font.setBold( false ); scrollArea->setFont( font ); // adjust background role if( !StyleConfigData::sidePanelDrawFrame() ) { scrollArea->setBackgroundRole( QPalette::Window ); scrollArea->setForegroundRole( QPalette::WindowText ); if( scrollArea->viewport() ) { scrollArea->viewport()->setBackgroundRole( QPalette::Window ); scrollArea->viewport()->setForegroundRole( QPalette::WindowText ); } // QTreeView animates expanding/collapsing branches. It paints them into a // temp pixmap whose background is unconditionally filled with the palette's // *base* color which is usually different from the window's color // cf. QTreeViewPrivate::renderTreeToPixmapForAnimation() if ( auto treeView = qobject_cast( scrollArea ) ) { if (treeView->isAnimated()) { QPalette pal( treeView->palette() ); pal.setColor( QPalette::Active, QPalette::Base, treeView->palette().color( treeView->backgroundRole() ) ); treeView->setPalette(pal); } } } } // disable autofill background for flat (== NoFrame) scrollareas, with QPalette::Window as a background // this fixes flat scrollareas placed in a tinted widget, such as groupboxes, tabwidgets or framed dock-widgets if( !(scrollArea->frameShape() == QFrame::NoFrame || scrollArea->backgroundRole() == QPalette::Window ) ) { return; } // get viewport and check background role auto viewport( scrollArea->viewport() ); if( !( viewport && viewport->backgroundRole() == QPalette::Window ) ) return; // change viewport autoFill background. // do the same for all children if the background role is QPalette::Window viewport->setAutoFillBackground( false ); QList children( viewport->findChildren() ); foreach( QWidget* child, children ) { if( child->parent() == viewport && child->backgroundRole() == QPalette::Window ) { child->setAutoFillBackground( false ); } } } //_______________________________________________________________ void Style::unpolish( QWidget* widget ) { // register widget to animations _animations->unregisterWidget( widget ); _frameShadowFactory->unregisterWidget( widget ); _mdiWindowShadowFactory->unregisterWidget( widget ); _shadowHelper->unregisterWidget( widget ); _windowManager->unregisterWidget( widget ); _splitterFactory->unregisterWidget( widget ); #if !BREEZE_USE_KDE4 _blurHelper->unregisterWidget( widget ); #endif // remove event filter if( qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || widget->inherits( "QComboBoxPrivateContainer" ) ) { widget->removeEventFilter( this ); } ParentStyleClass::unpolish( widget ); } //______________________________________________________________ int Style::pixelMetric( PixelMetric metric, const QStyleOption* option, const QWidget* widget ) const { // handle special cases switch( metric ) { // frame width case PM_DefaultFrameWidth: if( qobject_cast( widget ) ) return Metrics::Menu_FrameWidth; if( qobject_cast( widget ) ) return Metrics::LineEdit_FrameWidth; #if QT_VERSION >= 0x050000 else if( isQtQuickControl( option, widget ) ) { const QString &elementType = option->styleObject->property( "elementType" ).toString(); if( elementType == QLatin1String( "edit" ) || elementType == QLatin1String( "spinbox" ) ) { return Metrics::LineEdit_FrameWidth; } else if( elementType == QLatin1String( "combobox" ) ) { return Metrics::ComboBox_FrameWidth; } } #endif // fallback return Metrics::Frame_FrameWidth; case PM_ComboBoxFrameWidth: { const auto comboBoxOption( qstyleoption_cast< const QStyleOptionComboBox*>( option ) ); return comboBoxOption && comboBoxOption->editable ? Metrics::LineEdit_FrameWidth : Metrics::ComboBox_FrameWidth; } case PM_SpinBoxFrameWidth: return Metrics::SpinBox_FrameWidth; case PM_ToolBarFrameWidth: return Metrics::ToolBar_FrameWidth; case PM_ToolTipLabelFrameWidth: return Metrics::ToolTip_FrameWidth; // layout case PM_LayoutLeftMargin: case PM_LayoutTopMargin: case PM_LayoutRightMargin: case PM_LayoutBottomMargin: { /* * use either Child margin or TopLevel margin, * depending on widget type */ if( ( option && ( option->state & QStyle::State_Window ) ) || ( widget && widget->isWindow() ) ) { return Metrics::Layout_TopLevelMarginWidth; } else if( widget && widget->inherits( "KPageView" ) ) { return 0; } else { return Metrics::Layout_ChildMarginWidth; } } case PM_LayoutHorizontalSpacing: return Metrics::Layout_DefaultSpacing; case PM_LayoutVerticalSpacing: return Metrics::Layout_DefaultSpacing; // buttons case PM_ButtonMargin: { // needs special case for kcalc buttons, to prevent the application to set too small margins if( widget && widget->inherits( "KCalcButton" ) ) return Metrics::Button_MarginWidth + 4; else return Metrics::Button_MarginWidth; } case PM_ButtonDefaultIndicator: return 0; case PM_ButtonShiftHorizontal: return 0; case PM_ButtonShiftVertical: return 0; // menubars case PM_MenuBarPanelWidth: return 0; case PM_MenuBarHMargin: return 0; case PM_MenuBarVMargin: return 0; case PM_MenuBarItemSpacing: return 0; case PM_MenuDesktopFrameWidth: return 0; // menu buttons case PM_MenuButtonIndicator: return Metrics::MenuButton_IndicatorWidth; // toolbars case PM_ToolBarHandleExtent: return Metrics::ToolBar_HandleExtent; case PM_ToolBarSeparatorExtent: return Metrics::ToolBar_SeparatorWidth; case PM_ToolBarExtensionExtent: return pixelMetric( PM_SmallIconSize, option, widget ) + 2*Metrics::ToolButton_MarginWidth; case PM_ToolBarItemMargin: return 0; case PM_ToolBarItemSpacing: return Metrics::ToolBar_ItemSpacing; // tabbars case PM_TabBarTabShiftVertical: return 0; case PM_TabBarTabShiftHorizontal: return 0; case PM_TabBarTabOverlap: return Metrics::TabBar_TabOverlap; case PM_TabBarBaseOverlap: return Metrics::TabBar_BaseOverlap; case PM_TabBarTabHSpace: return 2*Metrics::TabBar_TabMarginWidth; case PM_TabBarTabVSpace: return 2*Metrics::TabBar_TabMarginHeight; case PM_TabCloseIndicatorWidth: case PM_TabCloseIndicatorHeight: return pixelMetric( PM_SmallIconSize, option, widget ); // scrollbars case PM_ScrollBarExtent: return Metrics::ScrollBar_Extend; case PM_ScrollBarSliderMin: return Metrics::ScrollBar_MinSliderHeight; // title bar case PM_TitleBarHeight: return 2*Metrics::TitleBar_MarginWidth + pixelMetric( PM_SmallIconSize, option, widget ); // sliders case PM_SliderThickness: return Metrics::Slider_ControlThickness; case PM_SliderControlThickness: return Metrics::Slider_ControlThickness; case PM_SliderLength: return Metrics::Slider_ControlThickness; // checkboxes and radio buttons case PM_IndicatorWidth: return Metrics::CheckBox_Size; case PM_IndicatorHeight: return Metrics::CheckBox_Size; case PM_ExclusiveIndicatorWidth: return Metrics::CheckBox_Size; case PM_ExclusiveIndicatorHeight: return Metrics::CheckBox_Size; // list heaaders case PM_HeaderMarkSize: return Metrics::Header_ArrowSize; case PM_HeaderMargin: return Metrics::Header_MarginWidth; // dock widget // return 0 here, since frame is handled directly in polish case PM_DockWidgetFrameWidth: return 0; case PM_DockWidgetTitleMargin: return Metrics::Frame_FrameWidth; case PM_DockWidgetTitleBarButtonMargin: return Metrics::ToolButton_MarginWidth; case PM_SplitterWidth: return Metrics::Splitter_SplitterWidth; case PM_DockWidgetSeparatorExtent: return Metrics::Splitter_SplitterWidth; // fallback default: return ParentStyleClass::pixelMetric( metric, option, widget ); } } //______________________________________________________________ int Style::styleHint( StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData ) const { switch( hint ) { case SH_RubberBand_Mask: { if( auto mask = qstyleoption_cast( returnData ) ) { mask->region = option->rect; /* * need to check on widget before removing inner region * in order to still preserve rubberband in MainWindow and QGraphicsView * in QMainWindow because it looks better * in QGraphicsView because the painting fails completely otherwise */ if( widget && ( qobject_cast( widget->parent() ) || qobject_cast( widget->parent() ) || qobject_cast( widget->parent() ) ) ) { return true; } // also check if widget's parent is some itemView viewport if( widget && widget->parent() && qobject_cast( widget->parent()->parent() ) && static_cast( widget->parent()->parent() )->viewport() == widget->parent() ) { return true; } // mask out center mask->region -= insideMargin( option->rect, 1 ); return true; } return false; } case SH_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; #if QT_VERSION >= 0x050000 // TODO Qt6: drop deprecated SH_Widget_Animate case SH_Widget_Animate: return StyleConfigData::animationsEnabled(); case SH_Menu_SupportsSections: return true; #endif #if QT_VERSION >= 0x050A00 case SH_Widget_Animation_Duration: return StyleConfigData::animationsEnabled() ? StyleConfigData::animationsDuration() : 0; #endif case SH_DialogButtonBox_ButtonsHaveIcons: return true; case SH_GroupBox_TextLabelVerticalAlignment: return Qt::AlignVCenter; case SH_TabBar_Alignment: return StyleConfigData::tabBarDrawCenteredTabs() ? Qt::AlignCenter:Qt::AlignLeft; case SH_ToolBox_SelectedPageTitleBold: return false; case SH_ScrollBar_MiddleClickAbsolutePosition: return true; case SH_ScrollView_FrameOnlyAroundContents: return false; 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_ProgressDialog_CenterCancelButton: return false; case SH_MessageBox_CenterButtons: return false; case SH_RequestSoftwareInputPanel: return RSIP_OnMouseClick; case SH_TitleBar_NoBorder: return true; case SH_DockWidget_ButtonsHaveFrame: return false; default: return ParentStyleClass::styleHint( hint, option, widget, returnData ); } } //______________________________________________________________ QRect Style::subElementRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const { switch( element ) { case SE_PushButtonContents: return pushButtonContentsRect( option, widget ); case SE_CheckBoxContents: return checkBoxContentsRect( option, widget ); case SE_RadioButtonContents: return checkBoxContentsRect( option, widget ); case SE_LineEditContents: return lineEditContentsRect( option, widget ); case SE_ProgressBarGroove: return progressBarGrooveRect( option, widget ); case SE_ProgressBarContents: return progressBarContentsRect( option, widget ); case SE_ProgressBarLabel: return progressBarLabelRect( option, widget ); case SE_HeaderArrow: return headerArrowRect( option, widget ); case SE_HeaderLabel: return headerLabelRect( option, widget ); case SE_TabBarTabLeftButton: return tabBarTabLeftButtonRect( option, widget ); case SE_TabBarTabRightButton: return tabBarTabRightButtonRect( option, widget ); case SE_TabWidgetTabBar: return tabWidgetTabBarRect( option, widget ); case SE_TabWidgetTabContents: return tabWidgetTabContentsRect( option, widget ); case SE_TabWidgetTabPane: return tabWidgetTabPaneRect( option, widget ); case SE_TabWidgetLeftCorner: return tabWidgetCornerRect( SE_TabWidgetLeftCorner, option, widget ); case SE_TabWidgetRightCorner: return tabWidgetCornerRect( SE_TabWidgetRightCorner, option, widget ); case SE_ToolBoxTabContents: return toolBoxTabContentsRect( option, widget ); // fallback default: return ParentStyleClass::subElementRect( element, option, widget ); } } //______________________________________________________________ QRect Style::subControlRect( ComplexControl element, const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { switch( element ) { case CC_GroupBox: return groupBoxSubControlRect( option, subControl, widget ); case CC_ToolButton: return toolButtonSubControlRect( option, subControl, widget ); case CC_ComboBox: return comboBoxSubControlRect( option, subControl, widget ); case CC_SpinBox: return spinBoxSubControlRect( option, subControl, widget ); case CC_ScrollBar: return scrollBarSubControlRect( option, subControl, widget ); case CC_Dial: return dialSubControlRect( option, subControl, widget ); case CC_Slider: return sliderSubControlRect( option, subControl, widget ); // fallback default: return ParentStyleClass::subControlRect( element, option, subControl, widget ); } } //______________________________________________________________ QSize Style::sizeFromContents( ContentsType element, const QStyleOption* option, const QSize& size, const QWidget* widget ) const { switch( element ) { case CT_CheckBox: return checkBoxSizeFromContents( option, size, widget ); case CT_RadioButton: return checkBoxSizeFromContents( option, size, widget ); case CT_LineEdit: return lineEditSizeFromContents( option, size, widget ); case CT_ComboBox: return comboBoxSizeFromContents( option, size, widget ); case CT_SpinBox: return spinBoxSizeFromContents( option, size, widget ); case CT_Slider: return sliderSizeFromContents( option, size, widget ); case CT_PushButton: return pushButtonSizeFromContents( option, size, widget ); case CT_ToolButton: return toolButtonSizeFromContents( option, size, widget ); case CT_MenuBar: return defaultSizeFromContents( option, size, widget ); case CT_MenuBarItem: return menuBarItemSizeFromContents( option, size, widget ); case CT_MenuItem: return menuItemSizeFromContents( option, size, widget ); case CT_ProgressBar: return progressBarSizeFromContents( option, size, widget ); case CT_TabWidget: return tabWidgetSizeFromContents( option, size, widget ); case CT_TabBarTab: return tabBarTabSizeFromContents( option, size, widget ); case CT_HeaderSection: return headerSectionSizeFromContents( option, size, widget ); case CT_ItemViewItem: return itemViewItemSizeFromContents( option, size, widget ); // fallback default: return ParentStyleClass::sizeFromContents( element, option, size, widget ); } } //______________________________________________________________ QStyle::SubControl Style::hitTestComplexControl( ComplexControl control, const QStyleOptionComplex* option, const QPoint& point, const QWidget* widget ) const { switch( control ) { case CC_ScrollBar: { auto grooveRect = subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ); if( grooveRect.contains( point ) ) { // Must be either page up/page down, or just click on the slider. auto sliderRect = subControlRect( CC_ScrollBar, option, SC_ScrollBarSlider, widget ); if( sliderRect.contains( point ) ) return SC_ScrollBarSlider; else if( preceeds( point, sliderRect, option ) ) return SC_ScrollBarSubPage; else return SC_ScrollBarAddPage; } // This is one of the up/down buttons. First, decide which one it is. if( preceeds( point, grooveRect, option ) ) { if( _subLineButtons == DoubleButton ) { auto buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarSubLine ); return scrollBarHitTest( buttonRect, point, option ); } else return SC_ScrollBarSubLine; } if( _addLineButtons == DoubleButton ) { auto buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarAddLine ); return scrollBarHitTest( buttonRect, point, option ); } else return SC_ScrollBarAddLine; } // fallback default: return ParentStyleClass::hitTestComplexControl( control, option, point, widget ); } } //______________________________________________________________ void Style::drawPrimitive( PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { StylePrimitive fcn; switch( element ) { case PE_PanelButtonCommand: fcn = &Style::drawPanelButtonCommandPrimitive; break; case PE_PanelButtonTool: fcn = &Style::drawPanelButtonToolPrimitive; break; case PE_PanelScrollAreaCorner: fcn = &Style::drawPanelScrollAreaCornerPrimitive; break; case PE_PanelMenu: fcn = &Style::drawPanelMenuPrimitive; break; case PE_PanelTipLabel: fcn = &Style::drawPanelTipLabelPrimitive; break; case PE_PanelItemViewItem: fcn = &Style::drawPanelItemViewItemPrimitive; break; case PE_IndicatorCheckBox: fcn = &Style::drawIndicatorCheckBoxPrimitive; break; case PE_IndicatorRadioButton: fcn = &Style::drawIndicatorRadioButtonPrimitive; break; case PE_IndicatorButtonDropDown: fcn = &Style::drawIndicatorButtonDropDownPrimitive; break; case PE_IndicatorTabClose: fcn = &Style::drawIndicatorTabClosePrimitive; break; case PE_IndicatorTabTear: fcn = &Style::drawIndicatorTabTearPrimitive; break; case PE_IndicatorArrowUp: fcn = &Style::drawIndicatorArrowUpPrimitive; break; case PE_IndicatorArrowDown: fcn = &Style::drawIndicatorArrowDownPrimitive; break; case PE_IndicatorArrowLeft: fcn = &Style::drawIndicatorArrowLeftPrimitive; break; case PE_IndicatorArrowRight: fcn = &Style::drawIndicatorArrowRightPrimitive; break; case PE_IndicatorHeaderArrow: fcn = &Style::drawIndicatorHeaderArrowPrimitive; break; case PE_IndicatorToolBarHandle: fcn = &Style::drawIndicatorToolBarHandlePrimitive; break; case PE_IndicatorToolBarSeparator: fcn = &Style::drawIndicatorToolBarSeparatorPrimitive; break; case PE_IndicatorBranch: fcn = &Style::drawIndicatorBranchPrimitive; break; case PE_FrameStatusBar: fcn = &Style::emptyPrimitive; break; case PE_Frame: fcn = &Style::drawFramePrimitive; break; case PE_FrameLineEdit: fcn = &Style::drawFrameLineEditPrimitive; break; case PE_FrameMenu: fcn = &Style::drawFrameMenuPrimitive; break; case PE_FrameGroupBox: fcn = &Style::drawFrameGroupBoxPrimitive; break; case PE_FrameTabWidget: fcn = &Style::drawFrameTabWidgetPrimitive; break; case PE_FrameTabBarBase: fcn = &Style::drawFrameTabBarBasePrimitive; break; case PE_FrameWindow: fcn = &Style::drawFrameWindowPrimitive; break; case PE_FrameFocusRect: fcn = _frameFocusPrimitive; break; // fallback default: break; } painter->save(); // call function if implemented if( !( fcn && fcn( *this, option, painter, widget ) ) ) { ParentStyleClass::drawPrimitive( element, option, painter, widget ); } painter->restore(); } //______________________________________________________________ void Style::drawControl( ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { StyleControl fcn; #if BREEZE_HAVE_KSTYLE||BREEZE_USE_KDE4 if( element == CE_CapacityBar ) { fcn = &Style::drawProgressBarControl; } else #endif switch( element ) { case CE_PushButtonBevel: fcn = &Style::drawPanelButtonCommandPrimitive; break; case CE_PushButtonLabel: fcn = &Style::drawPushButtonLabelControl; break; case CE_CheckBoxLabel: fcn = &Style::drawCheckBoxLabelControl; break; case CE_RadioButtonLabel: fcn = &Style::drawCheckBoxLabelControl; break; case CE_ToolButtonLabel: fcn = &Style::drawToolButtonLabelControl; break; case CE_ComboBoxLabel: fcn = &Style::drawComboBoxLabelControl; break; case CE_MenuBarEmptyArea: fcn = &Style::emptyControl; break; case CE_MenuBarItem: fcn = &Style::drawMenuBarItemControl; break; case CE_MenuItem: fcn = &Style::drawMenuItemControl; break; case CE_ToolBar: fcn = &Style::emptyControl; break; case CE_ProgressBar: fcn = &Style::drawProgressBarControl; break; case CE_ProgressBarContents: fcn = &Style::drawProgressBarContentsControl; break; case CE_ProgressBarGroove: fcn = &Style::drawProgressBarGrooveControl; break; case CE_ProgressBarLabel: fcn = &Style::drawProgressBarLabelControl; break; case CE_ScrollBarSlider: fcn = &Style::drawScrollBarSliderControl; break; case CE_ScrollBarAddLine: fcn = &Style::drawScrollBarAddLineControl; break; case CE_ScrollBarSubLine: fcn = &Style::drawScrollBarSubLineControl; break; case CE_ScrollBarAddPage: fcn = &Style::emptyControl; break; case CE_ScrollBarSubPage: fcn = &Style::emptyControl; break; case CE_ShapedFrame: fcn = &Style::drawShapedFrameControl; break; case CE_RubberBand: fcn = &Style::drawRubberBandControl; break; case CE_SizeGrip: fcn = &Style::emptyControl; break; case CE_HeaderSection: fcn = &Style::drawHeaderSectionControl; break; case CE_HeaderEmptyArea: fcn = &Style::drawHeaderEmptyAreaControl; break; case CE_TabBarTabLabel: fcn = &Style::drawTabBarTabLabelControl; break; case CE_TabBarTabShape: fcn = &Style::drawTabBarTabShapeControl; break; case CE_ToolBoxTabLabel: fcn = &Style::drawToolBoxTabLabelControl; break; case CE_ToolBoxTabShape: fcn = &Style::drawToolBoxTabShapeControl; break; case CE_DockWidgetTitle: fcn = &Style::drawDockWidgetTitleControl; break; // fallback default: break; } painter->save(); // call function if implemented if( !( fcn && fcn( *this, option, painter, widget ) ) ) { ParentStyleClass::drawControl( element, option, painter, widget ); } painter->restore(); } //______________________________________________________________ void Style::drawComplexControl( ComplexControl element, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { StyleComplexControl fcn; switch( element ) { case CC_GroupBox: fcn = &Style::drawGroupBoxComplexControl; break; case CC_ToolButton: fcn = &Style::drawToolButtonComplexControl; break; case CC_ComboBox: fcn = &Style::drawComboBoxComplexControl; break; case CC_SpinBox: fcn = &Style::drawSpinBoxComplexControl; break; case CC_Slider: fcn = &Style::drawSliderComplexControl; break; case CC_Dial: fcn = &Style::drawDialComplexControl; break; case CC_ScrollBar: fcn = &Style::drawScrollBarComplexControl; break; case CC_TitleBar: fcn = &Style::drawTitleBarComplexControl; break; // fallback default: break; } painter->save(); // call function if implemented if( !( fcn && fcn( *this, option, painter, widget ) ) ) { ParentStyleClass::drawComplexControl( element, option, painter, widget ); } painter->restore(); } //___________________________________________________________________________________ void Style::drawItemText( QPainter* painter, const QRect& rect, int flags, const QPalette& palette, bool enabled, const QString &text, QPalette::ColorRole textRole ) const { // hide mnemonics if requested if( !_mnemonics->enabled() && ( flags&Qt::TextShowMnemonic ) && !( flags&Qt::TextHideMnemonic ) ) { flags &= ~Qt::TextShowMnemonic; flags |= Qt::TextHideMnemonic; } // make sure vertical alignment is defined // fallback on Align::VCenter if not if( !(flags&Qt::AlignVertical_Mask) ) flags |= Qt::AlignVCenter; if( _animations->widgetEnabilityEngine().enabled() ) { /* * check if painter engine is registered to WidgetEnabilityEngine, and animated * if yes, merge the palettes. Note: a static_cast is safe here, since only the address * of the pointer is used, not the actual content. */ const QWidget* widget( static_cast( painter->device() ) ); if( _animations->widgetEnabilityEngine().isAnimated( widget, AnimationEnable ) ) { const QPalette copy( _helper->disabledPalette( palette, _animations->widgetEnabilityEngine().opacity( widget, AnimationEnable ) ) ); return ParentStyleClass::drawItemText( painter, rect, flags, copy, enabled, text, textRole ); } } // fallback return ParentStyleClass::drawItemText( painter, rect, flags, palette, enabled, text, textRole ); } //_____________________________________________________________________ bool Style::eventFilter( QObject *object, QEvent *event ) { if( auto dockWidget = qobject_cast( object ) ) { return eventFilterDockWidget( dockWidget, event ); } else if( auto subWindow = qobject_cast( object ) ) { return eventFilterMdiSubWindow( subWindow, event ); } #if QT_VERSION >= 0x050000 else if( auto commandLinkButton = qobject_cast( object ) ) { return eventFilterCommandLinkButton( commandLinkButton, event ); } #endif // cast to QWidget QWidget *widget = static_cast( object ); if( widget->inherits( "QAbstractScrollArea" ) || widget->inherits( "KTextEditor::View" ) ) { return eventFilterScrollArea( widget, event ); } else if( widget->inherits( "QComboBoxPrivateContainer" ) ) { return eventFilterComboBoxContainer( widget, event ); } // fallback return ParentStyleClass::eventFilter( object, event ); } //____________________________________________________________________________ bool Style::eventFilterScrollArea( QWidget* widget, QEvent* event ) { switch( event->type() ) { case QEvent::Paint: { // get scrollarea viewport auto scrollArea( qobject_cast( widget ) ); QWidget* viewport; if( !( scrollArea && (viewport = scrollArea->viewport()) ) ) break; // get scrollarea horizontal and vertical containers QWidget* child( nullptr ); QList children; if( ( child = scrollArea->findChild( "qt_scrollarea_vcontainer" ) ) && child->isVisible() ) { children.append( child ); } if( ( child = scrollArea->findChild( "qt_scrollarea_hcontainer" ) ) && child->isVisible() ) { children.append( child ); } if( children.empty() ) break; if( !scrollArea->styleSheet().isEmpty() ) break; // make sure proper background is rendered behind the containers QPainter painter( scrollArea ); painter.setClipRegion( static_cast( event )->region() ); painter.setPen( Qt::NoPen ); // decide background color const QPalette::ColorRole role( viewport->backgroundRole() ); QColor background; if( role == QPalette::Window && hasAlteredBackground( viewport ) ) background = _helper->frameBackgroundColor( viewport->palette() ); else background = viewport->palette().color( role ); painter.setBrush( background ); // render foreach( auto* child, children ) { painter.drawRect( child->geometry() ); } } break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: { // case event QMouseEvent* mouseEvent( static_cast( event ) ); // get frame framewidth const int frameWidth( pixelMetric( PM_DefaultFrameWidth, nullptr, widget ) ); // find list of scrollbars QList scrollBars; if( auto scrollArea = qobject_cast( widget ) ) { if( scrollArea->horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff ) scrollBars.append( scrollArea->horizontalScrollBar() ); if( scrollArea->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff )scrollBars.append( scrollArea->verticalScrollBar() ); } else if( widget->inherits( "KTextEditor::View" ) ) { scrollBars = widget->findChildren(); } // loop over found scrollbars foreach( QScrollBar* scrollBar, scrollBars ) { if( !( scrollBar && scrollBar->isVisible() ) ) continue; QPoint offset; if( scrollBar->orientation() == Qt::Horizontal ) offset = QPoint( 0, frameWidth ); else offset = QPoint( QApplication::isLeftToRight() ? frameWidth : -frameWidth, 0 ); // map position to scrollarea QPoint position( scrollBar->mapFrom( widget, mouseEvent->pos() - offset ) ); // check if contains if( !scrollBar->rect().contains( position ) ) continue; // copy event, send and return QMouseEvent copy( mouseEvent->type(), position, scrollBar->mapToGlobal( position ), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); QCoreApplication::sendEvent( scrollBar, © ); event->setAccepted( true ); return true; } break; } default: break; } return ParentStyleClass::eventFilter( widget, event ); } //_________________________________________________________ bool Style::eventFilterComboBoxContainer( QWidget* widget, QEvent* event ) { if( event->type() == QEvent::Paint ) { QPainter painter( widget ); auto paintEvent = static_cast( event ); painter.setClipRegion( paintEvent->region() ); const auto rect( widget->rect() ); const auto& palette( widget->palette() ); const auto background( _helper->frameBackgroundColor( palette ) ); const auto outline( _helper->frameOutlineColor( palette ) ); const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); if( hasAlpha ) { painter.setCompositionMode( QPainter::CompositionMode_Source ); _helper->renderMenuFrame( &painter, rect, background, outline, true ); } else { _helper->renderMenuFrame( &painter, rect, background, outline, false ); } } return false; } //____________________________________________________________________________ bool Style::eventFilterDockWidget( QDockWidget* dockWidget, QEvent* event ) { if( event->type() == QEvent::Paint ) { // create painter and clip QPainter painter( dockWidget ); QPaintEvent *paintEvent = static_cast( event ); painter.setClipRegion( paintEvent->region() ); // store palette and set colors const auto& palette( dockWidget->palette() ); const auto background( _helper->frameBackgroundColor( palette ) ); const auto outline( _helper->frameOutlineColor( palette ) ); // store rect const auto rect( dockWidget->rect() ); // render if( dockWidget->isFloating() ) { _helper->renderMenuFrame( &painter, rect, background, outline, false ); } else if( StyleConfigData::dockWidgetDrawFrame() || (dockWidget->features()&QDockWidget::AllDockWidgetFeatures) ) { _helper->renderFrame( &painter, rect, background, outline ); } } return false; } //____________________________________________________________________________ bool Style::eventFilterMdiSubWindow( QMdiSubWindow* subWindow, QEvent* event ) { if( event->type() == QEvent::Paint ) { QPainter painter( subWindow ); QPaintEvent* paintEvent( static_cast( event ) ); painter.setClipRegion( paintEvent->region() ); const auto rect( subWindow->rect() ); const auto background( subWindow->palette().color( QPalette::Window ) ); if( subWindow->isMaximized() ) { // full painting painter.setPen( Qt::NoPen ); painter.setBrush( background ); painter.drawRect( rect ); } else { // framed painting _helper->renderMenuFrame( &painter, rect, background, QColor() ); } } // continue with normal painting return false; } //____________________________________________________________________________ #if QT_VERSION >= 0x050000 bool Style::eventFilterCommandLinkButton( QCommandLinkButton* button, QEvent* event ) { if( event->type() == QEvent::Paint ) { // painter QPainter painter( button ); painter.setClipRegion( static_cast( event )->region() ); const bool isFlat = false; // option QStyleOptionButton option; option.initFrom( button ); option.features |= QStyleOptionButton::CommandLinkButton; if( isFlat ) option.features |= QStyleOptionButton::Flat; option.text = QString(); option.icon = QIcon(); if( button->isChecked() ) option.state|=State_On; if( button->isDown() ) option.state|=State_Sunken; // frame drawControl(QStyle::CE_PushButton, &option, &painter, button ); // offset const int margin( Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth ); QPoint offset( margin, margin ); if( button->isDown() && !isFlat ) painter.translate( 1, 1 ); { offset += QPoint( 1, 1 ); } // state const State& state( option.state ); const bool enabled( state & State_Enabled ); bool mouseOver( enabled && ( state & State_MouseOver ) ); bool hasFocus( enabled && ( state & State_HasFocus ) ); // icon if( !button->icon().isNull() ) { const auto pixmapSize( button->icon().actualSize( button->iconSize() ) ); const QRect pixmapRect( QPoint( offset.x(), button->description().isEmpty() ? (button->height() - pixmapSize.height())/2:offset.y() ), pixmapSize ); const QPixmap pixmap( button->icon().pixmap(pixmapSize, enabled ? QIcon::Normal : QIcon::Disabled, button->isChecked() ? QIcon::On : QIcon::Off) ); drawItemPixmap( &painter, pixmapRect, Qt::AlignCenter, pixmap ); offset.rx() += pixmapSize.width() + Metrics::Button_ItemSpacing; } // text rect QRect textRect( offset, QSize( button->size().width() - offset.x() - margin, button->size().height() - 2*margin ) ); const QPalette::ColorRole textRole = (enabled && hasFocus && !mouseOver && !isFlat ) ? QPalette::HighlightedText : QPalette::ButtonText; if( !button->text().isEmpty() ) { QFont font( button->font() ); font.setBold( true ); painter.setFont( font ); if( button->description().isEmpty() ) { drawItemText( &painter, textRect, Qt::AlignLeft|Qt::AlignVCenter|Qt::TextHideMnemonic, button->palette(), enabled, button->text(), textRole ); } else { drawItemText( &painter, textRect, Qt::AlignLeft|Qt::AlignTop|Qt::TextHideMnemonic, button->palette(), enabled, button->text(), textRole ); textRect.setTop( textRect.top() + QFontMetrics( font ).height() ); } painter.setFont( button->font() ); } if( !button->description().isEmpty() ) { drawItemText( &painter, textRect, Qt::AlignLeft|Qt::AlignVCenter|Qt::TextWordWrap, button->palette(), enabled, button->description(), textRole ); } return true; } // continue with normal painting return false; } #endif //_____________________________________________________________________ void Style::configurationChanged() { // reload #if BREEZE_USE_KDE4 StyleConfigData::self()->readConfig(); #else StyleConfigData::self()->load(); #endif // reload configuration loadConfiguration(); } //____________________________________________________________________ QIcon Style::standardIconImplementation( StandardPixmap standardPixmap, const QStyleOption* option, const QWidget* widget ) const { // lookup cache if( _iconCache.contains( standardPixmap ) ) return _iconCache.value( standardPixmap ); QIcon icon; switch( standardPixmap ) { case SP_TitleBarNormalButton: case SP_TitleBarMinButton: case SP_TitleBarMaxButton: case SP_TitleBarCloseButton: case SP_DockWidgetCloseButton: icon = titleBarButtonIcon( standardPixmap, option, widget ); break; case SP_ToolBarHorizontalExtensionButton: case SP_ToolBarVerticalExtensionButton: icon = toolBarExtensionIcon( standardPixmap, option, widget ); break; default: break; } if( icon.isNull() ) { // do not cache parent style icon, since it may change at runtime #if QT_VERSION >= 0x050000 return ParentStyleClass::standardIcon( standardPixmap, option, widget ); #else return ParentStyleClass::standardIconImplementation( standardPixmap, option, widget ); #endif } else { const_cast(&_iconCache)->insert( standardPixmap, icon ); return icon; } } //_____________________________________________________________________ void Style::loadConfiguration() { // load helper configuration _helper->loadConfig(); // reinitialize engines _animations->setupEngines(); _windowManager->initialize(); // mnemonics _mnemonics->setMode( StyleConfigData::mnemonicsMode() ); // splitter proxy _splitterFactory->setEnabled( StyleConfigData::splitterProxyEnabled() ); // reset shadow tiles _shadowHelper->loadConfig(); // set mdiwindow factory shadow tiles _mdiWindowShadowFactory->setShadowHelper( _shadowHelper ); // clear icon cache _iconCache.clear(); // scrollbar buttons switch( StyleConfigData::scrollBarAddLineButtons() ) { case 0: _addLineButtons = NoButton; break; case 1: _addLineButtons = SingleButton; break; default: case 2: _addLineButtons = DoubleButton; break; } switch( StyleConfigData::scrollBarSubLineButtons() ) { case 0: _subLineButtons = NoButton; break; case 1: _subLineButtons = SingleButton; break; default: case 2: _subLineButtons = DoubleButton; break; } // frame focus if( StyleConfigData::viewDrawFocusIndicator() ) _frameFocusPrimitive = &Style::drawFrameFocusRectPrimitive; else _frameFocusPrimitive = &Style::emptyPrimitive; // widget explorer _widgetExplorer->setEnabled( StyleConfigData::widgetExplorerEnabled() ); _widgetExplorer->setDrawWidgetRects( StyleConfigData::drawWidgetRects() ); } //___________________________________________________________________________________________________________________ QRect Style::pushButtonContentsRect( const QStyleOption* option, const QWidget* ) const { return insideMargin( option->rect, Metrics::Frame_FrameWidth ); } //___________________________________________________________________________________________________________________ QRect Style::checkBoxContentsRect( const QStyleOption* option, const QWidget* ) const { return visualRect( option, option->rect.adjusted( Metrics::CheckBox_Size + Metrics::CheckBox_ItemSpacing, 0, 0, 0 ) ); } //___________________________________________________________________________________________________________________ QRect Style::lineEditContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const auto frameOption( qstyleoption_cast( option ) ); if( !frameOption ) return option->rect; // check flatness const bool flat( frameOption->lineWidth == 0 ); if( flat ) return option->rect; // copy rect and take out margins auto rect( option->rect ); // take out margins if there is enough room const int frameWidth( pixelMetric( PM_DefaultFrameWidth, option, widget ) ); if( rect.height() >= option->fontMetrics.height() + 2*frameWidth ) return insideMargin( rect, frameWidth ); else return rect; } //___________________________________________________________________________________________________________________ QRect Style::progressBarGrooveRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const auto progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return option->rect; // get flags and orientation const bool textVisible( progressBarOption->textVisible ); const bool busy( progressBarOption->minimum == 0 && progressBarOption->maximum == 0 ); #if BREEZE_USE_KDE4 const auto progressBarOption2( qstyleoption_cast( option ) ); const bool horizontal( !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal ); #else const bool horizontal( BreezePrivate::isProgressBarHorizontal( progressBarOption ) ); #endif // copy rectangle and adjust auto rect( option->rect ); const int frameWidth( pixelMetric( PM_DefaultFrameWidth, option, widget ) ); if( horizontal ) rect = insideMargin( rect, frameWidth, 0 ); else rect = insideMargin( rect, 0, frameWidth ); if( textVisible && !busy && horizontal ) { auto textRect( subElementRect( SE_ProgressBarLabel, option, widget ) ); textRect = visualRect( option, textRect ); rect.setRight( textRect.left() - Metrics::ProgressBar_ItemSpacing - 1 ); rect = visualRect( option, rect ); rect = centerRect( rect, rect.width(), Metrics::ProgressBar_Thickness ); } else if( horizontal ) { rect = centerRect( rect, rect.width(), Metrics::ProgressBar_Thickness ); } else { rect = centerRect( rect, Metrics::ProgressBar_Thickness, rect.height() ); } return rect; } //___________________________________________________________________________________________________________________ QRect Style::progressBarContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const auto progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return QRect(); // get groove rect const auto rect( progressBarGrooveRect( option, widget ) ); // in busy mode, grooveRect is used const bool busy( progressBarOption->minimum == 0 && progressBarOption->maximum == 0 ); if( busy ) return rect; // get orientation #if BREEZE_USE_KDE4 const auto progressBarOption2( qstyleoption_cast( option ) ); const bool horizontal( !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal ); #else const bool horizontal( BreezePrivate::isProgressBarHorizontal( progressBarOption ) ); #endif // check inverted appearance #if BREEZE_USE_KDE4 const bool inverted( progressBarOption2 ? progressBarOption2->invertedAppearance : false ); #else const bool inverted( progressBarOption->invertedAppearance ); #endif // get progress and steps const qreal progress( progressBarOption->progress - progressBarOption->minimum ); const int steps( qMax( progressBarOption->maximum - progressBarOption->minimum, 1 ) ); //Calculate width fraction const qreal widthFrac = qMin( qreal(1), progress/steps ); // convert the pixel width const int indicatorSize( widthFrac*( horizontal ? rect.width():rect.height() ) ); QRect indicatorRect; if( horizontal ) { indicatorRect = QRect( inverted ? ( rect.right() - indicatorSize + 1):rect.left(), rect.y(), indicatorSize, rect.height() ); indicatorRect = visualRect( option->direction, rect, indicatorRect ); } else indicatorRect = QRect( rect.x(), inverted ? rect.top() : (rect.bottom() - indicatorSize + 1), rect.width(), indicatorSize ); return indicatorRect; } //___________________________________________________________________________________________________________________ QRect Style::progressBarLabelRect( const QStyleOption* option, const QWidget* ) const { // cast option and check const auto progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return QRect(); // get flags and check const bool textVisible( progressBarOption->textVisible ); const bool busy( progressBarOption->minimum == 0 && progressBarOption->maximum == 0 ); if( !textVisible || busy ) return QRect(); // get direction and check #if BREEZE_USE_KDE4 const auto progressBarOption2( qstyleoption_cast( option ) ); const bool horizontal( !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal ); #else const bool horizontal( BreezePrivate::isProgressBarHorizontal( progressBarOption ) ); #endif if( !horizontal ) return QRect(); int textWidth = qMax( option->fontMetrics.size( _mnemonics->textFlags(), progressBarOption->text ).width(), option->fontMetrics.size( _mnemonics->textFlags(), QStringLiteral( "100%" ) ).width() ); auto rect( insideMargin( option->rect, Metrics::Frame_FrameWidth, 0 ) ); rect.setLeft( rect.right() - textWidth + 1 ); rect = visualRect( option, rect ); return rect; } //___________________________________________________________________________________________________________________ QRect Style::headerArrowRect( const QStyleOption* option, const QWidget* ) const { // cast option and check const auto headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return option->rect; // check if arrow is necessary if( headerOption->sortIndicator == QStyleOptionHeader::None ) return QRect(); auto arrowRect( insideMargin( option->rect, Metrics::Header_MarginWidth ) ); arrowRect.setLeft( arrowRect.right() - Metrics::Header_ArrowSize + 1 ); return visualRect( option, arrowRect ); } //___________________________________________________________________________________________________________________ QRect Style::headerLabelRect( const QStyleOption* option, const QWidget* ) const { // cast option and check const auto headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return option->rect; // check if arrow is necessary auto labelRect( insideMargin( option->rect, Metrics::Header_MarginWidth, 0 ) ); if( headerOption->sortIndicator == QStyleOptionHeader::None ) return labelRect; labelRect.adjust( 0, 0, -Metrics::Header_ArrowSize-Metrics::Header_ItemSpacing, 0 ); return visualRect( option, labelRect ); } //____________________________________________________________________ QRect Style::tabBarTabLeftButtonRect( const QStyleOption* option, const QWidget* ) const { // cast option and check #if BREEZE_USE_KDE4 const auto tabOption( qstyleoption_cast( option ) ); #else const auto tabOption( qstyleoption_cast( option ) ); #endif if( !tabOption || tabOption->leftButtonSize.isEmpty() ) return QRect(); const auto rect( option->rect ); const QSize size( tabOption->leftButtonSize ); QRect buttonRect( QPoint(0,0), size ); // vertical positioning switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: buttonRect.moveLeft( rect.left() + Metrics::TabBar_TabMarginWidth ); buttonRect.moveTop( ( rect.height() - buttonRect.height() )/2 ); buttonRect = visualRect( option, buttonRect ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: buttonRect.moveBottom( rect.bottom() - Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: buttonRect.moveTop( rect.top() + Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; default: break; } return buttonRect; } //____________________________________________________________________ QRect Style::tabBarTabRightButtonRect( const QStyleOption* option, const QWidget* ) const { // cast option and check #if BREEZE_USE_KDE4 const auto tabOption( qstyleoption_cast( option ) ); #else const auto tabOption( qstyleoption_cast( option ) ); #endif if( !tabOption || tabOption->rightButtonSize.isEmpty() ) return QRect(); const auto rect( option->rect ); const auto size( tabOption->rightButtonSize ); QRect buttonRect( QPoint(0,0), size ); // vertical positioning switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: buttonRect.moveRight( rect.right() - Metrics::TabBar_TabMarginWidth ); buttonRect.moveTop( ( rect.height() - buttonRect.height() )/2 ); buttonRect = visualRect( option, buttonRect ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: buttonRect.moveTop( rect.top() + Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: buttonRect.moveBottom( rect.bottom() - Metrics::TabBar_TabMarginWidth ); buttonRect.moveLeft( ( rect.width() - buttonRect.width() )/2 ); break; default: break; } return buttonRect; } //____________________________________________________________________ QRect Style::tabWidgetTabBarRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const auto tabOption = qstyleoption_cast( option ); if( !tabOption ) return ParentStyleClass::subElementRect( SE_TabWidgetTabBar, option, widget ); // do nothing if tabbar is hidden const QSize tabBarSize( tabOption->tabBarSize ); auto rect( option->rect ); QRect tabBarRect( QPoint(0, 0), tabBarSize ); Qt::Alignment tabBarAlignment( styleHint( SH_TabBar_Alignment, option, widget ) ); // horizontal positioning const bool verticalTabs( isVerticalTab( tabOption->shape ) ); if( verticalTabs ) { tabBarRect.setHeight( qMin( tabBarRect.height(), rect.height() - 2 ) ); if( tabBarAlignment == Qt::AlignCenter ) tabBarRect.moveTop( rect.top() + ( rect.height() - tabBarRect.height() )/2 ); else tabBarRect.moveTop( rect.top()+1 ); } else { // account for corner rects // need to re-run visualRect to remove right-to-left handling, since it is re-added on tabBarRect at the end const auto leftButtonRect( visualRect( option, subElementRect( SE_TabWidgetLeftCorner, option, widget ) ) ); const auto rightButtonRect( visualRect( option, subElementRect( SE_TabWidgetRightCorner, option, widget ) ) ); rect.setLeft( leftButtonRect.width() ); rect.setRight( rightButtonRect.left() - 1 ); tabBarRect.setWidth( qMin( tabBarRect.width(), rect.width() - 2 ) ); if( tabBarAlignment == Qt::AlignCenter ) tabBarRect.moveLeft( rect.left() + (rect.width() - tabBarRect.width())/2 ); else tabBarRect.moveLeft( rect.left() + 1 ); tabBarRect = visualRect( option, tabBarRect ); } // vertical positioning switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: tabBarRect.moveTop( rect.top()+1 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: tabBarRect.moveBottom( rect.bottom()-1 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: tabBarRect.moveLeft( rect.left()+1 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: tabBarRect.moveRight( rect.right()-1 ); break; default: break; } return tabBarRect; } //____________________________________________________________________ QRect Style::tabWidgetTabContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const auto tabOption = qstyleoption_cast( option ); if( !tabOption ) return option->rect; // do nothing if tabbar is hidden if( tabOption->tabBarSize.isEmpty() ) return option->rect; const auto rect = tabWidgetTabPaneRect( option, widget ); const bool documentMode( tabOption->lineWidth == 0 ); if( documentMode ) { // add margin only to the relevant side switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: return rect.adjusted( 0, Metrics::TabWidget_MarginWidth, 0, 0 ); case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: return rect.adjusted( 0, 0, 0, -Metrics::TabWidget_MarginWidth ); case QTabBar::RoundedWest: case QTabBar::TriangularWest: return rect.adjusted( Metrics::TabWidget_MarginWidth, 0, 0, 0 ); case QTabBar::RoundedEast: case QTabBar::TriangularEast: return rect.adjusted( 0, 0, -Metrics::TabWidget_MarginWidth, 0 ); default: return rect; } } else return insideMargin( rect, Metrics::TabWidget_MarginWidth ); } //____________________________________________________________________ QRect Style::tabWidgetTabPaneRect( const QStyleOption* option, const QWidget* ) const { const auto tabOption = qstyleoption_cast( option ); if( !tabOption || tabOption->tabBarSize.isEmpty() ) return option->rect; const int overlap = Metrics::TabBar_BaseOverlap - 1; const QSize tabBarSize( tabOption->tabBarSize - QSize( overlap, overlap ) ); auto rect( option->rect ); switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: rect.adjust( 0, tabBarSize.height(), 0, 0 ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: rect.adjust( 0, 0, 0, -tabBarSize.height() ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: rect.adjust( tabBarSize.width(), 0, 0, 0 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: rect.adjust( 0, 0, -tabBarSize.width(), 0 ); break; default: return QRect(); } return rect; } //____________________________________________________________________ QRect Style::tabWidgetCornerRect( SubElement element, const QStyleOption* option, const QWidget* ) const { // cast option and check const auto tabOption = qstyleoption_cast( option ); if( !tabOption ) return option->rect; // do nothing if tabbar is hidden const QSize tabBarSize( tabOption->tabBarSize ); if( tabBarSize.isEmpty() ) return QRect(); // do nothing for vertical tabs const bool verticalTabs( isVerticalTab( tabOption->shape ) ); if( verticalTabs ) return QRect(); const auto rect( option->rect ); QRect cornerRect; switch( element ) { case SE_TabWidgetLeftCorner: cornerRect = QRect( QPoint(0,0), tabOption->leftCornerWidgetSize ); cornerRect.moveLeft( rect.left() ); break; case SE_TabWidgetRightCorner: cornerRect = QRect( QPoint(0,0), tabOption->rightCornerWidgetSize ); cornerRect.moveRight( rect.right() ); break; default: break; } // expend height to tabBarSize, if needed, to make sure base is properly rendered cornerRect.setHeight( qMax( cornerRect.height(), tabBarSize.height() + 1 ) ); switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: cornerRect.moveTop( rect.top() ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: cornerRect.moveBottom( rect.bottom() ); break; default: break; } // return cornerRect; cornerRect = visualRect( option, cornerRect ); return cornerRect; } //____________________________________________________________________ QRect Style::toolBoxTabContentsRect( const QStyleOption* option, const QWidget* widget ) const { // cast option and check const auto toolBoxOption( qstyleoption_cast( option ) ); if( !toolBoxOption ) return option->rect; // copy rect const auto& rect( option->rect ); int contentsWidth(0); if( !toolBoxOption->icon.isNull() ) { const int iconSize( pixelMetric( QStyle::PM_SmallIconSize, option, widget ) ); contentsWidth += iconSize; if( !toolBoxOption->text.isEmpty() ) contentsWidth += Metrics::ToolBox_TabItemSpacing; } if( !toolBoxOption->text.isEmpty() ) { const int textWidth = toolBoxOption->fontMetrics.size( _mnemonics->textFlags(), toolBoxOption->text ).width(); contentsWidth += textWidth; } contentsWidth += 2*Metrics::ToolBox_TabMarginWidth; contentsWidth = qMin( contentsWidth, rect.width() ); contentsWidth = qMax( contentsWidth, int(Metrics::ToolBox_TabMinWidth) ); return centerRect( rect, contentsWidth, rect.height() ); } //____________________________________________________________________ QRect Style::genericLayoutItemRect( const QStyleOption* option, const QWidget* ) const { return insideMargin( option->rect, -Metrics::Frame_FrameWidth ); } //______________________________________________________________ QRect Style::groupBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { QRect rect = option->rect; switch( subControl ) { case SC_GroupBoxFrame: return rect; case SC_GroupBoxContents: { // cast option and check const auto groupBoxOption = qstyleoption_cast( option ); if( !groupBoxOption ) break; // take out frame width rect = insideMargin( rect, Metrics::Frame_FrameWidth ); // get state const bool checkable( groupBoxOption->subControls & QStyle::SC_GroupBoxCheckBox ); const bool emptyText( groupBoxOption->text.isEmpty() ); // calculate title height int titleHeight( 0 ); if( !emptyText ) titleHeight = groupBoxOption->fontMetrics.height(); if( checkable ) titleHeight = qMax( titleHeight, int(Metrics::CheckBox_Size) ); // add margin if( titleHeight > 0 ) titleHeight += 2*Metrics::GroupBox_TitleMarginWidth; rect.adjust( 0, titleHeight, 0, 0 ); return rect; } case SC_GroupBoxCheckBox: case SC_GroupBoxLabel: { // cast option and check const auto groupBoxOption = qstyleoption_cast( option ); if( !groupBoxOption ) break; // take out frame width rect = insideMargin( rect, Metrics::Frame_FrameWidth ); const bool emptyText( groupBoxOption->text.isEmpty() ); const bool checkable( groupBoxOption->subControls & QStyle::SC_GroupBoxCheckBox ); // calculate title height int titleHeight( 0 ); int titleWidth( 0 ); if( !emptyText ) { const QFontMetrics fontMetrics = option->fontMetrics; titleHeight = qMax( titleHeight, fontMetrics.height() ); titleWidth += fontMetrics.size( _mnemonics->textFlags(), groupBoxOption->text ).width(); } if( checkable ) { titleHeight = qMax( titleHeight, int(Metrics::CheckBox_Size) ); titleWidth += Metrics::CheckBox_Size; if( !emptyText ) titleWidth += Metrics::CheckBox_ItemSpacing; } // adjust height auto titleRect( rect ); titleRect.setHeight( titleHeight ); titleRect.translate( 0, Metrics::GroupBox_TitleMarginWidth ); // center titleRect = centerRect( titleRect, titleWidth, titleHeight ); if( subControl == SC_GroupBoxCheckBox ) { // vertical centering titleRect = centerRect( titleRect, titleWidth, Metrics::CheckBox_Size ); // horizontal positioning const QRect subRect( titleRect.topLeft(), QSize( Metrics::CheckBox_Size, titleRect.height() ) ); return visualRect( option->direction, titleRect, subRect ); } else { // vertical centering QFontMetrics fontMetrics = option->fontMetrics; titleRect = centerRect( titleRect, titleWidth, fontMetrics.height() ); // horizontal positioning auto subRect( titleRect ); if( checkable ) subRect.adjust( Metrics::CheckBox_Size + Metrics::CheckBox_ItemSpacing, 0, 0, 0 ); return visualRect( option->direction, titleRect, subRect ); } } default: break; } return ParentStyleClass::subControlRect( CC_GroupBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::toolButtonSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const auto toolButtonOption = qstyleoption_cast( option ); if( !toolButtonOption ) return ParentStyleClass::subControlRect( CC_ToolButton, option, subControl, widget ); const bool hasPopupMenu( toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup ); const bool hasInlineIndicator( toolButtonOption->features&QStyleOptionToolButton::HasMenu && toolButtonOption->features&QStyleOptionToolButton::PopupDelay && !hasPopupMenu ); // store rect const auto& rect( option->rect ); const int menuButtonWidth( Metrics::MenuButton_IndicatorWidth ); switch( subControl ) { case SC_ToolButtonMenu: { // check fratures if( !(hasPopupMenu || hasInlineIndicator ) ) return QRect(); // check features auto menuRect( rect ); menuRect.setLeft( rect.right() - menuButtonWidth + 1 ); if( hasInlineIndicator ) { menuRect.setTop( menuRect.bottom() - menuButtonWidth + 1 ); } return visualRect( option, menuRect ); } case SC_ToolButton: { if( hasPopupMenu ) { auto contentsRect( rect ); contentsRect.setRight( rect.right() - menuButtonWidth ); return visualRect( option, contentsRect ); } else return rect; } default: return QRect(); } } //___________________________________________________________________________________________________________________ QRect Style::comboBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const auto comboBoxOption( qstyleoption_cast( option ) ); if( !comboBoxOption ) return ParentStyleClass::subControlRect( CC_ComboBox, option, subControl, widget ); const bool editable( comboBoxOption->editable ); const bool flat( editable && !comboBoxOption->frame ); // copy rect auto rect( option->rect ); switch( subControl ) { case SC_ComboBoxFrame: return flat ? rect : QRect(); case SC_ComboBoxListBoxPopup: return rect; case SC_ComboBoxArrow: { // take out frame width if( !flat ) rect = insideMargin( rect, Metrics::Frame_FrameWidth ); QRect arrowRect( rect.right() - Metrics::MenuButton_IndicatorWidth + 1, rect.top(), Metrics::MenuButton_IndicatorWidth, rect.height() ); arrowRect = centerRect( arrowRect, Metrics::MenuButton_IndicatorWidth, Metrics::MenuButton_IndicatorWidth ); return visualRect( option, arrowRect ); } case SC_ComboBoxEditField: { QRect labelRect; const int frameWidth( pixelMetric( PM_ComboBoxFrameWidth, option, widget ) ); labelRect = QRect( rect.left(), rect.top(), rect.width() - Metrics::MenuButton_IndicatorWidth, rect.height() ); // remove margins if( !flat && rect.height() >= option->fontMetrics.height() + 2*frameWidth ) { labelRect.adjust( frameWidth, frameWidth, 0, -frameWidth ); } return visualRect( option, labelRect ); } default: break; } return ParentStyleClass::subControlRect( CC_ComboBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::spinBoxSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const auto spinBoxOption( qstyleoption_cast( option ) ); if( !spinBoxOption ) return ParentStyleClass::subControlRect( CC_SpinBox, option, subControl, widget ); const bool flat( !spinBoxOption->frame ); // copy rect auto rect( option->rect ); switch( subControl ) { case SC_SpinBoxFrame: return flat ? QRect():rect; case SC_SpinBoxUp: case SC_SpinBoxDown: { // take out frame width if( !flat && rect.height() >= 2*Metrics::Frame_FrameWidth + Metrics::SpinBox_ArrowButtonWidth ) rect = insideMargin( rect, Metrics::Frame_FrameWidth ); QRect arrowRect; arrowRect = QRect( rect.right() - Metrics::SpinBox_ArrowButtonWidth + 1, rect.top(), Metrics::SpinBox_ArrowButtonWidth, rect.height() ); const int arrowHeight( qMin( rect.height(), int(Metrics::SpinBox_ArrowButtonWidth) ) ); arrowRect = centerRect( arrowRect, Metrics::SpinBox_ArrowButtonWidth, arrowHeight ); arrowRect.setHeight( arrowHeight/2 ); if( subControl == SC_SpinBoxDown ) arrowRect.translate( 0, arrowHeight/2 ); return visualRect( option, arrowRect ); } case SC_SpinBoxEditField: { QRect labelRect; labelRect = QRect( rect.left(), rect.top(), rect.width() - Metrics::SpinBox_ArrowButtonWidth, rect.height() ); // remove right side line editor margins const int frameWidth( pixelMetric( PM_SpinBoxFrameWidth, option, widget ) ); if( !flat && labelRect.height() >= option->fontMetrics.height() + 2*frameWidth ) { labelRect.adjust( frameWidth, frameWidth, 0, -frameWidth ); } return visualRect( option, labelRect ); } default: break; } return ParentStyleClass::subControlRect( CC_SpinBox, option, subControl, widget ); } //___________________________________________________________________________________________________________________ QRect Style::scrollBarInternalSubControlRect( const QStyleOptionComplex* option, SubControl subControl ) const { const auto& rect = option->rect; const State& state( option->state ); const bool horizontal( state & State_Horizontal ); switch( subControl ) { case SC_ScrollBarSubLine: { int majorSize( scrollBarButtonHeight( _subLineButtons ) ); if( horizontal ) return visualRect( option, QRect( rect.left(), rect.top(), majorSize, rect.height() ) ); else return visualRect( option, QRect( rect.left(), rect.top(), rect.width(), majorSize ) ); } case SC_ScrollBarAddLine: { int majorSize( scrollBarButtonHeight( _addLineButtons ) ); if( horizontal ) return visualRect( option, QRect( rect.right() - majorSize + 1, rect.top(), majorSize, rect.height() ) ); else return visualRect( option, QRect( rect.left(), rect.bottom() - majorSize + 1, rect.width(), majorSize ) ); } default: return QRect(); } } //___________________________________________________________________________________________________________________ QRect Style::scrollBarSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return ParentStyleClass::subControlRect( CC_ScrollBar, option, subControl, widget ); // get relevant state const State& state( option->state ); const bool horizontal( state & State_Horizontal ); switch( subControl ) { case SC_ScrollBarSubLine: case SC_ScrollBarAddLine: return scrollBarInternalSubControlRect( option, subControl ); case SC_ScrollBarGroove: { auto topRect = visualRect( option, scrollBarInternalSubControlRect( option, SC_ScrollBarSubLine ) ); auto bottomRect = visualRect( option, scrollBarInternalSubControlRect( option, SC_ScrollBarAddLine ) ); QPoint topLeftCorner; QPoint botRightCorner; if( horizontal ) { topLeftCorner = QPoint( topRect.right() + 1, topRect.top() ); botRightCorner = QPoint( bottomRect.left() - 1, topRect.bottom() ); } else { topLeftCorner = QPoint( topRect.left(), topRect.bottom() + 1 ); botRightCorner = QPoint( topRect.right(), bottomRect.top() - 1 ); } // define rect return visualRect( option, QRect( topLeftCorner, botRightCorner ) ); } case SC_ScrollBarSlider: { // handle RTL here to unreflect things if need be auto groove = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); if( sliderOption->minimum == sliderOption->maximum ) return groove; // Figure out how much room there is int space( horizontal ? groove.width() : groove.height() ); // Calculate the portion of this space that the slider should occupy int sliderSize = space * qreal( sliderOption->pageStep ) / ( sliderOption->maximum - sliderOption->minimum + sliderOption->pageStep ); sliderSize = qMax( sliderSize, static_cast(Metrics::ScrollBar_MinSliderHeight ) ); sliderSize = qMin( sliderSize, space ); space -= sliderSize; if( space <= 0 ) return groove; int pos = qRound( qreal( sliderOption->sliderPosition - sliderOption->minimum )/ ( sliderOption->maximum - sliderOption->minimum )*space ); if( sliderOption->upsideDown ) pos = space - pos; if( horizontal ) return visualRect( option, QRect( groove.left() + pos, groove.top(), sliderSize, groove.height() ) ); else return visualRect( option, QRect( groove.left(), groove.top() + pos, groove.width(), sliderSize ) ); } case SC_ScrollBarSubPage: { // handle RTL here to unreflect things if need be auto slider = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarSlider, widget ) ); auto groove = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); if( horizontal ) return visualRect( option, QRect( groove.left(), groove.top(), slider.left() - groove.left(), groove.height() ) ); else return visualRect( option, QRect( groove.left(), groove.top(), groove.width(), slider.top() - groove.top() ) ); } case SC_ScrollBarAddPage: { // handle RTL here to unreflect things if need be auto slider = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarSlider, widget ) ); auto groove = visualRect( option, subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); if( horizontal ) return visualRect( option, QRect( slider.right() + 1, groove.top(), groove.right() - slider.right(), groove.height() ) ); else return visualRect( option, QRect( groove.left(), slider.bottom() + 1, groove.width(), groove.bottom() - slider.bottom() ) ); } default: return ParentStyleClass::subControlRect( CC_ScrollBar, option, subControl, widget );; } } //___________________________________________________________________________________________________________________ QRect Style::dialSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return ParentStyleClass::subControlRect( CC_Dial, option, subControl, widget ); // adjust rect to be square, and centered auto rect( option->rect ); const int dimension( qMin( rect.width(), rect.height() ) ); rect = centerRect( rect, dimension, dimension ); switch( subControl ) { case QStyle::SC_DialGroove: return insideMargin( rect, (Metrics::Slider_ControlThickness - Metrics::Slider_GrooveThickness)/2 ); case QStyle::SC_DialHandle: { // calculate angle at which handle needs to be drawn const qreal angle( dialAngle( sliderOption, sliderOption->sliderPosition ) ); // groove rect const QRectF grooveRect( insideMargin( rect, Metrics::Slider_ControlThickness/2 ) ); qreal radius( grooveRect.width()/2 ); // slider center QPointF center( grooveRect.center() + QPointF( radius*std::cos( angle ), -radius*std::sin( angle ) ) ); // slider rect QRect handleRect( 0, 0, Metrics::Slider_ControlThickness, Metrics::Slider_ControlThickness ); handleRect.moveCenter( center.toPoint() ); return handleRect; } default: return ParentStyleClass::subControlRect( CC_Dial, option, subControl, widget );; } } //___________________________________________________________________________________________________________________ QRect Style::sliderSubControlRect( const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const { // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return ParentStyleClass::subControlRect( CC_Slider, option, subControl, widget ); switch( subControl ) { case SC_SliderGroove: { // direction const bool horizontal( sliderOption->orientation == Qt::Horizontal ); // get base class rect auto grooveRect( ParentStyleClass::subControlRect( CC_Slider, option, subControl, widget ) ); grooveRect = insideMargin( grooveRect, pixelMetric( PM_DefaultFrameWidth, option, widget ) ); // centering if( horizontal ) grooveRect = centerRect( grooveRect, grooveRect.width(), Metrics::Slider_GrooveThickness ); else grooveRect = centerRect( grooveRect, Metrics::Slider_GrooveThickness, grooveRect.height() ); return grooveRect; } default: return ParentStyleClass::subControlRect( CC_Slider, option, subControl, widget ); } } //______________________________________________________________ QSize Style::checkBoxSizeFromContents( const QStyleOption*, const QSize& contentsSize, const QWidget* ) const { // get contents size QSize size( contentsSize ); // add focus height size = expandSize( size, 0, Metrics::CheckBox_FocusMarginWidth ); // make sure there is enough height for indicator size.setHeight( qMax( size.height(), int(Metrics::CheckBox_Size) ) ); // Add space for the indicator and the icon size.rwidth() += Metrics::CheckBox_Size + Metrics::CheckBox_ItemSpacing; // also add extra space, to leave room to the right of the label size.rwidth() += Metrics::CheckBox_ItemSpacing; return size; } //______________________________________________________________ QSize Style::lineEditSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const auto frameOption( qstyleoption_cast( option ) ); if( !frameOption ) return contentsSize; const bool flat( frameOption->lineWidth == 0 ); const int frameWidth( pixelMetric( PM_DefaultFrameWidth, option, widget ) ); return flat ? contentsSize : expandSize( contentsSize, frameWidth ); } //______________________________________________________________ QSize Style::comboBoxSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const auto comboBoxOption( qstyleoption_cast( option ) ); if( !comboBoxOption ) return contentsSize; // copy size QSize size( contentsSize ); // add relevant margin const bool flat( !comboBoxOption->frame ); const int frameWidth( pixelMetric( PM_ComboBoxFrameWidth, option, widget ) ); if( !flat ) size = expandSize( size, frameWidth ); // make sure there is enough height for the button size.setHeight( qMax( size.height(), int(Metrics::MenuButton_IndicatorWidth) ) ); // add button width and spacing size.rwidth() += Metrics::MenuButton_IndicatorWidth+2; return size; } //______________________________________________________________ QSize Style::spinBoxSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const auto spinBoxOption( qstyleoption_cast( option ) ); if( !spinBoxOption ) return contentsSize; const bool flat( !spinBoxOption->frame ); // copy size QSize size( contentsSize ); // add editor margins const int frameWidth( pixelMetric( PM_SpinBoxFrameWidth, option, widget ) ); if( !flat ) size = expandSize( size, frameWidth ); // make sure there is enough height for the button size.setHeight( qMax( size.height(), int(Metrics::SpinBox_ArrowButtonWidth) ) ); // add button width and spacing size.rwidth() += Metrics::SpinBox_ArrowButtonWidth; return size; } //______________________________________________________________ QSize Style::sliderSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return contentsSize; // store tick position and orientation const QSlider::TickPosition& tickPosition( sliderOption->tickPosition ); const bool horizontal( sliderOption->orientation == Qt::Horizontal ); const bool disableTicks( !StyleConfigData::sliderDrawTickMarks() ); // do nothing if no ticks are requested if( tickPosition == QSlider::NoTicks ) return contentsSize; /* * Qt adds its own tick length directly inside QSlider. * Take it out and replace by ours, if needed */ const int tickLength( disableTicks ? 0 : ( Metrics::Slider_TickLength + Metrics::Slider_TickMarginWidth + (Metrics::Slider_GrooveThickness - Metrics::Slider_ControlThickness)/2 ) ); const int builtInTickLength( 5 ); QSize size( contentsSize ); if( horizontal ) { if(tickPosition & QSlider::TicksAbove) size.rheight() += tickLength - builtInTickLength; if(tickPosition & QSlider::TicksBelow) size.rheight() += tickLength - builtInTickLength; } else { if(tickPosition & QSlider::TicksAbove) size.rwidth() += tickLength - builtInTickLength; if(tickPosition & QSlider::TicksBelow) size.rwidth() += tickLength - builtInTickLength; } return size; } //______________________________________________________________ QSize Style::pushButtonSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const auto buttonOption( qstyleoption_cast( option ) ); if( !buttonOption ) return contentsSize; // output QSize size; // check text and icon const bool hasText( !buttonOption->text.isEmpty() ); const bool flat( buttonOption->features & QStyleOptionButton::Flat ); bool hasIcon( !buttonOption->icon.isNull() ); if( !( hasText||hasIcon ) ) { /* no text nor icon is passed. assume custom button and use contentsSize as a starting point */ size = contentsSize; } else { /* rather than trying to guess what Qt puts into its contents size calculation, we recompute the button size entirely, based on button option this ensures consistency with the rendering stage */ // update has icon to honour showIconsOnPushButtons, when possible hasIcon &= (showIconsOnPushButtons() || flat || !hasText ); // text if( hasText ) size = buttonOption->fontMetrics.size( Qt::TextShowMnemonic, buttonOption->text ); // icon if( hasIcon ) { QSize iconSize = buttonOption->iconSize; if( !iconSize.isValid() ) iconSize = QSize( pixelMetric( PM_SmallIconSize, option, widget ), pixelMetric( PM_SmallIconSize, option, widget ) ); size.setHeight( qMax( size.height(), iconSize.height() ) ); size.rwidth() += iconSize.width(); if( hasText ) size.rwidth() += Metrics::Button_ItemSpacing; } } // menu const bool hasMenu( buttonOption->features & QStyleOptionButton::HasMenu ); if( hasMenu ) { size.rwidth() += Metrics::MenuButton_IndicatorWidth; if( hasText||hasIcon ) size.rwidth() += Metrics::Button_ItemSpacing; } // expand with buttons margin size = expandSize( size, Metrics::Button_MarginWidth ); // make sure buttons have a minimum width if( hasText ) { size.setWidth( qMax( size.width(), int( Metrics::Button_MinWidth ) ) ); } // finally add frame margins return expandSize( size, Metrics::Frame_FrameWidth ); } //______________________________________________________________ QSize Style::toolButtonSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { // cast option and check const auto toolButtonOption = qstyleoption_cast( option ); if( !toolButtonOption ) return contentsSize; // copy size QSize size = contentsSize; // get relevant state flags const State& state( option->state ); const bool autoRaise( state & State_AutoRaise ); const bool hasPopupMenu( toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup ); const bool hasInlineIndicator( toolButtonOption->features&QStyleOptionToolButton::HasMenu && toolButtonOption->features&QStyleOptionToolButton::PopupDelay && !hasPopupMenu ); const int marginWidth( autoRaise ? Metrics::ToolButton_MarginWidth : Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth ); if( hasInlineIndicator ) size.rwidth() += Metrics::ToolButton_InlineIndicatorWidth; size = expandSize( size, marginWidth ); return size; } //______________________________________________________________ QSize Style::menuBarItemSizeFromContents( const QStyleOption*, const QSize& contentsSize, const QWidget* ) const { return expandSize( contentsSize, Metrics::MenuBarItem_MarginWidth, Metrics::MenuBarItem_MarginHeight ); } //______________________________________________________________ QSize Style::menuItemSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const auto menuItemOption = qstyleoption_cast( option ); if( !menuItemOption ) return contentsSize; /* * First calculate the intrinsic size of the item. * this must be kept consistent with what's in drawMenuItemControl */ QSize size( contentsSize ); switch( menuItemOption->menuItemType ) { case QStyleOptionMenuItem::Normal: case QStyleOptionMenuItem::DefaultItem: case QStyleOptionMenuItem::SubMenu: { int iconWidth = 0; if( showIconsInMenuItems() ) iconWidth = isQtQuickControl( option, widget ) ? qMax( pixelMetric(PM_SmallIconSize, option, widget ), menuItemOption->maxIconWidth ) : menuItemOption->maxIconWidth; int leftColumnWidth = 0; // add icon width if( iconWidth > 0 ) { leftColumnWidth += iconWidth + Metrics::MenuItem_ItemSpacing; } // add checkbox indicator width if( menuItemOption->menuHasCheckableItems ) { leftColumnWidth += Metrics::CheckBox_Size + Metrics::MenuItem_ItemSpacing; } // add spacing for accelerator /* * Note: * The width of the accelerator itself is not included here since * Qt will add that on separately after obtaining the * sizeFromContents() for each menu item in the menu to be shown * ( see QMenuPrivate::calcActionRects() ) */ const bool hasAccelerator( menuItemOption->text.indexOf( QLatin1Char( '\t' ) ) >= 0 ); if( hasAccelerator ) size.rwidth() += Metrics::MenuItem_AcceleratorSpace; // right column const int rightColumnWidth = Metrics::MenuButton_IndicatorWidth + Metrics::MenuItem_ItemSpacing; size.rwidth() += leftColumnWidth + rightColumnWidth; // make sure height is large enough for icon and arrow size.setHeight( qMax( size.height(), int(Metrics::MenuButton_IndicatorWidth) ) ); size.setHeight( qMax( size.height(), int(Metrics::CheckBox_Size) ) ); size.setHeight( qMax( size.height(), iconWidth ) ); return expandSize( size, Metrics::MenuItem_MarginWidth + MenuItem_HighlightHorizontalMargin * 2, Metrics::MenuItem_MarginHeight + MenuItem_HighlightVerticalMargin * 2 ); } case QStyleOptionMenuItem::Separator: { if( menuItemOption->text.isEmpty() && menuItemOption->icon.isNull() ) { return expandSize( QSize(0,1), Metrics::MenuItem_MarginWidth, MenuItem_SeparatorMargin ); } else { // build toolbutton option const QStyleOptionToolButton toolButtonOption( separatorMenuItemOption( menuItemOption, widget ) ); // make sure height is large enough for icon and text const int iconWidth( menuItemOption->maxIconWidth ); const int textHeight( menuItemOption->fontMetrics.height() ); if( !menuItemOption->icon.isNull() ) size.setHeight( qMax( size.height(), iconWidth ) ); if( !menuItemOption->text.isEmpty() ) { size.setHeight( qMax( size.height(), textHeight ) ); size.setWidth( qMax( size.width(), menuItemOption->fontMetrics.width( menuItemOption->text ) ) ); } return sizeFromContents( CT_ToolButton, &toolButtonOption, size, widget ); } } // for all other cases, return input default: return contentsSize; } } //______________________________________________________________ QSize Style::progressBarSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { // cast option const auto progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return contentsSize; #if BREEZE_USE_KDE4 const auto progressBarOption2( qstyleoption_cast( option ) ); const bool horizontal( !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal ); #else const bool horizontal( BreezePrivate::isProgressBarHorizontal( progressBarOption ) ); #endif // make local copy QSize size( contentsSize ); if( horizontal ) { // check text visibility const bool textVisible( progressBarOption->textVisible ); size.setWidth( qMax( size.width(), int(Metrics::ProgressBar_Thickness) ) ); size.setHeight( qMax( size.height(), int(Metrics::ProgressBar_Thickness) ) ); if( textVisible ) size.setHeight( qMax( size.height(), option->fontMetrics.height() ) ); } else { size.setHeight( qMax( size.height(), int(Metrics::ProgressBar_Thickness) ) ); size.setWidth( qMax( size.width(), int(Metrics::ProgressBar_Thickness) ) ); } return size; } //______________________________________________________________ QSize Style::tabWidgetSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // cast option and check const auto tabOption = qstyleoption_cast( option ); if( !tabOption ) return expandSize( contentsSize, Metrics::TabWidget_MarginWidth ); // try find direct children of type QTabBar and QStackedWidget // this is needed in order to add TabWidget margins only if they are necessary around tabWidget content, not the tabbar if( !widget ) return expandSize( contentsSize, Metrics::TabWidget_MarginWidth ); QTabBar* tabBar = nullptr; QStackedWidget* stack = nullptr; auto children( widget->children() ); foreach( auto child, children ) { if( !tabBar ) tabBar = qobject_cast( child ); if( !stack ) stack = qobject_cast( child ); if( tabBar && stack ) break; } if( !( tabBar && stack ) ) return expandSize( contentsSize, Metrics::TabWidget_MarginWidth ); // tab orientation const bool verticalTabs( tabOption && isVerticalTab( tabOption->shape ) ); if( verticalTabs ) { const int tabBarHeight = tabBar->minimumSizeHint().height(); const int stackHeight = stack->minimumSizeHint().height(); if( contentsSize.height() == tabBarHeight && tabBarHeight + 2*(Metrics::Frame_FrameWidth - 1) >= stackHeight + 2*Metrics::TabWidget_MarginWidth ) return QSize( contentsSize.width() + 2*Metrics::TabWidget_MarginWidth, contentsSize.height() + 2*(Metrics::Frame_FrameWidth - 1) ); else return expandSize( contentsSize, Metrics::TabWidget_MarginWidth ); } else { const int tabBarWidth = tabBar->minimumSizeHint().width(); const int stackWidth = stack->minimumSizeHint().width(); if( contentsSize.width() == tabBarWidth && tabBarWidth + 2*(Metrics::Frame_FrameWidth - 1) >= stackWidth + 2*Metrics::TabWidget_MarginWidth) return QSize( contentsSize.width() + 2*(Metrics::Frame_FrameWidth - 1), contentsSize.height() + 2*Metrics::TabWidget_MarginWidth ); else return expandSize( contentsSize, Metrics::TabWidget_MarginWidth ); } } //______________________________________________________________ QSize Style::tabBarTabSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { const auto tabOption( qstyleoption_cast( option ) ); const bool hasText( tabOption && !tabOption->text.isEmpty() ); const bool hasIcon( tabOption && !tabOption->icon.isNull() ); #if BREEZE_USE_KDE4 const auto tabOptionV3( qstyleoption_cast( option ) ); const bool hasLeftButton( tabOptionV3 && !tabOptionV3->leftButtonSize.isEmpty() ); const bool hasRightButton( tabOptionV3 && !tabOptionV3->leftButtonSize.isEmpty() ); #else const bool hasLeftButton( tabOption && !tabOption->leftButtonSize.isEmpty() ); const bool hasRightButton( tabOption && !tabOption->leftButtonSize.isEmpty() ); #endif // calculate width increment for horizontal tabs int widthIncrement = 0; if( hasIcon && !( hasText || hasLeftButton || hasRightButton ) ) widthIncrement -= 4; if( hasText && hasIcon ) widthIncrement += Metrics::TabBar_TabItemSpacing; if( hasLeftButton && ( hasText || hasIcon ) ) widthIncrement += Metrics::TabBar_TabItemSpacing; if( hasRightButton && ( hasText || hasIcon || hasLeftButton ) ) widthIncrement += Metrics::TabBar_TabItemSpacing; // add margins QSize size( contentsSize ); // compare to minimum size const bool verticalTabs( tabOption && isVerticalTab( tabOption ) ); if( verticalTabs ) { size.rheight() += widthIncrement; if( hasIcon && !hasText ) size = size.expandedTo( QSize( Metrics::TabBar_TabMinHeight, 0 ) ); else size = size.expandedTo( QSize( Metrics::TabBar_TabMinHeight, Metrics::TabBar_TabMinWidth ) ); } else { size.rwidth() += widthIncrement; if( hasIcon && !hasText ) size = size.expandedTo( QSize( 0, Metrics::TabBar_TabMinHeight ) ); else size = size.expandedTo( QSize( Metrics::TabBar_TabMinWidth, Metrics::TabBar_TabMinHeight ) ); } return size; } //______________________________________________________________ QSize Style::headerSectionSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* ) const { // cast option and check const auto headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return contentsSize; // get text size const bool horizontal( headerOption->orientation == Qt::Horizontal ); const bool hasText( !headerOption->text.isEmpty() ); const bool hasIcon( !headerOption->icon.isNull() ); const QSize textSize( hasText ? headerOption->fontMetrics.size( 0, headerOption->text ) : QSize() ); const QSize iconSize( hasIcon ? QSize( 22,22 ) : QSize() ); // contents width int contentsWidth( 0 ); if( hasText ) contentsWidth += textSize.width(); if( hasIcon ) { contentsWidth += iconSize.width(); if( hasText ) contentsWidth += Metrics::Header_ItemSpacing; } // contents height int contentsHeight( headerOption->fontMetrics.height() ); if( hasIcon ) contentsHeight = qMax( contentsHeight, iconSize.height() ); if( horizontal && headerOption->sortIndicator != QStyleOptionHeader::None ) { // also add space for sort indicator contentsWidth += Metrics::Header_ArrowSize + Metrics::Header_ItemSpacing; contentsHeight = qMax( contentsHeight, int(Metrics::Header_ArrowSize) ); } // update contents size, add margins and return const QSize size( contentsSize.expandedTo( QSize( contentsWidth, contentsHeight ) ) ); return expandSize( size, Metrics::Header_MarginWidth ); } //______________________________________________________________ QSize Style::itemViewItemSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget* widget ) const { // call base class const QSize size( ParentStyleClass::sizeFromContents( CT_ItemViewItem, option, contentsSize, widget ) ); return expandSize( size, Metrics::ItemView_ItemMarginWidth ); } //______________________________________________________________ bool Style::drawFramePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy palette and rect const auto& palette( option->palette ); const auto& rect( option->rect ); // detect title widgets const bool isTitleWidget( StyleConfigData::titleWidgetDrawFrame() && widget && widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ); // copy state const State& state( option->state ); if( !isTitleWidget && !( state & (State_Sunken | State_Raised ) ) ) return true; #if QT_VERSION >= 0x050000 const bool isInputWidget( ( widget && widget->testAttribute( Qt::WA_Hover ) ) || ( isQtQuickControl( option, widget ) && option->styleObject->property( "elementType" ).toString() == QStringLiteral( "edit") ) ); #else const bool isInputWidget( ( widget && widget->testAttribute( Qt::WA_Hover ) ) ); #endif const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && isInputWidget && ( state & State_MouseOver ) ); const bool hasFocus( enabled && isInputWidget && ( state & State_HasFocus ) ); // focus takes precedence over mouse over _animations->inputWidgetEngine().updateState( widget, AnimationFocus, hasFocus ); _animations->inputWidgetEngine().updateState( widget, AnimationHover, mouseOver && !hasFocus ); // retrieve animation mode and opacity const AnimationMode mode( _animations->inputWidgetEngine().frameAnimationMode( widget ) ); const qreal opacity( _animations->inputWidgetEngine().frameOpacity( widget ) ); // render if( !StyleConfigData::sidePanelDrawFrame() && widget && widget->property( PropertyNames::sidePanelView ).toBool() ) { const auto outline( _helper->sidePanelOutlineColor( palette, hasFocus, opacity, mode ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const Side side( reverseLayout ? SideRight : SideLeft ); _helper->renderSidePanelFrame( painter, rect, outline, side ); } else { if( _frameShadowFactory->isRegistered( widget ) ) { // update frame shadow factory _frameShadowFactory->updateShadowsGeometry( widget, rect ); _frameShadowFactory->updateState( widget, hasFocus, mouseOver, opacity, mode ); } const auto background( isTitleWidget ? palette.color( widget->backgroundRole() ):QColor() ); const auto outline( _helper->frameOutlineColor( palette, mouseOver, hasFocus, opacity, mode ) ); _helper->renderFrame( painter, rect, background, outline ); } return true; } //______________________________________________________________ bool Style::drawFrameLineEditPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy palette and rect const auto& palette( option->palette ); const auto& rect( option->rect ); // make sure there is enough room to render frame if( rect.height() < 2*Metrics::LineEdit_FrameWidth + option->fontMetrics.height()) { const auto background( palette.color( QPalette::Base ) ); painter->setPen( Qt::NoPen ); painter->setBrush( background ); painter->drawRect( rect ); return true; } else { // copy state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); // focus takes precedence over mouse over _animations->inputWidgetEngine().updateState( widget, AnimationFocus, hasFocus ); _animations->inputWidgetEngine().updateState( widget, AnimationHover, mouseOver && !hasFocus ); // retrieve animation mode and opacity const AnimationMode mode( _animations->inputWidgetEngine().frameAnimationMode( widget ) ); const qreal opacity( _animations->inputWidgetEngine().frameOpacity( widget ) ); // render const auto background( palette.color( QPalette::Base ) ); const auto outline( _helper->frameOutlineColor( palette, mouseOver, hasFocus, opacity, mode ) ); _helper->renderFrame( painter, rect, background, outline ); } return true; } //___________________________________________________________________________________ bool Style::drawFrameFocusRectPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // no focus indicator on buttons / scrollbars, since it is rendered elsewhere if ( qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) ) { return true; } // no focus indicator on ComboBox list items if (widget && widget->inherits("QComboBoxListView")) { return true; } #if QT_VERSION >= 0x050000 if ( option->styleObject && option->styleObject->property("elementType") == QLatin1String("button") ) { return true; } #endif const State& state( option->state ); // no focus indicator on selected list items if ((state & State_Selected) && qobject_cast(widget)) { return true; } const auto rect( option->rect.adjusted( 0, 0, 0, 1 ) ); const auto& palette( option->palette ); if( rect.width() < 10 ) return true; const auto outlineColor( state & State_Selected ? palette.color( QPalette::HighlightedText ):palette.color( QPalette::Highlight ) ); painter->setRenderHint( QPainter::Antialiasing, false ); painter->setPen( outlineColor ); painter->drawLine( QPoint( rect.bottomLeft() - QPoint( 0,1 ) ), QPoint( rect.bottomRight() - QPoint( 0,1 ) ) ); return true; } //___________________________________________________________________________________ bool Style::drawFrameMenuPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // only draw frame for (expanded) toolbars and QtQuick controls // do nothing for other cases, for which frame is rendered via drawPanelMenuPrimitive if( qobject_cast( widget ) ) { const auto& palette( option->palette ); const auto background( _helper->frameBackgroundColor( palette ) ); const auto outline( _helper->frameOutlineColor( palette ) ); const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); _helper->renderMenuFrame( painter, option->rect, background, outline, hasAlpha ); } else if( isQtQuickControl( option, widget ) ) { const auto& palette( option->palette ); const auto background( _helper->frameBackgroundColor( palette ) ); const auto outline( _helper->frameOutlineColor( palette ) ); const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); _helper->renderMenuFrame( painter, option->rect, background, outline, hasAlpha ); } return true; } //______________________________________________________________ bool Style::drawFrameGroupBoxPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const auto frameOption( qstyleoption_cast( option ) ); if( !frameOption ) return true; // no frame for flat groupboxes #if BREEZE_USE_KDE4 QStyleOptionFrameV2 frameOption2( *frameOption ); if( frameOption2.features & QStyleOptionFrameV2::Flat ) return true; #else if( frameOption->features & QStyleOptionFrame::Flat ) return true; #endif // normal frame const auto& palette( option->palette ); const auto background( _helper->frameBackgroundColor( palette ) ); const auto outline( _helper->frameOutlineColor( palette ) ); /* * need to reset painter's clip region in order to paint behind textbox label * (was taken out in QCommonStyle) */ painter->setClipRegion( option->rect ); _helper->renderFrame( painter, option->rect, background, outline ); return true; } //___________________________________________________________________________________ bool Style::drawFrameTabWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check #if BREEZE_USE_KDE4 const auto tabOption( qstyleoption_cast( option ) ); #else const auto tabOption( qstyleoption_cast( option ) ); #endif if( !tabOption ) return true; // do nothing if tabbar is hidden const bool isQtQuickControl( this->isQtQuickControl( option, widget ) ); if( tabOption->tabBarSize.isEmpty() && !isQtQuickControl ) return true; // adjust rect to handle overlaps auto rect( option->rect ); const auto tabBarRect( tabOption->tabBarRect ); const QSize tabBarSize( tabOption->tabBarSize ); Corners corners = AllCorners; // adjust corners to deal with oversized tabbars switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: if( isQtQuickControl ) rect.adjust( -1, -1, 1, 0 ); if( tabBarSize.width() >= rect.width() - 2*Metrics::Frame_FrameRadius ) corners &= ~CornersTop; if( tabBarRect.left() < rect.left() + Metrics::Frame_FrameRadius ) corners &= ~CornerTopLeft; if( tabBarRect.right() > rect.right() - Metrics::Frame_FrameRadius ) corners &= ~CornerTopRight; break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: if( isQtQuickControl ) rect.adjust( -1, 0, 1, 1 ); if( tabBarSize.width() >= rect.width()-2*Metrics::Frame_FrameRadius ) corners &= ~CornersBottom; if( tabBarRect.left() < rect.left() + Metrics::Frame_FrameRadius ) corners &= ~CornerBottomLeft; if( tabBarRect.right() > rect.right() - Metrics::Frame_FrameRadius ) corners &= ~CornerBottomRight; break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: if( isQtQuickControl ) rect.adjust( -1, 0, 0, 0 ); if( tabBarSize.height() >= rect.height()-2*Metrics::Frame_FrameRadius ) corners &= ~CornersLeft; if( tabBarRect.top() < rect.top() + Metrics::Frame_FrameRadius ) corners &= ~CornerTopLeft; if( tabBarRect.bottom() > rect.bottom() - Metrics::Frame_FrameRadius ) corners &= ~CornerBottomLeft; break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: if( isQtQuickControl ) rect.adjust( 0, 0, 1, 0 ); if( tabBarSize.height() >= rect.height()-2*Metrics::Frame_FrameRadius ) corners &= ~CornersRight; if( tabBarRect.top() < rect.top() + Metrics::Frame_FrameRadius ) corners &= ~CornerTopRight; if( tabBarRect.bottom() > rect.bottom() - Metrics::Frame_FrameRadius ) corners &= ~CornerBottomRight; break; default: break; } // define colors const auto& palette( option->palette ); const auto background( _helper->frameBackgroundColor( palette ) ); const auto outline( _helper->frameOutlineColor( palette ) ); _helper->renderTabWidgetFrame( painter, rect, background, outline, corners ); return true; } //___________________________________________________________________________________ bool Style::drawFrameTabBarBasePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // tabbar frame used either for 'separate' tabbar, or in 'document mode' // cast option and check const auto tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; // get rect, orientation, palette const auto rect( option->rect ); const auto outline( _helper->frameOutlineColor( option->palette ) ); // setup painter painter->setBrush( Qt::NoBrush ); painter->setRenderHint( QPainter::Antialiasing, false ); painter->setPen( QPen( outline, 1 ) ); // render switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: painter->drawLine( rect.bottomLeft() - QPoint( 1, 0 ), rect.bottomRight() + QPoint( 1, 0 ) ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: painter->drawLine( rect.topLeft() - QPoint( 1, 0 ), rect.topRight() + QPoint( 1, 0 ) ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: painter->drawLine( rect.topRight() - QPoint( 0, 1 ), rect.bottomRight() + QPoint( 1, 0 ) ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: painter->drawLine( rect.topLeft() - QPoint( 0, 1 ), rect.bottomLeft() + QPoint( 1, 0 ) ); break; default: break; } return true; } //___________________________________________________________________________________ bool Style::drawFrameWindowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); const State state( option->state ); const bool selected( state & State_Selected ); // render frame outline const auto outline( _helper->frameOutlineColor( palette, false, selected ) ); _helper->renderMenuFrame( painter, rect, QColor(), outline ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorArrowPrimitive( ArrowOrientation orientation, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // store rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); bool mouseOver( enabled && ( state & State_MouseOver ) ); bool hasFocus( enabled && ( state & State_HasFocus ) ); // detect special buttons const bool inTabBar( widget && qobject_cast( widget->parentWidget() ) ); const bool inToolButton( qstyleoption_cast( option ) ); // color QColor color; if( inTabBar ) { // for tabbar arrows one uses animations to get the arrow color /* * get animation state * there is no need to update the engine since this was already done when rendering the frame */ const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); color = _helper->arrowColor( palette, mouseOver, hasFocus, opacity, mode ); } else if( mouseOver && !inToolButton ) { color = _helper->hoverColor( palette ); } else if( inToolButton ) { const bool flat( state & State_AutoRaise ); // cast option const QStyleOptionToolButton* toolButtonOption( static_cast( option ) ); const bool hasPopupMenu( toolButtonOption->subControls & SC_ToolButtonMenu ); const bool sunken( state & (State_On | State_Sunken) ); if( flat && hasPopupMenu ) { if( sunken && !mouseOver ) color = palette.color( QPalette::HighlightedText ); else { // for menu arrows in flat toolbutton one uses animations to get the arrow color // handle arrow over animation const bool arrowHover( mouseOver && ( toolButtonOption->activeSubControls & SC_ToolButtonMenu ) ); _animations->toolButtonEngine().updateState( widget, AnimationHover, arrowHover ); const bool animated( _animations->toolButtonEngine().isAnimated( widget, AnimationHover ) ); const qreal opacity( _animations->toolButtonEngine().opacity( widget, AnimationHover ) ); color = _helper->arrowColor( palette, arrowHover, false, opacity, animated ? AnimationHover:AnimationNone ); } } else if( flat ) { if( sunken && hasFocus && !mouseOver ) color = palette.color( QPalette::HighlightedText ); else color = _helper->arrowColor( palette, QPalette::WindowText ); } else if( hasFocus && !mouseOver ) { color = palette.color( QPalette::HighlightedText ); } else { color = _helper->arrowColor( palette, QPalette::ButtonText ); } } else color = _helper->arrowColor( palette, QPalette::WindowText ); // render _helper->renderArrow( painter, rect, color, orientation ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorHeaderArrowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const auto headerOption( qstyleoption_cast( option ) ); const State& state( option->state ); // arrow orientation ArrowOrientation orientation( ArrowNone ); if( state & State_UpArrow || ( headerOption && headerOption->sortIndicator==QStyleOptionHeader::SortUp ) ) orientation = ArrowUp; else if( state & State_DownArrow || ( headerOption && headerOption->sortIndicator==QStyleOptionHeader::SortDown ) ) orientation = ArrowDown; if( orientation == ArrowNone ) return true; // invert arrows if requested by (hidden) options if( StyleConfigData::viewInvertSortIndicator() ) orientation = (orientation == ArrowUp) ? ArrowDown:ArrowUp; // state, rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // define color and polygon for drawing arrow const auto color = _helper->arrowColor( palette, QPalette::ButtonText ); // render _helper->renderArrow( painter, rect, color, orientation ); return true; } //______________________________________________________________ bool Style::drawPanelButtonCommandPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto buttonOption( qstyleoption_cast< const QStyleOptionButton* >( option ) ); if( !buttonOption ) return true; // rect and palette const auto& rect( option->rect ); // button state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( ( enabled && ( state & State_HasFocus ) ) && !( widget && widget->focusProxy())); const bool sunken( state & ( State_On|State_Sunken ) ); const bool flat( buttonOption->features & QStyleOptionButton::Flat ); // update animation state // mouse over takes precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); if( flat ) { // define colors and render const auto& palette( option->palette ); const auto color( _helper->toolButtonColor( palette, mouseOver, hasFocus, sunken, opacity, mode ) ); _helper->renderToolButtonFrame( painter, rect, color, sunken ); } else { // update button color from palette in case button is default QPalette palette( option->palette ); if( enabled && buttonOption->features & QStyleOptionButton::DefaultButton ) { const auto button( palette.color( QPalette::Button ) ); const auto base( palette.color( QPalette::Base ) ); palette.setColor( QPalette::Button, KColorUtils::mix( button, base, 0.7 ) ); } const auto shadow( _helper->shadowColor( palette ) ); const auto outline( _helper->buttonOutlineColor( palette, mouseOver, hasFocus, opacity, mode ) ); const auto background( _helper->buttonBackgroundColor( palette, mouseOver, hasFocus, sunken, opacity, mode ) ); // render _helper->renderButtonFrame( painter, rect, background, outline, shadow, hasFocus, sunken ); } return true; } //______________________________________________________________ bool Style::drawPanelButtonToolPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy palette and rect const auto& palette( option->palette ); auto rect( option->rect ); // store relevant flags const State& state( option->state ); const bool autoRaise( state & State_AutoRaise ); const bool enabled( state & State_Enabled ); const bool sunken( state & (State_On | State_Sunken) ); const bool mouseOver( enabled && (option->state & State_MouseOver) ); const bool hasFocus( enabled && (option->state & (State_HasFocus | State_Sunken)) ); /* * get animation state * no need to update, this was already done in drawToolButtonComplexControl */ const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); if( !autoRaise ) { // need to check widget for popup mode, because option is not set properly const auto toolButton( qobject_cast( widget ) ); const bool hasPopupMenu( toolButton && toolButton->popupMode() == QToolButton::MenuButtonPopup ); // render as push button const auto shadow( _helper->shadowColor( palette ) ); const auto outline( _helper->buttonOutlineColor( palette, mouseOver, hasFocus, opacity, mode ) ); const auto background( _helper->buttonBackgroundColor( palette, mouseOver, hasFocus, sunken, opacity, mode ) ); // adjust frame in case of menu if( hasPopupMenu ) { painter->setClipRect( rect ); rect.adjust( 0, 0, Metrics::Frame_FrameRadius + 2, 0 ); rect = visualRect( option, rect ); } // render _helper->renderButtonFrame( painter, rect, background, outline, shadow, hasFocus, sunken ); } else { const auto color( _helper->toolButtonColor( palette, mouseOver, hasFocus, sunken, opacity, mode ) ); _helper->renderToolButtonFrame( painter, rect, color, sunken ); } return true; } //______________________________________________________________ bool Style::drawTabBarPanelButtonToolPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy palette and rect auto rect( option->rect ); // static_cast is safe here since check was already performed in calling function const QTabBar* tabBar( static_cast( widget->parentWidget() ) ); // overlap. // subtract 1, because of the empty pixel left the tabwidget frame const int overlap( Metrics::TabBar_BaseOverlap - 1 ); // adjust rect based on tabbar shape switch( tabBar->shape() ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: rect.adjust( 0, 0, 0, -overlap ); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: rect.adjust( 0, overlap, 0, 0 ); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: rect.adjust( 0, 0, -overlap, 0 ); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: rect.adjust( overlap, 0, 0, 0 ); break; default: break; } // get the relevant palette const QWidget* parent( tabBar->parentWidget() ); if( qobject_cast( parent ) ) parent = parent->parentWidget(); const auto& palette( parent ? parent->palette() : QApplication::palette() ); const auto color = hasAlteredBackground(parent) ? _helper->frameBackgroundColor( palette ):palette.color( QPalette::Window ); // render flat background painter->setPen( Qt::NoPen ); painter->setBrush( color ); painter->drawRect( rect ); return true; } //___________________________________________________________________________________ bool Style::drawPanelScrollAreaCornerPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // make sure background role matches viewport const QAbstractScrollArea* scrollArea; if( ( scrollArea = qobject_cast( widget ) ) && scrollArea->viewport() ) { // need to adjust clipRect in order not to render outside of frame const int frameWidth( pixelMetric( PM_DefaultFrameWidth, nullptr, scrollArea ) ); painter->setClipRect( insideMargin( scrollArea->rect(), frameWidth ) ); painter->setBrush( scrollArea->viewport()->palette().color( scrollArea->viewport()->backgroundRole() ) ); painter->setPen( Qt::NoPen ); painter->drawRect( option->rect ); return true; } else { return false; } } //___________________________________________________________________________________ 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 auto& palette( option->palette ); const auto outline( _helper->frameOutlineColor( palette ) ); const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); auto background( _helper->frameBackgroundColor( palette ) ); #if !BREEZE_USE_KDE4 if ( hasAlpha ) { background.setAlphaF(StyleConfigData::menuOpacity() / 100.0); } #endif _helper->renderMenuFrame( painter, option->rect, background, outline, hasAlpha ); return true; } //___________________________________________________________________________________ bool Style::drawPanelTipLabelPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // force registration of widget if( widget && widget->window() ) { _shadowHelper->registerWidget( widget->window(), true ); } const auto& palette( option->palette ); const auto background( palette.color( QPalette::ToolTipBase ) ); const auto outline( KColorUtils::mix( palette.color( QPalette::ToolTipBase ), palette.color( QPalette::ToolTipText ), 0.25 ) ); const bool hasAlpha( _helper->hasAlphaChannel( widget ) ); _helper->renderMenuFrame( painter, option->rect, background, outline, hasAlpha ); return true; } //___________________________________________________________________________________ bool Style::drawPanelItemViewItemPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check #if BREEZE_USE_KDE4 const auto viewItemOption = qstyleoption_cast( option ); #else const auto viewItemOption = qstyleoption_cast( option ); #endif if( !viewItemOption ) return false; // try cast widget const auto abstractItemView = qobject_cast( widget ); // store palette and rect const auto& palette( option->palette ); auto rect( option->rect ); // store flags const State& state( option->state ); const bool mouseOver( ( state & State_MouseOver ) && ( !abstractItemView || abstractItemView->selectionMode() != QAbstractItemView::NoSelection ) ); const bool selected( state & State_Selected ); const bool enabled( state & State_Enabled ); const bool active( state & State_Active ); const bool hasCustomBackground = viewItemOption->backgroundBrush.style() != Qt::NoBrush && !( state & State_Selected ); const bool hasSolidBackground = !hasCustomBackground || viewItemOption->backgroundBrush.style() == Qt::SolidPattern; #if BREEZE_USE_KDE4 const bool hasAlternateBackground( viewItemOption->features & QStyleOptionViewItemV2::Alternate ); #else const bool hasAlternateBackground( viewItemOption->features & QStyleOptionViewItem::Alternate ); #endif // do nothing if no background is to be rendered if( !( mouseOver || selected || hasCustomBackground || hasAlternateBackground ) ) { return true; } // define color group QPalette::ColorGroup colorGroup; if( enabled ) colorGroup = active ? QPalette::Active : QPalette::Inactive; else colorGroup = QPalette::Disabled; // render alternate background if( hasAlternateBackground ) { painter->setPen( Qt::NoPen ); painter->setBrush( palette.brush( colorGroup, QPalette::AlternateBase ) ); painter->drawRect( rect ); } // stop here if no highlight is needed if( !( mouseOver || selected ||hasCustomBackground ) ) { return true; } // render custom background if( hasCustomBackground && !hasSolidBackground ) { painter->setBrushOrigin( viewItemOption->rect.topLeft() ); painter->setBrush( viewItemOption->backgroundBrush ); painter->setPen( Qt::NoPen ); painter->drawRect( viewItemOption->rect ); return true; } // render selection // define color QColor color; QColor sideLine; if( hasCustomBackground && hasSolidBackground ) color = viewItemOption->backgroundBrush.color(); else color = palette.color( colorGroup, QPalette::Highlight ); QColor outline = color; sideLine = color; color.setAlpha(OpacityBackgroundMain); // change color to implement mouse over if( mouseOver && selected && !hasCustomBackground ) { color = color.lighter( 110 ); } // render // On sidebar panels, render it as a tabbar-looking item // otherwise use the default delegate const bool reverseLayout( option->direction == Qt::RightToLeft ); if ( widget && widget->property( PropertyNames::sidePanelView ).toBool() ) { if( selected ) { sideLine.setAlpha(OpacitySideLineSelected); } else { sideLine.setAlpha(OpacitySideLineNotSelected); } _helper->renderSidePanelItem( painter, rect, color, sideLine, reverseLayout ); } else { if( selected ) { color.setAlpha(OpacityBackgroundSelected); } else { color.setAlpha(OpacityBackgroundNotSelected); } Sides sides = SideTop|SideBottom; if( !viewItemOption->rect.isNull() ) { if( viewItemOption->viewItemPosition == QStyleOptionViewItem::Beginning || viewItemOption->viewItemPosition == QStyleOptionViewItem::OnlyOne ) sides |= SideLeft; if( viewItemOption->viewItemPosition == QStyleOptionViewItem::End || viewItemOption->viewItemPosition == QStyleOptionViewItem::OnlyOne ) sides |= SideRight; } _helper->renderSelection( painter, rect, color, outline, sides, mouseOver); } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorCheckBoxPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // store flags const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool sunken( enabled && ( state & State_Sunken ) ); const bool active( ( state & (State_On|State_NoChange) ) ); // checkbox state CheckBoxState checkBoxState( CheckOff ); if( state & State_NoChange ) checkBoxState = CheckPartial; else if( state & State_On ) checkBoxState = CheckOn; // detect checkboxes in lists const bool isSelectedItem( this->isSelectedItem( widget, rect.center() ) ); // animation state _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationPressed, checkBoxState != CheckOff ); if( _animations->widgetStateEngine().isAnimated( widget, AnimationPressed ) ) checkBoxState = CheckAnimated; const qreal animation( _animations->widgetStateEngine().opacity( widget, AnimationPressed ) ); QColor color; if( isSelectedItem ) { color = _helper->checkBoxIndicatorColor( palette, false, enabled && active ); _helper->renderCheckBoxBackground( painter, rect, palette.color( QPalette::Base ), sunken ); } else { const AnimationMode mode( _animations->widgetStateEngine().isAnimated( widget, AnimationHover ) ? AnimationHover:AnimationNone ); const qreal opacity( _animations->widgetStateEngine().opacity( widget, AnimationHover ) ); color = _helper->checkBoxIndicatorColor( palette, mouseOver, enabled && active, opacity, mode ); } // render const auto shadow( _helper->shadowColor( palette ) ); _helper->renderCheckBox( painter, rect, color, shadow, sunken, checkBoxState, animation ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorRadioButtonPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // store flags const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool sunken( state & State_Sunken ); const bool checked( state & State_On ); // radio button state RadioButtonState radioButtonState( state & State_On ? RadioOn:RadioOff ); // detect radiobuttons in lists const bool isSelectedItem( this->isSelectedItem( widget, rect.center() ) ); // animation state _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationPressed, radioButtonState != RadioOff ); if( _animations->widgetStateEngine().isAnimated( widget, AnimationPressed ) ) radioButtonState = RadioAnimated; const qreal animation( _animations->widgetStateEngine().opacity( widget, AnimationPressed ) ); // colors const auto shadow( _helper->shadowColor( palette ) ); QColor color; if( isSelectedItem ) { color = _helper->checkBoxIndicatorColor( palette, false, enabled && checked ); _helper->renderRadioButtonBackground( painter, rect, palette.color( QPalette::Base ), sunken ); } else { const AnimationMode mode( _animations->widgetStateEngine().isAnimated( widget, AnimationHover ) ? AnimationHover:AnimationNone ); const qreal opacity( _animations->widgetStateEngine().opacity( widget, AnimationHover ) ); color = _helper->checkBoxIndicatorColor( palette, mouseOver, enabled && checked, opacity, mode ); } // render _helper->renderRadioButton( painter, rect, color, shadow, sunken, radioButtonState, animation ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorButtonDropDownPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto toolButtonOption( qstyleoption_cast( option ) ); if( !toolButtonOption ) return true; // store state const State& state( option->state ); const bool autoRaise( state & State_AutoRaise ); // do nothing for autoraise buttons if( autoRaise || !(toolButtonOption->subControls & SC_ToolButtonMenu) ) return true; // store palette and rect const auto& palette( option->palette ); const auto& rect( option->rect ); // store state const bool enabled( state & State_Enabled ); const bool hasFocus( enabled && ( state & ( State_HasFocus | State_Sunken ) ) ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool sunken( enabled && ( state & State_Sunken ) ); // update animation state // mouse over takes precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); // render as push button const auto shadow( _helper->shadowColor( palette ) ); const auto outline( _helper->buttonOutlineColor( palette, mouseOver, hasFocus, opacity, mode ) ); const auto background( _helper->buttonBackgroundColor( palette, mouseOver, hasFocus, false, opacity, mode ) ); auto frameRect( rect ); painter->setClipRect( rect ); frameRect.adjust( -Metrics::Frame_FrameRadius - 1, 0, 0, 0 ); frameRect = visualRect( option, frameRect ); // render _helper->renderButtonFrame( painter, frameRect, background, outline, shadow, hasFocus, sunken ); // also render separator auto separatorRect( rect.adjusted( 0, 2, -2, -2 ) ); separatorRect.setWidth( 1 ); separatorRect = visualRect( option, separatorRect ); _helper->renderSeparator( painter, separatorRect, outline, true ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorTabClosePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // get icon and check QIcon icon( standardIcon( SP_TitleBarCloseButton, option, widget ) ); if( icon.isNull() ) return false; // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool active( state & State_Raised ); const bool sunken( state & State_Sunken ); // decide icon mode and state QIcon::Mode iconMode; QIcon::State iconState; if( !enabled ) { iconMode = QIcon::Disabled; iconState = QIcon::Off; } else { if( active ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; iconState = sunken ? QIcon::On : QIcon::Off; } // icon size const int iconWidth( pixelMetric(QStyle::PM_SmallIconSize, option, widget ) ); const QSize iconSize( iconWidth, iconWidth ); // get pixmap const QPixmap pixmap( icon.pixmap( iconSize, iconMode, iconState ) ); // render drawItemPixmap( painter, option->rect, Qt::AlignCenter, pixmap ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorTabTearPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const auto tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; // store palette and rect const auto& palette( option->palette ); auto rect( option->rect ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const auto color( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.2 ) ); painter->setRenderHint( QPainter::Antialiasing, false ); painter->setPen( color ); painter->setBrush( Qt::NoBrush ); switch( tabOption->shape ) { case QTabBar::TriangularNorth: case QTabBar::RoundedNorth: rect.adjust( 0, 1, 0, 0 ); if( reverseLayout ) painter->drawLine( rect.topRight(), rect.bottomRight() ); else painter->drawLine( rect.topLeft(), rect.bottomLeft() ); break; case QTabBar::TriangularSouth: case QTabBar::RoundedSouth: rect.adjust( 0, 0, 0, -1 ); if( reverseLayout ) painter->drawLine( rect.topRight(), rect.bottomRight() ); else painter->drawLine( rect.topLeft(), rect.bottomLeft() ); break; case QTabBar::TriangularWest: case QTabBar::RoundedWest: rect.adjust( 1, 0, 0, 0 ); painter->drawLine( rect.topLeft(), rect.topRight() ); break; case QTabBar::TriangularEast: case QTabBar::RoundedEast: rect.adjust( 0, 0, -1, 0 ); painter->drawLine( rect.topLeft(), rect.topRight() ); break; default: break; } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorToolBarHandlePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // do nothing if disabled from options if( !StyleConfigData::toolBarDrawItemSeparator() ) return true; // store rect and palette auto rect( option->rect ); const auto& palette( option->palette ); // store state const State& state( option->state ); const bool separatorIsVertical( state & State_Horizontal ); // define color and render const auto color( _helper->separatorColor( palette ) ); if( separatorIsVertical ) { rect.setWidth( Metrics::ToolBar_HandleWidth ); rect = centerRect( option->rect, rect.size() ); rect.setWidth( 3 ); _helper->renderSeparator( painter, rect, color, separatorIsVertical ); rect.translate( 2, 0 ); _helper->renderSeparator( painter, rect, color, separatorIsVertical ); } else { rect.setHeight( Metrics::ToolBar_HandleWidth ); rect = centerRect( option->rect, rect.size() ); rect.setHeight( 3 ); _helper->renderSeparator( painter, rect, color, separatorIsVertical ); rect.translate( 0, 2 ); _helper->renderSeparator( painter, rect, color, separatorIsVertical ); } return true; } //___________________________________________________________________________________ bool Style::drawIndicatorToolBarSeparatorPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { /* * do nothing if disabled from options * also need to check if widget is a combobox, because of Qt hack using 'toolbar' separator primitive * for rendering separators in comboboxes */ if( !( StyleConfigData::toolBarDrawItemSeparator() || qobject_cast( widget ) ) ) { return true; } // store rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // store state const State& state( option->state ); const bool separatorIsVertical( state & State_Horizontal ); // define color and render const auto color( _helper->separatorColor( palette ) ); _helper->renderSeparator( painter, rect, color, separatorIsVertical ); return true; } //___________________________________________________________________________________ bool Style::drawIndicatorBranchPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // state const State& state( option->state ); const bool reverseLayout( option->direction == Qt::RightToLeft ); //draw expander int expanderAdjust = 0; if( state & State_Children ) { // state const bool expanderOpen( state & State_Open ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); // expander rect int expanderSize = qMin( rect.width(), rect.height() ); expanderSize = qMin( expanderSize, int(Metrics::ItemView_ArrowSize) ); expanderAdjust = expanderSize/2 + 1; const auto arrowRect = centerRect( rect, expanderSize, expanderSize ); // get orientation from option ArrowOrientation orientation; if( expanderOpen ) orientation = ArrowDown; else if( reverseLayout ) orientation = ArrowLeft; else orientation = ArrowRight; // color const auto arrowColor( mouseOver ? _helper->hoverColor( palette ) : _helper->arrowColor( palette, QPalette::Text ) ); // render _helper->renderArrow( painter, arrowRect, arrowColor, orientation ); } // tree branches if( !StyleConfigData::viewDrawTreeBranchLines() ) return true; const auto center( rect.center() ); const auto lineColor( KColorUtils::mix( palette.color( QPalette::Base ), palette.color( QPalette::Text ), 0.25 ) ); painter->setRenderHint( QPainter::Antialiasing, true ); painter->translate( 0.5, 0.5 ); painter->setPen( QPen( lineColor, 1 ) ); if( state & ( State_Item | State_Children | State_Sibling ) ) { const QLineF line( QPointF( center.x(), rect.top() ), QPointF( center.x(), center.y() - expanderAdjust - 1 ) ); painter->drawLine( line ); } // The right/left (depending on direction) line gets drawn if we have an item if( state & State_Item ) { const QLineF line = reverseLayout ? QLineF( QPointF( rect.left(), center.y() ), QPointF( center.x() - expanderAdjust, center.y() ) ): QLineF( QPointF( center.x() + expanderAdjust, center.y() ), QPointF( rect.right(), center.y() ) ); painter->drawLine( line ); } // The bottom if we have a sibling if( state & State_Sibling ) { const QLineF line( QPointF( center.x(), center.y() + expanderAdjust ), QPointF( center.x(), rect.bottom() ) ); painter->drawLine( line ); } return true; } //___________________________________________________________________________________ bool Style::drawPushButtonLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto buttonOption( qstyleoption_cast( option ) ); if( !buttonOption ) return true; // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool sunken( state & (State_On | State_Sunken) ); const bool mouseOver( enabled && (option->state & State_MouseOver) ); const bool hasFocus( enabled && !mouseOver && (option->state & State_HasFocus) ); const bool flat( buttonOption->features & QStyleOptionButton::Flat ); // content const bool hasText( !buttonOption->text.isEmpty() ); const bool hasIcon( (showIconsOnPushButtons() || flat || !hasText ) && !buttonOption->icon.isNull() ); // contents auto contentsRect( rect ); if( sunken && !flat ) contentsRect.translate( 1, 1 ); // color role QPalette::ColorRole textRole; if( flat ) { if( hasFocus && sunken ) textRole = QPalette::HighlightedText; else textRole = QPalette::WindowText; } else if( hasFocus ) textRole = QPalette::HighlightedText; else textRole = QPalette::ButtonText; // menu arrow if( buttonOption->features & QStyleOptionButton::HasMenu ) { // define rect auto arrowRect( contentsRect ); arrowRect.setLeft( contentsRect.right() - Metrics::MenuButton_IndicatorWidth + 1 ); arrowRect = centerRect( arrowRect, Metrics::MenuButton_IndicatorWidth, Metrics::MenuButton_IndicatorWidth ); contentsRect.setRight( arrowRect.left() - Metrics::Button_ItemSpacing - 1 ); contentsRect.adjust( Metrics::Button_MarginWidth, 0, 0, 0 ); arrowRect = visualRect( option, arrowRect ); // define color const auto arrowColor( _helper->arrowColor( palette, textRole ) ); _helper->renderArrow( painter, arrowRect, arrowColor, ArrowDown ); } // icon size QSize iconSize; if( hasIcon ) { iconSize = buttonOption->iconSize; if( !iconSize.isValid() ) { const int metric( pixelMetric( PM_SmallIconSize, option, widget ) ); iconSize = QSize( metric, metric ); } } // text size const int textFlags( _mnemonics->textFlags() | Qt::AlignCenter ); const QSize textSize( option->fontMetrics.size( textFlags, buttonOption->text ) ); // adjust text and icon rect based on options QRect iconRect; QRect textRect; if( hasText && !hasIcon ) textRect = contentsRect; else if( hasIcon && !hasText ) iconRect = contentsRect; else { const int contentsWidth( iconSize.width() + textSize.width() + Metrics::Button_ItemSpacing ); iconRect = QRect( QPoint( contentsRect.left() + (contentsRect.width() - contentsWidth )/2, contentsRect.top() + (contentsRect.height() - iconSize.height())/2 ), iconSize ); textRect = QRect( QPoint( iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, contentsRect.top() + (contentsRect.height() - textSize.height())/2 ), textSize ); } // handle right to left if( iconRect.isValid() ) iconRect = visualRect( option, iconRect ); if( textRect.isValid() ) textRect = visualRect( option, textRect ); // make sure there is enough room for icon if( iconRect.isValid() ) iconRect = centerRect( iconRect, iconSize ); // render icon if( hasIcon && iconRect.isValid() ) { // icon state and mode const QIcon::State iconState( sunken ? QIcon::On : QIcon::Off ); QIcon::Mode iconMode; if( !enabled ) iconMode = QIcon::Disabled; else if( !flat && hasFocus ) iconMode = QIcon::Selected; else if( mouseOver && flat ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; const auto pixmap = buttonOption->icon.pixmap( iconSize, iconMode, iconState ); drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); } // render text if( hasText && textRect.isValid() ) { drawItemText( painter, textRect, textFlags, palette, enabled, buttonOption->text, textRole ); } return true; } //___________________________________________________________________________________ bool Style::drawToolButtonLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto toolButtonOption( qstyleoption_cast(option) ); // copy rect and palette const auto& rect = option->rect; const auto& palette = option->palette; // state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool sunken( state & (State_On | State_Sunken) ); const bool mouseOver( enabled && (option->state & State_MouseOver) ); const bool flat( state & State_AutoRaise ); // focus flag is set to match the background color in either renderButtonFrame or renderToolButtonFrame bool hasFocus( false ); if( flat ) hasFocus = enabled && !mouseOver && (option->state & State_HasFocus); else hasFocus = enabled && !mouseOver && (option->state & (State_HasFocus|State_Sunken) ); const bool hasArrow( toolButtonOption->features & QStyleOptionToolButton::Arrow ); const bool hasIcon( !( hasArrow || toolButtonOption->icon.isNull() ) ); const bool hasText( !toolButtonOption->text.isEmpty() ); // contents auto contentsRect( rect ); if( sunken && !flat ) contentsRect.translate( 1, 1 ); // icon size const QSize iconSize( toolButtonOption->iconSize ); // text size int textFlags( _mnemonics->textFlags() ); const QSize textSize( option->fontMetrics.size( textFlags, toolButtonOption->text ) ); // adjust text and icon rect based on options QRect iconRect; QRect textRect; if( hasText && ( !(hasArrow||hasIcon) || toolButtonOption->toolButtonStyle == Qt::ToolButtonTextOnly ) ) { // text only textRect = contentsRect; textFlags |= Qt::AlignCenter; } else if( (hasArrow||hasIcon) && (!hasText || toolButtonOption->toolButtonStyle == Qt::ToolButtonIconOnly ) ) { // icon only iconRect = contentsRect; } else if( toolButtonOption->toolButtonStyle == Qt::ToolButtonTextUnderIcon ) { const int contentsHeight( iconSize.height() + textSize.height() + Metrics::ToolButton_ItemSpacing ); iconRect = QRect( QPoint( contentsRect.left() + (contentsRect.width() - iconSize.width())/2, contentsRect.top() + (contentsRect.height() - contentsHeight)/2 ), iconSize ); textRect = QRect( QPoint( contentsRect.left() + (contentsRect.width() - textSize.width())/2, iconRect.bottom() + Metrics::ToolButton_ItemSpacing + 1 ), textSize ); textFlags |= Qt::AlignCenter; } else { const bool leftAlign( widget && widget->property( PropertyNames::toolButtonAlignment ).toInt() == Qt::AlignLeft ); if( leftAlign ) { const int marginWidth( Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth + 1 ); iconRect = QRect( QPoint( contentsRect.left() + marginWidth, contentsRect.top() + (contentsRect.height() - iconSize.height())/2 ), iconSize ); } else { const int contentsWidth( iconSize.width() + textSize.width() + Metrics::ToolButton_ItemSpacing ); iconRect = QRect( QPoint( contentsRect.left() + (contentsRect.width() - contentsWidth )/2, contentsRect.top() + (contentsRect.height() - iconSize.height())/2 ), iconSize ); } textRect = QRect( QPoint( iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, contentsRect.top() + (contentsRect.height() - textSize.height())/2 ), textSize ); // handle right to left layouts iconRect = visualRect( option, iconRect ); textRect = visualRect( option, textRect ); textFlags |= Qt::AlignLeft | Qt::AlignVCenter; } // make sure there is enough room for icon if( iconRect.isValid() ) iconRect = centerRect( iconRect, iconSize ); // render arrow or icon if( hasArrow && iconRect.isValid() ) { QStyleOptionToolButton copy( *toolButtonOption ); copy.rect = iconRect; switch( toolButtonOption->arrowType ) { case Qt::LeftArrow: drawPrimitive( PE_IndicatorArrowLeft, ©, painter, widget ); break; case Qt::RightArrow: drawPrimitive( PE_IndicatorArrowRight, ©, painter, widget ); break; case Qt::UpArrow: drawPrimitive( PE_IndicatorArrowUp, ©, painter, widget ); break; case Qt::DownArrow: drawPrimitive( PE_IndicatorArrowDown, ©, painter, widget ); break; default: break; } } else if( hasIcon && iconRect.isValid() ) { // icon state and mode const QIcon::State iconState( sunken ? QIcon::On : QIcon::Off ); QIcon::Mode iconMode; if( !enabled ) iconMode = QIcon::Disabled; else if( (!flat && hasFocus) || (flat && (state & State_Sunken) && !mouseOver) ) iconMode = QIcon::Selected; else if( mouseOver && flat ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; const QPixmap pixmap = toolButtonOption->icon.pixmap( iconSize, iconMode, iconState ); drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); } // render text if( hasText && textRect.isValid() ) { QPalette::ColorRole textRole( QPalette::ButtonText ); if( flat ) textRole = ( ((hasFocus&&sunken) || (state & State_Sunken))&&!mouseOver) ? QPalette::HighlightedText: QPalette::WindowText; else if( hasFocus&&!mouseOver ) textRole = QPalette::HighlightedText; painter->setFont(toolButtonOption->font); drawItemText( painter, textRect, textFlags, palette, enabled, toolButtonOption->text, textRole ); } return true; } //___________________________________________________________________________________ bool Style::drawCheckBoxLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto buttonOption( qstyleoption_cast(option) ); if( !buttonOption ) return true; // copy palette and rect const auto& palette( option->palette ); const auto& rect( option->rect ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); // text alignment const bool reverseLayout( option->direction == Qt::RightToLeft ); const int textFlags( _mnemonics->textFlags() | Qt::AlignVCenter | (reverseLayout ? Qt::AlignRight:Qt::AlignLeft ) ); // text rect auto textRect( rect ); // render icon if( !buttonOption->icon.isNull() ) { const QIcon::Mode mode( enabled ? QIcon::Normal : QIcon::Disabled ); const QPixmap pixmap( buttonOption->icon.pixmap( buttonOption->iconSize, mode ) ); drawItemPixmap( painter, rect, textFlags, pixmap ); // adjust rect (copied from QCommonStyle) textRect.setLeft( textRect.left() + buttonOption->iconSize.width() + 4 ); textRect = visualRect( option, textRect ); } // render text if( !buttonOption->text.isEmpty() ) { textRect = option->fontMetrics.boundingRect( textRect, textFlags, buttonOption->text ); drawItemText( painter, textRect, textFlags, palette, enabled, buttonOption->text, QPalette::WindowText ); // check focus state const bool hasFocus( enabled && ( state & State_HasFocus ) ); // update animation state _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus ); const bool isFocusAnimated( _animations->widgetStateEngine().isAnimated( widget, AnimationFocus ) ); const qreal opacity( _animations->widgetStateEngine().opacity( widget, AnimationFocus ) ); // focus color QColor focusColor; if( isFocusAnimated ) focusColor = _helper->alphaColor( _helper->focusColor( palette ), opacity ); else if( hasFocus ) focusColor = _helper->focusColor( palette ); // render focus _helper->renderFocusLine( painter, textRect, focusColor ); } return true; } //___________________________________________________________________________________ bool Style::drawComboBoxLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const auto comboBoxOption( qstyleoption_cast( option ) ); if( !comboBoxOption ) return false; if( comboBoxOption->editable ) return false; // need to alter palette for focused buttons const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool sunken( state & (State_On | State_Sunken) ); const bool mouseOver( enabled && (option->state & State_MouseOver) ); const bool hasFocus( enabled && !mouseOver && (option->state & State_HasFocus) ); const bool flat( !comboBoxOption->frame ); QPalette::ColorRole textRole; if( flat ) { if( hasFocus && sunken ) textRole = QPalette::HighlightedText; else textRole = QPalette::WindowText; } else if( hasFocus ) textRole = QPalette::HighlightedText; else textRole = QPalette::ButtonText; // change pen color directly painter->setPen( QPen( option->palette.color( textRole ), 1 ) ); // translate painter for pressed down comboboxes if( sunken && !flat ) { painter->translate( 1, 1 ); } #if QT_VERSION >= 0x050000 if (const auto cb = qstyleoption_cast(option)) { auto editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget); painter->save(); painter->setClipRect(editRect); if (!cb->currentIcon.isNull()) { QIcon::Mode mode; if ((cb->state & QStyle::State_Selected) && (cb->state & QStyle::State_Active)) { mode = QIcon::Selected; } else if (cb->state & QStyle::State_Enabled) { mode = QIcon::Normal; } else { mode = QIcon::Disabled; } QWindow *window = nullptr; if (widget && widget->window()) { window = widget->window()->windowHandle(); #if BREEZE_HAVE_QTQUICK } else if (QQuickItem *quickItem = qobject_cast(option->styleObject)) { window = quickItem->window(); #endif } const auto pixmap = cb->currentIcon.pixmap(window, cb->iconSize, mode); auto iconRect(editRect); iconRect.setWidth(cb->iconSize.width() + 4); iconRect = alignedRect(cb->direction, Qt::AlignLeft | Qt::AlignVCenter, iconRect.size(), editRect); if (cb->editable) painter->fillRect(iconRect, option->palette.brush(QPalette::Base)); proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); if (cb->direction == Qt::RightToLeft) editRect.translate(-4 - cb->iconSize.width(), 0); else editRect.translate(cb->iconSize.width() + 4, 0); } if (!cb->currentText.isEmpty() && !cb->editable) { proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0), visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter), cb->palette, cb->state & State_Enabled, cb->currentText); } painter->restore(); } #else // call base class method ParentStyleClass::drawControl( CE_ComboBoxLabel, option, painter, widget ); #endif return true; } //___________________________________________________________________________________ bool Style::drawMenuBarItemControl( const QStyleOption* option, QPainter* painter, const QWidget* widget) const { // cast option and check const auto menuItemOption = qstyleoption_cast( option ); if( !menuItemOption ) return true; // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( enabled && (state & State_Selected) ); const bool sunken( enabled && (state & State_Sunken) ); const bool useStrongFocus( StyleConfigData::menuItemDrawStrongFocus() ); // render hover and focus if( useStrongFocus && ( selected || sunken ) ) { QColor backgroundColor = _helper->focusColor( palette ); QColor outlineColor = backgroundColor; backgroundColor.setAlpha(OpacityBackgroundMain); if( sunken ) { _helper->renderMenuBarItem( painter, rect, backgroundColor, outlineColor ); } else if( selected ) { _helper->renderFocusRect( painter, rect, backgroundColor, outlineColor ); } } /* check if item as an icon, in which case only the icon should be rendered consistently with comment in QMenuBarPrivate::calcActionRects */ if( !menuItemOption->icon.isNull() ) { // icon size is forced to SmallIconSize const auto iconSize = pixelMetric(QStyle::PM_SmallIconSize, nullptr, widget); const auto iconRect = centerRect( rect, iconSize, iconSize ); // decide icon mode and state QIcon::Mode iconMode; QIcon::State iconState; if( !enabled ) { iconMode = QIcon::Disabled; iconState = QIcon::Off; } else { if( useStrongFocus && sunken ) iconMode = QIcon::Selected; else if( useStrongFocus && selected ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; iconState = sunken ? QIcon::On : QIcon::Off; } const auto pixmap = menuItemOption->icon.pixmap( iconSize, iconMode, iconState ); drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); // render outline if( !useStrongFocus && ( selected || sunken ) ) { QColor outlineColor; if( sunken ) outlineColor = _helper->focusColor( palette ); else if( selected ) outlineColor = _helper->hoverColor( palette ); _helper->renderFocusLine( painter, iconRect, outlineColor ); } } else { // get text rect const int textFlags( Qt::AlignCenter|_mnemonics->textFlags() ); const auto textRect = option->fontMetrics.boundingRect( rect, textFlags, menuItemOption->text ); // render text const QPalette::ColorRole role = (useStrongFocus && sunken ) ? QPalette::HighlightedText : QPalette::WindowText; drawItemText( painter, textRect, textFlags, palette, enabled, menuItemOption->text, role ); // render outline if( !useStrongFocus && ( selected || sunken ) ) { QColor outlineColor; if( sunken ) outlineColor = _helper->focusColor( palette ); else if( selected ) outlineColor = _helper->hoverColor( palette ); _helper->renderFocusLine( painter, textRect, outlineColor ); } } return true; } //___________________________________________________________________________________ bool Style::drawMenuItemControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto menuItemOption = qstyleoption_cast( option ); if( !menuItemOption ) return true; if( menuItemOption->menuItemType == QStyleOptionMenuItem::EmptyArea ) return true; // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // deal with separators if( menuItemOption->menuItemType == QStyleOptionMenuItem::Separator ) { // normal separator if( menuItemOption->text.isEmpty() && menuItemOption->icon.isNull() ) { const auto color( _helper->separatorColor( palette ) ); _helper->renderSeparator( painter, rect, color ); return true; } else { /* * separator can have a title and an icon * in that case they are rendered as menu title buttons */ QStyleOptionToolButton copy( separatorMenuItemOption( menuItemOption, widget ) ); renderMenuTitle( ©, painter, widget ); return true; } } // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( enabled && (state & State_Selected) ); const bool sunken( enabled && (state & (State_On|State_Sunken) ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); const bool useStrongFocus( StyleConfigData::menuItemDrawStrongFocus() ); // render hover and focus if( useStrongFocus && ( selected || sunken ) ) { const auto color = _helper->focusColor( palette ); const auto outlineColor = _helper->focusOutlineColor( palette ); _helper->renderFocusRect( painter, rect.marginsRemoved( QMargins(MenuItem_HighlightHorizontalMargin, MenuItem_HighlightVerticalMargin, MenuItem_HighlightHorizontalMargin, MenuItem_HighlightVerticalMargin )), color, outlineColor ); } // get rect available for contents auto contentsRect( insideMargin( rect, Metrics::MenuItem_MarginWidth, Metrics::MenuItem_MarginHeight ) ); // define relevant rectangles // checkbox QRect checkBoxRect; if( menuItemOption->menuHasCheckableItems ) { checkBoxRect = QRect( contentsRect.left(), contentsRect.top() + (contentsRect.height()-Metrics::CheckBox_Size)/2, Metrics::CheckBox_Size, Metrics::CheckBox_Size ); contentsRect.setLeft( checkBoxRect.right() + Metrics::MenuItem_ItemSpacing + 1 ); } // render checkbox indicator if( menuItemOption->checkType == QStyleOptionMenuItem::NonExclusive ) { checkBoxRect = visualRect( option, checkBoxRect ); // checkbox state if( useStrongFocus && ( selected || sunken ) ) { _helper->renderCheckBoxBackground( painter, checkBoxRect, palette.color( QPalette::Window ), sunken ); } CheckBoxState state( menuItemOption->checked ? CheckOn : CheckOff ); const bool active( menuItemOption->checked ); const auto shadow( _helper->shadowColor( palette ) ); const auto color( _helper->checkBoxIndicatorColor( palette, false, enabled && active ) ); _helper->renderCheckBox( painter, checkBoxRect, color, shadow, sunken, state ); } else if( menuItemOption->checkType == QStyleOptionMenuItem::Exclusive ) { checkBoxRect = visualRect( option, checkBoxRect ); if( useStrongFocus && ( selected || sunken ) ) { _helper->renderRadioButtonBackground( painter, checkBoxRect, palette.color( QPalette::Window ), sunken ); } const bool active( menuItemOption->checked ); const auto shadow( _helper->shadowColor( palette ) ); const auto color( _helper->checkBoxIndicatorColor( palette, false, enabled && active ) ); _helper->renderRadioButton( painter, checkBoxRect, color, shadow, sunken, active ? RadioOn:RadioOff ); } // icon int iconWidth = 0; const bool showIcon( showIconsInMenuItems() ); if( showIcon ) iconWidth = isQtQuickControl( option, widget ) ? qMax( pixelMetric(PM_SmallIconSize, option, widget ), menuItemOption->maxIconWidth ) : menuItemOption->maxIconWidth; QRect iconRect; if( showIcon && iconWidth > 0 ) { iconRect = QRect( contentsRect.left(), contentsRect.top() + (contentsRect.height()-iconWidth)/2, iconWidth, iconWidth ); contentsRect.setLeft( iconRect.right() + Metrics::MenuItem_ItemSpacing + 1 ); const QSize iconSize( pixelMetric( PM_SmallIconSize, option, widget ), pixelMetric( PM_SmallIconSize, option, widget ) ); iconRect = centerRect( iconRect, iconSize ); } if( showIcon && !menuItemOption->icon.isNull() ) { iconRect = visualRect( option, iconRect ); // icon mode QIcon::Mode mode; if( selected && !useStrongFocus) mode = QIcon::Active; else if( selected ) mode = QIcon::Selected; else if( enabled ) mode = QIcon::Normal; else mode = QIcon::Disabled; // icon state const QIcon::State iconState( sunken ? QIcon::On:QIcon::Off ); const QPixmap icon = menuItemOption->icon.pixmap( iconRect.size(), mode, iconState ); painter->drawPixmap( iconRect, icon ); } // arrow QRect arrowRect( contentsRect.right() - Metrics::MenuButton_IndicatorWidth + 1, contentsRect.top() + (contentsRect.height()-Metrics::MenuButton_IndicatorWidth)/2, Metrics::MenuButton_IndicatorWidth, Metrics::MenuButton_IndicatorWidth ); contentsRect.setRight( arrowRect.left() - Metrics::MenuItem_ItemSpacing - 1 ); if( menuItemOption->menuItemType == QStyleOptionMenuItem::SubMenu ) { // apply right-to-left layout arrowRect = visualRect( option, arrowRect ); // arrow orientation const ArrowOrientation orientation( reverseLayout ? ArrowLeft:ArrowRight ); // color QColor arrowColor; if( useStrongFocus && ( selected || sunken ) ) arrowColor = palette.color( QPalette::HighlightedText ); else if( sunken ) arrowColor = _helper->focusColor( palette ); else if( selected ) arrowColor = _helper->hoverColor( palette ); else arrowColor = _helper->arrowColor( palette, QPalette::WindowText ); // render _helper->renderArrow( painter, arrowRect, arrowColor, orientation ); } // text auto textRect = contentsRect; if( !menuItemOption->text.isEmpty() ) { // adjust textRect QString text = menuItemOption->text; textRect = centerRect( textRect, textRect.width(), option->fontMetrics.size( _mnemonics->textFlags(), text ).height() ); textRect = visualRect( option, textRect ); // set font painter->setFont( menuItemOption->font ); // color role const QPalette::ColorRole role = (useStrongFocus && ( selected || sunken )) ? QPalette::HighlightedText : QPalette::WindowText; // locate accelerator and render const int tabPosition( text.indexOf( QLatin1Char( '\t' ) ) ); if( tabPosition >= 0 ) { const int textFlags( Qt::AlignVCenter | Qt::AlignRight ); QString accelerator( text.mid( tabPosition + 1 ) ); text = text.left( tabPosition ); drawItemText( painter, textRect, textFlags, palette, enabled, accelerator, role ); } // render text const int textFlags( Qt::AlignVCenter | (reverseLayout ? Qt::AlignRight : Qt::AlignLeft ) | _mnemonics->textFlags() ); textRect = option->fontMetrics.boundingRect( textRect, textFlags, text ); drawItemText( painter, textRect, textFlags, palette, enabled, text, role ); // render hover and focus if( !useStrongFocus && ( selected || sunken ) ) { QColor outlineColor; if( sunken ) outlineColor = _helper->focusColor( palette ); else if( selected ) outlineColor = _helper->hoverColor( palette ); _helper->renderFocusLine( painter, textRect, outlineColor ); } } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const auto progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return true; // render groove #if BREEZE_USE_KDE4 QStyleOptionProgressBarV2 progressBarOption2 = *progressBarOption; #else QStyleOptionProgressBar progressBarOption2 = *progressBarOption; #endif progressBarOption2.rect = subElementRect( SE_ProgressBarGroove, progressBarOption, widget ); drawControl( CE_ProgressBarGroove, &progressBarOption2, painter, widget ); #if QT_VERSION >= 0x050000 const QObject* styleObject( widget ? widget:progressBarOption->styleObject ); #else const QObject* styleObject( widget ); #endif // enable busy animations // need to check both widget and passed styleObject, used for QML if( styleObject && _animations->busyIndicatorEngine().enabled() ) { #if QT_VERSION >= 0x050000 // register QML object if defined if( !widget && progressBarOption->styleObject ) { _animations->busyIndicatorEngine().registerWidget( progressBarOption->styleObject ); } #endif _animations->busyIndicatorEngine().setAnimated( styleObject, progressBarOption->maximum == 0 && progressBarOption->minimum == 0 ); } // check if animated and pass to option if( _animations->busyIndicatorEngine().isAnimated( styleObject ) ) { progressBarOption2.progress = _animations->busyIndicatorEngine().value(); } // render contents progressBarOption2.rect = subElementRect( SE_ProgressBarContents, progressBarOption, widget ); drawControl( CE_ProgressBarContents, &progressBarOption2, painter, widget ); // render text const bool textVisible( progressBarOption->textVisible ); const bool busy( progressBarOption->minimum == 0 && progressBarOption->maximum == 0 ); if( textVisible && !busy ) { progressBarOption2.rect = subElementRect( SE_ProgressBarLabel, progressBarOption, widget ); drawControl( CE_ProgressBarLabel, &progressBarOption2, painter, widget ); } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarContentsControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const auto progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return true; // copy rect and palette auto rect( option->rect ); const auto& palette( option->palette ); // get direction #if BREEZE_USE_KDE4 const auto progressBarOption2( qstyleoption_cast( option ) ); const bool horizontal = !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal; const bool inverted( progressBarOption2 ? progressBarOption2->invertedAppearance : false ); #else const bool horizontal( BreezePrivate::isProgressBarHorizontal( progressBarOption ) ); const bool inverted( progressBarOption->invertedAppearance ); #endif bool reverse = horizontal && option->direction == Qt::RightToLeft; if( inverted ) reverse = !reverse; // check if anything is to be drawn const bool busy( ( progressBarOption->minimum == 0 && progressBarOption->maximum == 0 ) ); if( busy ) { const qreal progress( _animations->busyIndicatorEngine().value() ); const auto first( palette.color( QPalette::Highlight ) ); const auto second( KColorUtils::mix( palette.color( QPalette::Highlight ), palette.color( QPalette::Window ), 0.7 ) ); _helper->renderProgressBarBusyContents( painter, rect, first, second, horizontal, reverse, progress ); } else { const QRegion oldClipRegion( painter->clipRegion() ); if( horizontal ) { if( rect.width() < Metrics::ProgressBar_Thickness ) { painter->setClipRect( rect, Qt::IntersectClip ); if( reverse ) rect.setLeft( rect.left() - Metrics::ProgressBar_Thickness + rect.width() ); else rect.setWidth( Metrics::ProgressBar_Thickness ); } } else { if( rect.height() < Metrics::ProgressBar_Thickness ) { painter->setClipRect( rect, Qt::IntersectClip ); if( reverse ) rect.setHeight( Metrics::ProgressBar_Thickness ); else rect.setTop( rect.top() - Metrics::ProgressBar_Thickness + rect.height() ); } } auto contentsColor( option->state.testFlag( QStyle::State_Selected ) ? palette.color( QPalette::HighlightedText ) : palette.color( QPalette::Highlight ) ); _helper->renderProgressBarContents( painter, rect, contentsColor ); painter->setClipRegion( oldClipRegion ); } return true; } //___________________________________________________________________________________ bool Style::drawProgressBarGrooveControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const auto& palette( option->palette ); const auto color( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.3 ) ); _helper->renderProgressBarGroove( painter, option->rect, color ); return true; } //___________________________________________________________________________________ bool Style::drawProgressBarLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // cast option and check const auto progressBarOption( qstyleoption_cast( option ) ); if( !progressBarOption ) return true; // get direction and check #if BREEZE_USE_KDE4 const auto progressBarOption2( qstyleoption_cast( option ) ); const bool horizontal = !progressBarOption2 || progressBarOption2->orientation == Qt::Horizontal; #else const bool horizontal( BreezePrivate::isProgressBarHorizontal( progressBarOption ) ); #endif if( !horizontal ) return true; // store rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // store state and direction const State& state( option->state ); const bool enabled( state & State_Enabled ); // define text rect Qt::Alignment hAlign( ( progressBarOption->textAlignment == Qt::AlignLeft ) ? Qt::AlignHCenter : progressBarOption->textAlignment ); drawItemText( painter, rect, Qt::AlignVCenter | hAlign, palette, enabled, progressBarOption->text, QPalette::WindowText ); return true; } //___________________________________________________________________________________ bool Style::drawScrollBarSliderControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); //try to understand if anywhere the widget is under mouse, not just the handle, use _animations in case of QWidget, option->styleObject in case of QML #if QT_VERSION >= 0x050000 bool widgetMouseOver( ( option->state & State_MouseOver ) ); if( widget ) widgetMouseOver = _animations->scrollBarEngine().isHovered( widget, QStyle::SC_ScrollBarGroove ); else if( option->styleObject ) widgetMouseOver = option->styleObject->property("hover").toBool(); #else const bool widgetMouseOver( _animations->scrollBarEngine().isHovered( widget, QStyle::SC_ScrollBarGroove ) ); #endif qreal grooveAnimationOpacity( _animations->scrollBarEngine().opacity( widget, QStyle::SC_ScrollBarGroove ) ); if( grooveAnimationOpacity == AnimationData::OpacityInvalid ) grooveAnimationOpacity = (widgetMouseOver ? 1 : 0); const qreal handleSize = StyleConfigData::animationsEnabled() ? ((Metrics::ScrollBar_SliderWidth / 2.0) * (1 - grooveAnimationOpacity) + Metrics::ScrollBar_SliderWidth * grooveAnimationOpacity) : (int)Metrics::ScrollBar_SliderWidth; // define handle rect QRect handleRect; const State& state( option->state ); const bool horizontal( state & State_Horizontal ); if( horizontal ) handleRect = centerRect( rect, rect.width(), handleSize ); else handleRect = centerRect( rect, handleSize, rect.height() ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); // check focus from relevant parent const QWidget* parent( scrollBarParent( widget ) ); const bool hasFocus( enabled && ( (widget && widget->hasFocus()) || (parent && parent->hasFocus()) ) ); // enable animation state const bool handleActive( sliderOption->activeSubControls & SC_ScrollBarSlider ); _animations->scrollBarEngine().updateState( widget, AnimationFocus, hasFocus ); _animations->scrollBarEngine().updateState( widget, AnimationHover, mouseOver && handleActive ); const auto mode( _animations->scrollBarEngine().animationMode( widget, SC_ScrollBarSlider ) ); const qreal opacity( _animations->scrollBarEngine().opacity( widget, SC_ScrollBarSlider ) ); auto color = _helper->scrollBarHandleColor( palette, mouseOver, hasFocus, opacity, mode ); if (StyleConfigData::animationsEnabled()) { color.setAlphaF(color.alphaF() * (0.7 + 0.3 * grooveAnimationOpacity)); } _helper->renderScrollBarHandle( painter, handleRect, color ); 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 auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; const State& state( option->state ); const bool horizontal( state & State_Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // adjust rect, based on number of buttons to be drawn const auto rect( scrollBarInternalSubControlRect( sliderOption, SC_ScrollBarAddLine ) ); QColor color; QStyleOptionSlider copy( *sliderOption ); if( _addLineButtons == DoubleButton ) { if( horizontal ) { //Draw the arrows const QSize halfSize( rect.width()/2, rect.height() ); const QRect leftSubButton( rect.topLeft(), halfSize ); const QRect rightSubButton( leftSubButton.topRight() + QPoint( 1, 0 ), halfSize ); copy.rect = leftSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarAddLine:SC_ScrollBarSubLine, widget ); _helper->renderArrow( painter, leftSubButton, color, ArrowLeft ); copy.rect = rightSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarSubLine:SC_ScrollBarAddLine, widget ); _helper->renderArrow( painter, rightSubButton, color, ArrowRight ); } else { const QSize halfSize( rect.width(), rect.height()/2 ); const QRect topSubButton( rect.topLeft(), halfSize ); const QRect botSubButton( topSubButton.bottomLeft() + QPoint( 0, 1 ), halfSize ); copy.rect = topSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarSubLine, widget ); _helper->renderArrow( painter, topSubButton, color, ArrowUp ); copy.rect = botSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarAddLine, widget ); _helper->renderArrow( painter, botSubButton, color, ArrowDown ); } } else if( _addLineButtons == SingleButton ) { copy.rect = rect; color = scrollBarArrowColor( ©, SC_ScrollBarAddLine, widget ); if( horizontal ) { if( reverseLayout ) _helper->renderArrow( painter, rect, color, ArrowLeft ); else _helper->renderArrow( painter, rect.translated( 1, 0 ), color, ArrowRight ); } else _helper->renderArrow( painter, rect.translated( 0, 1 ), color, ArrowDown ); } return true; } //___________________________________________________________________________________ bool Style::drawScrollBarSubLineControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // do nothing if no buttons are set if( _subLineButtons == NoButton ) return true; // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; const State& state( option->state ); const bool horizontal( state & State_Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // colors const auto& palette( option->palette ); const auto background( palette.color( QPalette::Window ) ); // adjust rect, based on number of buttons to be drawn const auto rect( scrollBarInternalSubControlRect( sliderOption, SC_ScrollBarSubLine ) ); QColor color; QStyleOptionSlider copy( *sliderOption ); if( _subLineButtons == DoubleButton ) { if( horizontal ) { //Draw the arrows const QSize halfSize( rect.width()/2, rect.height() ); const QRect leftSubButton( rect.topLeft(), halfSize ); const QRect rightSubButton( leftSubButton.topRight() + QPoint( 1, 0 ), halfSize ); copy.rect = leftSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarAddLine:SC_ScrollBarSubLine, widget ); _helper->renderArrow( painter, leftSubButton, color, ArrowLeft ); copy.rect = rightSubButton; color = scrollBarArrowColor( ©, reverseLayout ? SC_ScrollBarSubLine:SC_ScrollBarAddLine, widget ); _helper->renderArrow( painter, rightSubButton, color, ArrowRight ); } else { const QSize halfSize( rect.width(), rect.height()/2 ); const QRect topSubButton( rect.topLeft(), halfSize ); const QRect botSubButton( topSubButton.bottomLeft() + QPoint( 0, 1 ), halfSize ); copy.rect = topSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarSubLine, widget ); _helper->renderArrow( painter, topSubButton, color, ArrowUp ); copy.rect = botSubButton; color = scrollBarArrowColor( ©, SC_ScrollBarAddLine, widget ); _helper->renderArrow( painter, botSubButton, color, ArrowDown ); } } else if( _subLineButtons == SingleButton ) { copy.rect = rect; color = scrollBarArrowColor( ©, SC_ScrollBarSubLine, widget ); if( horizontal ) { if( reverseLayout ) _helper->renderArrow( painter, rect.translated( 1, 0 ), color, ArrowRight ); else _helper->renderArrow( painter, rect, color, ArrowLeft ); } else _helper->renderArrow( painter, rect, color, ArrowUp ); } return true; } //___________________________________________________________________________________ bool Style::drawShapedFrameControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check #if BREEZE_USE_KDE4 const auto frameOpt = qstyleoption_cast( option ); #else const auto frameOpt = qstyleoption_cast( option ); #endif if( !frameOpt ) return false; switch( frameOpt->frameShape ) { case QFrame::Box: { if( option->state & State_Sunken ) return true; else break; } case QFrame::HLine: case QFrame::VLine: { const auto& rect( option->rect ); const auto color( _helper->separatorColor( option->palette ) ); const bool isVertical( frameOpt->frameShape == QFrame::VLine ); _helper->renderSeparator( painter, rect, color, isVertical ); return true; } case QFrame::StyledPanel: { if( isQtQuickControl( option, widget ) ) { // ComboBox popup frame drawFrameMenuPrimitive( option, painter, widget ); return true; } else break; } default: break; } return false; } //___________________________________________________________________________________ bool Style::drawRubberBandControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { const auto& palette( option->palette ); const auto rect( option->rect ); auto color = palette.color( QPalette::Highlight ); painter->setPen( KColorUtils::mix( color, palette.color( QPalette::Active, QPalette::WindowText ) ) ); color.setAlpha( 50 ); painter->setBrush( color ); painter->setClipRegion( rect ); painter->drawRect( rect.adjusted( 0, 0, -1, -1 ) ); return true; } //___________________________________________________________________________________ bool Style::drawHeaderSectionControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const auto& rect( option->rect ); const auto& palette( option->palette ); const auto& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool sunken( enabled && ( state & (State_On|State_Sunken) ) ); const auto headerOption( qstyleoption_cast( option ) ); if( !headerOption ) return true; const bool horizontal( headerOption->orientation == Qt::Horizontal ); const bool isFirst( horizontal && ( headerOption->position == QStyleOptionHeader::Beginning ) ); const bool isCorner( widget && widget->inherits( "QTableCornerButton" ) ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // update animation state _animations->headerViewEngine().updateState( widget, rect.topLeft(), mouseOver ); const bool animated( enabled && _animations->headerViewEngine().isAnimated( widget, rect.topLeft() ) ); const qreal opacity( _animations->headerViewEngine().opacity( widget, rect.topLeft() ) ); // fill const auto normal( palette.color( QPalette::Button ) ); const auto focus( KColorUtils::mix( normal, _helper->focusColor( palette ), 0.2 ) ); const auto hover( KColorUtils::mix( normal, _helper->hoverColor( palette ), 0.2 ) ); QColor color; if( sunken ) color = focus; else if( animated ) color = KColorUtils::mix( normal, hover, opacity ); else if( mouseOver ) color = hover; else color = normal; painter->setRenderHint( QPainter::Antialiasing, false ); painter->setBrush( color ); painter->setPen( Qt::NoPen ); painter->drawRect( rect ); // outline painter->setBrush( Qt::NoBrush ); painter->setPen( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.1 ) ); if( isCorner ) { if( reverseLayout ) painter->drawPoint( rect.bottomLeft() ); else painter->drawPoint( rect.bottomRight() ); } else if( horizontal ) { painter->drawLine( rect.bottomLeft(), rect.bottomRight() ); } else { if( reverseLayout ) painter->drawLine( rect.topLeft(), rect.bottomLeft() ); else painter->drawLine( rect.topRight(), rect.bottomRight() ); } // separators painter->setPen( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.2 ) ); if( horizontal ) { if( headerOption->section != 0 || isFirst ) { if( reverseLayout ) painter->drawLine( rect.topLeft(), rect.bottomLeft() - QPoint( 0, 1 ) ); else painter->drawLine( rect.topRight(), rect.bottomRight() - QPoint( 0, 1 ) ); } } else { if( reverseLayout ) painter->drawLine( rect.bottomLeft()+QPoint( 1, 0 ), rect.bottomRight() ); else painter->drawLine( rect.bottomLeft(), rect.bottomRight() - QPoint( 1, 0 ) ); } return true; } //___________________________________________________________________________________ bool Style::drawHeaderEmptyAreaControl( const QStyleOption* option, QPainter* painter, const QWidget* ) const { // use the same background as in drawHeaderPrimitive const auto& rect( option->rect ); auto palette( option->palette ); const bool horizontal( option->state & QStyle::State_Horizontal ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // fill painter->setRenderHint( QPainter::Antialiasing, false ); painter->setBrush( palette.color( QPalette::Button ) ); painter->setPen( Qt::NoPen ); painter->drawRect( rect ); // outline painter->setBrush( Qt::NoBrush ); painter->setPen( _helper->alphaColor( palette.color( QPalette::ButtonText ), 0.1 ) ); if( horizontal ) { painter->drawLine( rect.bottomLeft(), rect.bottomRight() ); } else { if( reverseLayout ) painter->drawLine( rect.topLeft(), rect.bottomLeft() ); else painter->drawLine( rect.topRight(), rect.bottomRight() ); } return true; } //___________________________________________________________________________________ bool Style::drawTabBarTabLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // call parent style method ParentStyleClass::drawControl( CE_TabBarTabLabel, option, painter, widget ); // store rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // check focus const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( state & State_Selected ); const bool hasFocus( enabled && selected && (state & State_HasFocus) ); // update mouse over animation state _animations->tabBarEngine().updateState( widget, rect.topLeft(), AnimationFocus, hasFocus ); const bool animated( enabled && selected && _animations->tabBarEngine().isAnimated( widget, rect.topLeft(), AnimationFocus ) ); const qreal opacity( _animations->tabBarEngine().opacity( widget, rect.topLeft(), AnimationFocus ) ); if( !( hasFocus || animated ) ) return true; // code is copied from QCommonStyle, but adds focus // cast option and check const auto tabOption( qstyleoption_cast(option) ); if( !tabOption || tabOption->text.isEmpty() ) return true; // tab option rect const bool verticalTabs( isVerticalTab( tabOption ) ); const int textFlags( Qt::AlignCenter | _mnemonics->textFlags() ); // text rect auto textRect( subElementRect(SE_TabBarTabText, option, widget) ); if( verticalTabs ) { // properly rotate painter painter->save(); int newX, newY, newRot; if( tabOption->shape == QTabBar::RoundedEast || tabOption->shape == QTabBar::TriangularEast) { newX = rect.width() + rect.x(); newY = rect.y(); newRot = 90; } else { newX = rect.x(); newY = rect.y() + rect.height(); newRot = -90; } QTransform transform; transform.translate( newX, newY ); transform.rotate(newRot); painter->setTransform( transform, true ); } // adjust text rect based on font metrics textRect = option->fontMetrics.boundingRect( textRect, textFlags, tabOption->text ); // focus color QColor focusColor; if( animated ) focusColor = _helper->alphaColor( _helper->focusColor( palette ), opacity ); else if( hasFocus ) focusColor = _helper->focusColor( palette ); // render focus line _helper->renderFocusLine( painter, textRect, focusColor ); if( verticalTabs ) painter->restore(); return true; } //___________________________________________________________________________________ bool Style::drawTabBarTabShapeControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { const auto tabOption( qstyleoption_cast( option ) ); if( !tabOption ) return true; // palette and state const auto& palette( option->palette ); const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( state & State_Selected ); const bool mouseOver( enabled && !selected && ( state & State_MouseOver ) ); // check if tab is being dragged const bool isDragged( widget && selected && painter->device() != widget ); const bool isLocked( widget && _tabBarData->isLocked( widget ) ); // store rect auto rect( option->rect ); // update mouse over animation state _animations->tabBarEngine().updateState( widget, rect.topLeft(), AnimationHover, mouseOver ); const bool animated( enabled && !selected && _animations->tabBarEngine().isAnimated( widget, rect.topLeft(), AnimationHover ) ); const qreal opacity( _animations->tabBarEngine().opacity( widget, rect.topLeft(), AnimationHover ) ); // lock state if( selected && widget && isDragged ) _tabBarData->lock( widget ); else if( widget && selected && _tabBarData->isLocked( widget ) ) _tabBarData->release(); // tab position const QStyleOptionTab::TabPosition& position = tabOption->position; const bool isSingle( position == QStyleOptionTab::OnlyOneTab ); const bool isQtQuickControl( this->isQtQuickControl( option, widget ) ); bool isFirst( isSingle || position == QStyleOptionTab::Beginning ); bool isLast( isSingle || position == QStyleOptionTab::End ); bool isLeftOfSelected( !isLocked && tabOption->selectedPosition == QStyleOptionTab::NextIsSelected ); bool isRightOfSelected( !isLocked && tabOption->selectedPosition == QStyleOptionTab::PreviousIsSelected ); // 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 isFirst &= !isRightOfSelected; isLast &= !isLeftOfSelected; // swap state based on reverse layout, so that they become layout independent const bool reverseLayout( option->direction == Qt::RightToLeft ); const bool verticalTabs( isVerticalTab( tabOption ) ); if( reverseLayout && !verticalTabs ) { qSwap( isFirst, isLast ); qSwap( isLeftOfSelected, isRightOfSelected ); } // overlap // for QtQuickControls, ovelap is already accounted of in the option. Unlike in the qwidget case const int overlap( isQtQuickControl ? 0:Metrics::TabBar_TabOverlap ); // adjust rect and define corners based on tabbar orientation Corners corners; switch( tabOption->shape ) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: if( selected ) { corners = CornerTopLeft|CornerTopRight; rect.adjust( 0, 0, 0, 1 ); } else { rect.adjust( 0, 0, 0, -1 ); if( isFirst ) corners |= CornerTopLeft; if( isLast ) corners |= CornerTopRight; if( isRightOfSelected ) rect.adjust( -Metrics::Frame_FrameRadius, 0, 0, 0 ); if( isLeftOfSelected ) rect.adjust( 0, 0, Metrics::Frame_FrameRadius, 0 ); else if( !isLast ) rect.adjust( 0, 0, overlap, 0 ); } break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: if( selected ) { corners = CornerBottomLeft|CornerBottomRight; rect.adjust( 0, - 1, 0, 0 ); } else { rect.adjust( 0, 1, 0, 0 ); if( isFirst ) corners |= CornerBottomLeft; if( isLast ) corners |= CornerBottomRight; if( isRightOfSelected ) rect.adjust( -Metrics::Frame_FrameRadius, 0, 0, 0 ); if( isLeftOfSelected ) rect.adjust( 0, 0, Metrics::Frame_FrameRadius, 0 ); else if( !isLast ) rect.adjust( 0, 0, overlap, 0 ); } break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: if( selected ) { corners = CornerTopLeft|CornerBottomLeft; rect.adjust( 0, 0, 1, 0 ); } else { rect.adjust( 0, 0, -1, 0 ); if( isFirst ) corners |= CornerTopLeft; if( isLast ) corners |= CornerBottomLeft; if( isRightOfSelected ) rect.adjust( 0, -Metrics::Frame_FrameRadius, 0, 0 ); if( isLeftOfSelected ) rect.adjust( 0, 0, 0, Metrics::Frame_FrameRadius ); else if( !isLast ) rect.adjust( 0, 0, 0, overlap ); } break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: if( selected ) { corners = CornerTopRight|CornerBottomRight; rect.adjust( -1, 0, 0, 0 ); } else { rect.adjust( 1, 0, 0, 0 ); if( isFirst ) corners |= CornerTopRight; if( isLast ) corners |= CornerBottomRight; if( isRightOfSelected ) rect.adjust( 0, -Metrics::Frame_FrameRadius, 0, 0 ); if( isLeftOfSelected ) rect.adjust( 0, 0, 0, Metrics::Frame_FrameRadius ); else if( !isLast ) rect.adjust( 0, 0, 0, overlap ); } break; default: break; } // color QColor color; if( selected ) { #if QT_VERSION >= 0x050000 bool documentMode = tabOption->documentMode; #else bool documentMode = false; if( const auto tabOptionV3 = qstyleoption_cast( option ) ) { documentMode = tabOptionV3->documentMode; } #endif // flag passed to QStyleOptionTab is unfortunately not reliable enough // also need to check on parent widget const auto tabWidget = ( widget && widget->parentWidget() ) ? qobject_cast( widget->parentWidget() ) : nullptr; documentMode |= ( tabWidget ? tabWidget->documentMode() : true ); color = (documentMode&&!isQtQuickControl&&!hasAlteredBackground(widget)) ? palette.color( QPalette::Window ) : _helper->frameBackgroundColor( palette ); } else { const auto normal( _helper->alphaColor( palette.color( QPalette::Shadow ), 0.2 ) ); const auto hover( _helper->alphaColor( _helper->hoverColor( palette ), 0.2 ) ); if( animated ) color = KColorUtils::mix( normal, hover, opacity ); else if( mouseOver ) color = hover; else color = normal; } // outline const auto outline( selected ? _helper->alphaColor( palette.color( QPalette::WindowText ), 0.25 ) : QColor() ); // render if( selected ) { QRegion oldRegion( painter->clipRegion() ); painter->setClipRect( option->rect, Qt::IntersectClip ); _helper->renderTabBarTab( painter, rect, color, outline, corners ); painter->setClipRegion( oldRegion ); } else { _helper->renderTabBarTab( painter, rect, color, outline, corners ); } return true; } //___________________________________________________________________________________ bool Style::drawToolBoxTabLabelControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // rendering is similar to drawPushButtonLabelControl // cast option and check const auto toolBoxOption( qstyleoption_cast( option ) ); if( !toolBoxOption ) return true; // copy palette const auto& palette( option->palette ); const State& state( option->state ); const bool enabled( state & State_Enabled ); // text alignment const int textFlags( _mnemonics->textFlags() | Qt::AlignCenter ); // contents rect const auto rect( subElementRect( SE_ToolBoxTabContents, option, widget ) ); // store icon size const int iconSize( pixelMetric( QStyle::PM_SmallIconSize, option, widget ) ); // find contents size and rect auto contentsRect( rect ); QSize contentsSize; if( !toolBoxOption->text.isEmpty() ) { contentsSize = option->fontMetrics.size( _mnemonics->textFlags(), toolBoxOption->text ); if( !toolBoxOption->icon.isNull() ) contentsSize.rwidth() += Metrics::ToolBox_TabItemSpacing; } // icon size if( !toolBoxOption->icon.isNull() ) { contentsSize.setHeight( qMax( contentsSize.height(), iconSize ) ); contentsSize.rwidth() += iconSize; } // adjust contents rect contentsRect = centerRect( contentsRect, contentsSize ); // render icon if( !toolBoxOption->icon.isNull() ) { // icon rect QRect iconRect; if( toolBoxOption->text.isEmpty() ) iconRect = centerRect( contentsRect, iconSize, iconSize ); else { iconRect = contentsRect; iconRect.setWidth( iconSize ); iconRect = centerRect( iconRect, iconSize, iconSize ); contentsRect.setLeft( iconRect.right() + Metrics::ToolBox_TabItemSpacing + 1 ); } iconRect = visualRect( option, iconRect ); const QIcon::Mode mode( enabled ? QIcon::Normal : QIcon::Disabled ); const QPixmap pixmap( toolBoxOption->icon.pixmap( iconSize, mode ) ); drawItemPixmap( painter, iconRect, textFlags, pixmap ); } // render text if( !toolBoxOption->text.isEmpty() ) { contentsRect = visualRect( option, contentsRect ); drawItemText( painter, contentsRect, textFlags, palette, enabled, toolBoxOption->text, QPalette::WindowText ); } return true; } //___________________________________________________________________________________ bool Style::drawToolBoxTabShapeControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto toolBoxOption( qstyleoption_cast( option ) ); if( !toolBoxOption ) return true; // copy rect and palette const auto& rect( option->rect ); const auto tabRect( toolBoxTabContentsRect( option, widget ) ); /* * important: option returns the wrong palette. * we use the widget palette instead, when set */ const auto& palette( widget ? widget->palette() : option->palette ); // store flags 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 ) ); // update animation state /* * the proper widget ( the toolbox tab ) is not passed as argument by Qt. * What is passed is the toolbox directly. To implement animations properly, *the painter->device() is used instead */ bool isAnimated( false ); qreal opacity( AnimationData::OpacityInvalid ); QPaintDevice* device = painter->device(); if( enabled && device ) { _animations->toolBoxEngine().updateState( device, mouseOver ); isAnimated = _animations->toolBoxEngine().isAnimated( device ); opacity = _animations->toolBoxEngine().opacity( device ); } // color QColor outline; if( selected ) outline = _helper->focusColor( palette ); else outline = _helper->frameOutlineColor( palette, mouseOver, false, opacity, isAnimated ? AnimationHover:AnimationNone ); // render _helper->renderToolBoxFrame( painter, rect, tabRect.width(), outline ); return true; } //___________________________________________________________________________________ bool Style::drawDockWidgetTitleControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto dockWidgetOption = qstyleoption_cast( option ); if( !dockWidgetOption ) return true; const auto& palette( option->palette ); const auto& state( option->state ); const bool enabled( state & State_Enabled ); const bool reverseLayout( option->direction == Qt::RightToLeft ); // cast to v2 to check vertical bar #if BREEZE_USE_KDE4 const auto v2 = qstyleoption_cast( option ); const bool verticalTitleBar( v2 ? v2->verticalTitleBar : false ); #else const bool verticalTitleBar( dockWidgetOption->verticalTitleBar ); #endif const auto buttonRect( subElementRect( dockWidgetOption->floatable ? SE_DockWidgetFloatButton : SE_DockWidgetCloseButton, option, widget ) ); // get rectangle and adjust to properly accounts for buttons auto rect( insideMargin( dockWidgetOption->rect, Metrics::Frame_FrameWidth ) ); if( verticalTitleBar ) { if( buttonRect.isValid() ) rect.setTop( buttonRect.bottom() + 1 ); } else if( reverseLayout ) { if( buttonRect.isValid() ) rect.setLeft( buttonRect.right() + 1 ); rect.adjust( 0, 0, -4, 0 ); } else { if( buttonRect.isValid() ) rect.setRight( buttonRect.left() - 1 ); rect.adjust( 4, 0, 0, 0 ); } QString title( dockWidgetOption->title ); int titleWidth = dockWidgetOption->fontMetrics.size( _mnemonics->textFlags(), title ).width(); int width = verticalTitleBar ? rect.height() : rect.width(); if( width < titleWidth ) title = dockWidgetOption->fontMetrics.elidedText( title, Qt::ElideRight, width, Qt::TextShowMnemonic ); if( verticalTitleBar ) { QSize size = rect.size(); size.transpose(); rect.setSize( size ); painter->save(); painter->translate( rect.left(), rect.top() + rect.width() ); painter->rotate( -90 ); painter->translate( -rect.left(), -rect.top() ); drawItemText( painter, rect, Qt::AlignLeft | Qt::AlignVCenter | _mnemonics->textFlags(), palette, enabled, title, QPalette::WindowText ); painter->restore(); } else { drawItemText( painter, rect, Qt::AlignLeft | Qt::AlignVCenter | _mnemonics->textFlags(), palette, enabled, title, QPalette::WindowText ); } return true; } //______________________________________________________________ bool Style::drawGroupBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // base class method ParentStyleClass::drawComplexControl( CC_GroupBox, option, painter, widget ); // cast option and check const auto groupBoxOption = qstyleoption_cast( option ); if( !groupBoxOption ) return true; // do nothing if either label is not selected or groupbox is empty if( !(option->subControls & QStyle::SC_GroupBoxLabel) || groupBoxOption->text.isEmpty() ) { return true; } // store palette and rect const auto& palette( option->palette ); // check focus state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool hasFocus( enabled && (option->state & State_HasFocus) ); if( !hasFocus ) return true; // alignment const int textFlags( groupBoxOption->textAlignment | _mnemonics->textFlags() ); // update animation state _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus ); const bool isFocusAnimated( _animations->widgetStateEngine().isAnimated( widget, AnimationFocus ) ); const qreal opacity( _animations->widgetStateEngine().opacity( widget, AnimationFocus ) ); // get relevant rect auto textRect = subControlRect( CC_GroupBox, option, SC_GroupBoxLabel, widget ); textRect = option->fontMetrics.boundingRect( textRect, textFlags, groupBoxOption->text ); // focus color QColor focusColor; if( isFocusAnimated ) focusColor = _helper->alphaColor( _helper->focusColor( palette ), opacity ); else if( hasFocus ) focusColor = _helper->focusColor( palette ); // render focus _helper->renderFocusLine( painter, textRect, focusColor ); return true; } //______________________________________________________________ bool Style::drawToolButtonComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto toolButtonOption( qstyleoption_cast( option ) ); if( !toolButtonOption ) return true; // need to alter palette for focused buttons const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && (option->state & State_MouseOver) ); const bool hasFocus( enabled && (option->state & State_HasFocus) ); const bool sunken( state & (State_On | State_Sunken) ); const bool flat( state & State_AutoRaise ); // update animation state // mouse over takes precedence over focus _animations->widgetStateEngine().updateState( widget, AnimationHover, mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); // detect buttons in tabbar, for which special rendering is needed const bool inTabBar( widget && qobject_cast( widget->parentWidget() ) ); const bool isMenuTitle( this->isMenuTitle( widget ) ); if( isMenuTitle ) { // copy option to adust state, and set font as not-bold QStyleOptionToolButton copy( *toolButtonOption ); copy.font.setBold( false ); copy.state = State_Enabled; // render renderMenuTitle( ©, painter, widget ); return true; } // copy option and alter palette QStyleOptionToolButton copy( *toolButtonOption ); const bool hasPopupMenu( toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup ); const bool hasInlineIndicator( toolButtonOption->features&QStyleOptionToolButton::HasMenu && toolButtonOption->features&QStyleOptionToolButton::PopupDelay && !hasPopupMenu ); const auto buttonRect( subControlRect( CC_ToolButton, option, SC_ToolButton, widget ) ); const auto menuRect( subControlRect( CC_ToolButton, option, SC_ToolButtonMenu, widget ) ); // frame if( toolButtonOption->subControls & SC_ToolButton ) { if( inTabBar ) drawTabBarPanelButtonToolPrimitive( ©, painter, widget ); else drawPrimitive( PE_PanelButtonTool, ©, painter, widget); } // arrow if( hasPopupMenu ) { copy.rect = menuRect; if( !flat ) drawPrimitive( PE_IndicatorButtonDropDown, ©, painter, widget ); if( sunken && !flat ) copy.rect.translate( 1, 1 ); drawPrimitive( PE_IndicatorArrowDown, ©, painter, widget ); } else if( hasInlineIndicator ) { copy.rect = menuRect; if( sunken && !flat ) copy.rect.translate( 1, 1 ); drawPrimitive( PE_IndicatorArrowDown, ©, painter, widget ); } // contents { // restore state copy.state = state; // define contents rect auto contentsRect( buttonRect ); // detect dock widget title button // for dockwidget title buttons, do not take out margins, so that icon do not get scaled down const bool isDockWidgetTitleButton( widget && widget->inherits( "QDockWidgetTitleButton" ) ); if( isDockWidgetTitleButton ) { // cast to abstract button // adjust state to have correct icon rendered const auto button( qobject_cast( widget ) ); if( button->isChecked() || button->isDown() ) copy.state |= State_On; } else if( !inTabBar && hasInlineIndicator ) { const int marginWidth( flat ? Metrics::ToolButton_MarginWidth : Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth ); contentsRect = insideMargin( contentsRect, marginWidth, 0 ); contentsRect.setRight( contentsRect.right() - Metrics::ToolButton_InlineIndicatorWidth ); contentsRect = visualRect( option, contentsRect ); } copy.rect = contentsRect; // render drawControl( CE_ToolButtonLabel, ©, painter, widget); } return true; } //______________________________________________________________ bool Style::drawComboBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto comboBoxOption( qstyleoption_cast( option ) ); if( !comboBoxOption ) return true; // rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & (State_HasFocus | State_Sunken ) ) ); const bool editable( comboBoxOption->editable ); const bool sunken( state & (State_On|State_Sunken) ); bool flat( !comboBoxOption->frame ); // frame if( option->subControls & SC_ComboBoxFrame ) { if( editable ) { flat |= ( rect.height() <= 2*Metrics::Frame_FrameWidth + Metrics::MenuButton_IndicatorWidth ); if( flat ) { const auto background( palette.color( QPalette::Base ) ); painter->setBrush( background ); painter->setPen( Qt::NoPen ); painter->drawRect( rect ); } else { drawPrimitive( PE_FrameLineEdit, option, painter, widget ); } } else { // update animation state // hover takes precedence over focus _animations->inputWidgetEngine().updateState( widget, AnimationHover, mouseOver ); _animations->inputWidgetEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver ); const AnimationMode mode( _animations->inputWidgetEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->inputWidgetEngine().buttonOpacity( widget ) ); if( flat ) { // define colors and render const auto color( _helper->toolButtonColor( palette, mouseOver, hasFocus, sunken, opacity, mode ) ); _helper->renderToolButtonFrame( painter, rect, color, sunken ); } else { // define colors const auto shadow( _helper->shadowColor( palette ) ); const auto outline( _helper->buttonOutlineColor( palette, mouseOver, hasFocus, opacity, mode ) ); const auto background( _helper->buttonBackgroundColor( palette, mouseOver, hasFocus, false, opacity, mode ) ); // render _helper->renderButtonFrame( painter, rect, background, outline, shadow, hasFocus, sunken ); } } } // arrow if( option->subControls & SC_ComboBoxArrow ) { // detect empty comboboxes const auto comboBox = qobject_cast( widget ); const bool empty( comboBox && !comboBox->count() ); // arrow color QColor arrowColor; if( editable ) { if( empty || !enabled ) arrowColor = palette.color( QPalette::Disabled, QPalette::Text ); else { // check animation state const bool subControlHover( enabled && mouseOver && comboBoxOption->activeSubControls&SC_ComboBoxArrow ); _animations->comboBoxEngine().updateState( widget, AnimationHover, subControlHover ); const bool animated( enabled && _animations->comboBoxEngine().isAnimated( widget, AnimationHover ) ); const qreal opacity( _animations->comboBoxEngine().opacity( widget, AnimationHover ) ); // color const auto normal( _helper->arrowColor( palette, QPalette::WindowText ) ); const auto hover( _helper->hoverColor( palette ) ); if( animated ) { arrowColor = KColorUtils::mix( normal, hover, opacity ); } else if( subControlHover ) { arrowColor = hover; } else arrowColor = normal; } } else if( flat ) { if( empty || !enabled ) arrowColor = _helper->arrowColor( palette, QPalette::Disabled, QPalette::WindowText ); else if( hasFocus && !mouseOver && sunken ) arrowColor = palette.color( QPalette::HighlightedText ); else arrowColor = _helper->arrowColor( palette, QPalette::WindowText ); } else if( empty || !enabled ) arrowColor = _helper->arrowColor( palette, QPalette::Disabled, QPalette::ButtonText ); else if( hasFocus && !mouseOver ) arrowColor = palette.color( QPalette::HighlightedText ); else arrowColor = _helper->arrowColor( palette, QPalette::ButtonText ); // arrow rect auto arrowRect( subControlRect( CC_ComboBox, option, SC_ComboBoxArrow, widget ) ); // translate for non editable, non flat, sunken comboboxes if( sunken && !flat && !editable ) arrowRect.translate( 1, 1 ); // render _helper->renderArrow( painter, arrowRect, arrowColor, ArrowDown ); } return true; } //______________________________________________________________ bool Style::drawSpinBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { const auto spinBoxOption( qstyleoption_cast( option ) ); if( !spinBoxOption ) return true; // store palette and rect const auto& palette( option->palette ); const auto& rect( option->rect ); if( option->subControls & SC_SpinBoxFrame ) { // detect flat spinboxes bool flat( !spinBoxOption->frame ); flat |= ( rect.height() < 2*Metrics::Frame_FrameWidth + Metrics::SpinBox_ArrowButtonWidth ); if( flat ) { const auto background( palette.color( QPalette::Base ) ); painter->setBrush( background ); painter->setPen( Qt::NoPen ); painter->drawRect( rect ); } else { drawPrimitive( PE_FrameLineEdit, option, painter, widget ); } } if( option->subControls & SC_SpinBoxUp ) renderSpinBoxArrow( SC_SpinBoxUp, spinBoxOption, painter, widget ); if( option->subControls & SC_SpinBoxDown ) renderSpinBoxArrow( SC_SpinBoxDown, spinBoxOption, painter, widget ); return true; } //______________________________________________________________ bool Style::drawSliderComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; // copy rect and palette const auto& rect( option->rect ); const auto& palette( option->palette ); // copy state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); // direction const bool horizontal( sliderOption->orientation == Qt::Horizontal ); // tickmarks if( StyleConfigData::sliderDrawTickMarks() && ( sliderOption->subControls & SC_SliderTickmarks ) ) { const bool upsideDown( sliderOption->upsideDown ); const int tickPosition( sliderOption->tickPosition ); const int available( pixelMetric( PM_SliderSpaceAvailable, option, widget ) ); int interval = sliderOption->tickInterval; if( interval < 1 ) interval = sliderOption->pageStep; if( interval >= 1 ) { const int fudge( pixelMetric( PM_SliderLength, option, widget ) / 2 ); int current( sliderOption->minimum ); // store tick lines const auto grooveRect( subControlRect( CC_Slider, sliderOption, SC_SliderGroove, widget ) ); QList tickLines; if( horizontal ) { if( tickPosition & QSlider::TicksAbove ) tickLines.append( QLine( rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength ) ); if( tickPosition & QSlider::TicksBelow ) tickLines.append( QLine( rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength ) ); } else { if( tickPosition & QSlider::TicksAbove ) tickLines.append( QLine( grooveRect.left() - Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.left() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength, rect.top() ) ); if( tickPosition & QSlider::TicksBelow ) tickLines.append( QLine( grooveRect.right() + Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.right() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength, rect.top() ) ); } // colors const auto base( _helper->separatorColor( palette ) ); const auto highlight( palette.color( QPalette::Highlight ) ); while( current <= sliderOption->maximum ) { // adjust color const auto color( (enabled && current <= sliderOption->sliderPosition) ? highlight:base ); painter->setPen( color ); // calculate positions and draw lines int position( sliderPositionFromValue( sliderOption->minimum, sliderOption->maximum, current, available ) + fudge ); foreach( const QLine& tickLine, tickLines ) { if( horizontal ) painter->drawLine( tickLine.translated( upsideDown ? (rect.width() - position) : position, 0 ) ); else painter->drawLine( tickLine.translated( 0, upsideDown ? (rect.height() - position):position ) ); } // go to next position current += interval; } } } // groove if( sliderOption->subControls & SC_SliderGroove ) { // retrieve groove rect auto grooveRect( subControlRect( CC_Slider, sliderOption, SC_SliderGroove, widget ) ); // base color const auto grooveColor( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.3 ) ); if( !enabled ) _helper->renderSliderGroove( painter, grooveRect, grooveColor ); else { const bool upsideDown( sliderOption->upsideDown ); // handle rect auto handleRect( subControlRect( CC_Slider, sliderOption, SC_SliderHandle, widget ) ); // highlight color const auto highlight( palette.color( QPalette::Highlight ) ); if( sliderOption->orientation == Qt::Horizontal ) { auto leftRect( grooveRect ); leftRect.setRight( handleRect.right() - Metrics::Slider_ControlThickness/2 ); _helper->renderSliderGroove( painter, leftRect, upsideDown ? grooveColor:highlight ); auto rightRect( grooveRect ); rightRect.setLeft( handleRect.left() + Metrics::Slider_ControlThickness/2 ); _helper->renderSliderGroove( painter, rightRect, upsideDown ? highlight:grooveColor ); } else { auto topRect( grooveRect ); topRect.setBottom( handleRect.bottom() - Metrics::Slider_ControlThickness/2 ); _helper->renderSliderGroove( painter, topRect, upsideDown ? grooveColor:highlight ); auto bottomRect( grooveRect ); bottomRect.setTop( handleRect.top() + Metrics::Slider_ControlThickness/2 ); _helper->renderSliderGroove( painter, bottomRect, upsideDown ? highlight:grooveColor ); } } } // handle if( sliderOption->subControls & SC_SliderHandle ) { // get rect and center auto handleRect( subControlRect( CC_Slider, sliderOption, SC_SliderHandle, widget ) ); // handle state const bool handleActive( sliderOption->activeSubControls & SC_SliderHandle ); const bool sunken( state & (State_On|State_Sunken) ); // animation state _animations->widgetStateEngine().updateState( widget, AnimationHover, handleActive && mouseOver ); _animations->widgetStateEngine().updateState( widget, AnimationFocus, hasFocus ); const AnimationMode mode( _animations->widgetStateEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->widgetStateEngine().buttonOpacity( widget ) ); // define colors const auto background( palette.color( QPalette::Button ) ); const auto outline( _helper->sliderOutlineColor( palette, handleActive && mouseOver, hasFocus, opacity, mode ) ); const auto shadow( _helper->shadowColor( palette ) ); // render _helper->renderSliderHandle( painter, handleRect, background, outline, shadow, sunken ); } return true; } //______________________________________________________________ bool Style::drawDialComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto sliderOption( qstyleoption_cast( option ) ); if( !sliderOption ) return true; const auto& palette( option->palette ); const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool mouseOver( enabled && ( state & State_MouseOver ) ); const bool hasFocus( enabled && ( state & State_HasFocus ) ); // do not render tickmarks if( sliderOption->subControls & SC_DialTickmarks ) {} // groove if( sliderOption->subControls & SC_DialGroove ) { // groove rect auto grooveRect( subControlRect( CC_Dial, sliderOption, SC_SliderGroove, widget ) ); // groove const auto grooveColor( KColorUtils::mix( palette.color( QPalette::Window ), palette.color( QPalette::WindowText ), 0.3 ) ); // render groove _helper->renderDialGroove( painter, grooveRect, grooveColor ); if( enabled ) { // highlight const auto highlight( palette.color( QPalette::Highlight ) ); // angles const qreal first( dialAngle( sliderOption, sliderOption->minimum ) ); const qreal second( dialAngle( sliderOption, sliderOption->sliderPosition ) ); // render contents _helper->renderDialContents( painter, grooveRect, highlight, first, second ); } } // handle if( sliderOption->subControls & SC_DialHandle ) { // get handle rect auto handleRect( subControlRect( CC_Dial, sliderOption, SC_DialHandle, widget ) ); handleRect = centerRect( handleRect, Metrics::Slider_ControlThickness, Metrics::Slider_ControlThickness ); // handle state const bool handleActive( mouseOver && handleRect.contains( _animations->dialEngine().position( widget ) ) ); const bool sunken( state & (State_On|State_Sunken) ); // animation state _animations->dialEngine().setHandleRect( widget, handleRect ); _animations->dialEngine().updateState( widget, AnimationHover, handleActive && mouseOver ); _animations->dialEngine().updateState( widget, AnimationFocus, hasFocus ); const auto mode( _animations->dialEngine().buttonAnimationMode( widget ) ); const qreal opacity( _animations->dialEngine().buttonOpacity( widget ) ); // define colors const auto background( palette.color( QPalette::Button ) ); const auto outline( _helper->sliderOutlineColor( palette, handleActive && mouseOver, hasFocus, opacity, mode ) ); const auto shadow( _helper->shadowColor( palette ) ); // render _helper->renderSliderHandle( painter, handleRect, background, outline, shadow, sunken ); } return true; } //______________________________________________________________ bool Style::drawScrollBarComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { //the animation for QStyle::SC_ScrollBarGroove is special: it will animate //the opacity of everything else as well, included slider and arrows qreal opacity( _animations->scrollBarEngine().opacity( widget, QStyle::SC_ScrollBarGroove ) ); const bool animated( StyleConfigData::animationsEnabled() && _animations->scrollBarEngine().isAnimated( widget, AnimationHover, QStyle::SC_ScrollBarGroove ) ); const bool mouseOver( option->state & State_MouseOver ); if( opacity == AnimationData::OpacityInvalid ) opacity = 1; // render full groove directly, rather than using the addPage and subPage control element methods if( (!StyleConfigData::animationsEnabled() || mouseOver || animated) && option->subControls & SC_ScrollBarGroove ) { // retrieve groove rectangle auto grooveRect( subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget ) ); const auto& palette( option->palette ); const auto color( _helper->alphaColor( palette.color( QPalette::WindowText ), 0.3 * (animated ? opacity : 1) ) ); const auto& state( option->state ); const bool horizontal( state & State_Horizontal ); if( horizontal ) grooveRect = centerRect( grooveRect, grooveRect.width(), Metrics::ScrollBar_SliderWidth ); else grooveRect = centerRect( grooveRect, Metrics::ScrollBar_SliderWidth, grooveRect.height() ); // render _helper->renderScrollBarGroove( painter, grooveRect, color ); } // call base class primitive ParentStyleClass::drawComplexControl( CC_ScrollBar, option, painter, widget ); return true; } //______________________________________________________________ bool Style::drawTitleBarComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const { // cast option and check const auto titleBarOption( qstyleoption_cast( option ) ); if( !titleBarOption ) return true; // store palette and rect auto palette( option->palette ); const auto& rect( option->rect ); const State& flags( option->state ); const bool enabled( flags & State_Enabled ); const bool active( enabled && ( titleBarOption->titleBarState & Qt::WindowActive ) ); if( titleBarOption->subControls & SC_TitleBarLabel ) { // render background painter->setClipRect( rect ); const auto outline( active ? QColor():_helper->frameOutlineColor( palette, false, false ) ); const auto background( _helper->titleBarColor( active ) ); _helper->renderTabWidgetFrame( painter, rect.adjusted( -1, -1, 1, 3 ), background, outline, CornersTop ); const bool useSeparator( active && _helper->titleBarColor( active ) != palette.color( QPalette::Window ) && !( titleBarOption->titleBarState & Qt::WindowMinimized ) ); if( useSeparator ) { painter->setRenderHint( QPainter::Antialiasing, false ); painter->setBrush( Qt::NoBrush ); painter->setPen( palette.color( QPalette::Highlight ) ); painter->drawLine( rect.bottomLeft(), rect.bottomRight() ); } // render text palette.setColor( QPalette::WindowText, _helper->titleBarTextColor( active ) ); const auto textRect( subControlRect( CC_TitleBar, option, SC_TitleBarLabel, widget ) ); ParentStyleClass::drawItemText( painter, textRect, Qt::AlignCenter, palette, active, titleBarOption->text, QPalette::WindowText ); } // buttons static const QList subControls = { SC_TitleBarMinButton, SC_TitleBarMaxButton, SC_TitleBarCloseButton, SC_TitleBarNormalButton, SC_TitleBarSysMenu }; // loop over supported buttons foreach( const SubControl& subControl, subControls ) { // skip if not requested if( !( titleBarOption->subControls & subControl ) ) continue; // find matching icon QIcon icon; switch( subControl ) { case SC_TitleBarMinButton: icon = standardIcon( SP_TitleBarMinButton, option, widget ); break; case SC_TitleBarMaxButton: icon = standardIcon( SP_TitleBarMaxButton, option, widget ); break; case SC_TitleBarCloseButton: icon = standardIcon( SP_TitleBarCloseButton, option, widget ); break; case SC_TitleBarNormalButton: icon = standardIcon( SP_TitleBarNormalButton, option, widget ); break; case SC_TitleBarSysMenu: icon = titleBarOption->icon; break; default: break; } // check icon if( icon.isNull() ) continue; // define icon rect auto iconRect( subControlRect( CC_TitleBar, option, subControl, widget ) ); if( iconRect.isEmpty() ) continue; // active state const bool subControlActive( titleBarOption->activeSubControls & subControl ); // mouse over state const bool mouseOver( !subControlActive && widget && iconRect.translated( widget->mapToGlobal( QPoint( 0,0 ) ) ).contains( QCursor::pos() ) ); // adjust iconRect const int iconWidth( pixelMetric( PM_SmallIconSize, option, widget ) ); const QSize iconSize( iconWidth, iconWidth ); iconRect = centerRect( iconRect, iconSize ); // set icon mode and state QIcon::Mode iconMode; QIcon::State iconState; if( !enabled ) { iconMode = QIcon::Disabled; iconState = QIcon::Off; } else { if( mouseOver ) iconMode = QIcon::Active; else if( active ) iconMode = QIcon::Selected; else iconMode = QIcon::Normal; iconState = subControlActive ? QIcon::On : QIcon::Off; } // get pixmap and render const QPixmap pixmap = icon.pixmap( iconSize, iconMode, iconState ); painter->drawPixmap( iconRect, pixmap ); } return true; } //____________________________________________________________________________________________________ void Style::renderSpinBoxArrow( const SubControl& subControl, const QStyleOptionSpinBox* option, QPainter* painter, const QWidget* widget ) const { const auto& palette( option->palette ); const State& state( option->state ); // enable state bool enabled( state & State_Enabled ); // check steps enable step const bool atLimit( (subControl == SC_SpinBoxUp && !(option->stepEnabled & QAbstractSpinBox::StepUpEnabled )) || (subControl == SC_SpinBoxDown && !(option->stepEnabled & QAbstractSpinBox::StepDownEnabled ) ) ); // update enabled state accordingly enabled &= !atLimit; // update mouse-over effect const bool mouseOver( enabled && ( state & State_MouseOver ) ); // check animation state const bool subControlHover( enabled && mouseOver && ( option->activeSubControls & subControl ) ); _animations->spinBoxEngine().updateState( widget, subControl, subControlHover ); const bool animated( enabled && _animations->spinBoxEngine().isAnimated( widget, subControl ) ); const qreal opacity( _animations->spinBoxEngine().opacity( widget, subControl ) ); auto color = _helper->arrowColor( palette, QPalette::Text ); if( animated ) { auto highlight = _helper->hoverColor( palette ); color = KColorUtils::mix( color, highlight, opacity ); } else if( subControlHover ) { color = _helper->hoverColor( palette ); } else if( atLimit ) { color = _helper->arrowColor( palette, QPalette::Disabled, QPalette::Text ); } // arrow orientation ArrowOrientation orientation( ( subControl == SC_SpinBoxUp ) ? ArrowUp:ArrowDown ); // arrow rect const auto arrowRect( subControlRect( CC_SpinBox, option, subControl, widget ) ); // render _helper->renderArrow( painter, arrowRect, color, orientation ); } //______________________________________________________________________________ void Style::renderMenuTitle( const QStyleOptionToolButton* option, QPainter* painter, const QWidget* ) const { // render a separator at the bottom const auto& palette( option->palette ); const auto color( _helper->separatorColor( palette ) ); _helper->renderSeparator( painter, QRect( option->rect.bottomLeft()-QPoint( 0, Metrics::MenuItem_MarginHeight), QSize( option->rect.width(), 1 ) ), color ); // render text in the center of the rect // icon is discarded on purpose painter->setFont( option->font ); const auto contentsRect = insideMargin( option->rect, Metrics::MenuItem_MarginWidth, Metrics::MenuItem_MarginHeight ); drawItemText( painter, contentsRect, Qt::AlignCenter, palette, true, option->text, QPalette::WindowText ); } //______________________________________________________________________________ qreal Style::dialAngle( const QStyleOptionSlider* sliderOption, int value ) const { // calculate angle at which handle needs to be drawn qreal angle( 0 ); if( sliderOption->maximum == sliderOption->minimum ) angle = M_PI / 2; else { qreal fraction( qreal( value - sliderOption->minimum )/qreal( sliderOption->maximum - sliderOption->minimum ) ); if( !sliderOption->upsideDown ) fraction = 1 - fraction; if( sliderOption->dialWrapping ) angle = 1.5*M_PI - fraction*2*M_PI; else angle = ( M_PI*8 - fraction*10*M_PI )/6; } return angle; } //______________________________________________________________________________ const QWidget* Style::scrollBarParent( const QWidget* widget ) const { // check widget and parent if( !(widget && widget->parentWidget() ) ) return nullptr; // try cast to scroll area. Must test both parent and grandparent QAbstractScrollArea* scrollArea; if( !(scrollArea = qobject_cast( widget->parentWidget() ) ) ) { scrollArea = qobject_cast( widget->parentWidget()->parentWidget() ); } // check scrollarea if( scrollArea && (widget == scrollArea->verticalScrollBar() || widget == scrollArea->horizontalScrollBar() ) ) { return scrollArea; } else if( widget->parentWidget()->inherits( "KTextEditor::View" ) ) { return widget->parentWidget(); } else return nullptr; } //______________________________________________________________________________ QColor Style::scrollBarArrowColor( const QStyleOptionSlider* option, const SubControl& control, const QWidget* widget ) const { const auto& rect( option->rect ); const auto& palette( option->palette ); auto color( _helper->arrowColor( palette, QPalette::WindowText ) ); bool widgetMouseOver( ( option->state & State_MouseOver ) ); if( widget ) widgetMouseOver = widget->underMouse(); #if QT_VERSION >= 0x050000 // in case this QStyle is used by QQuickControls QStyle wrapper else if( option->styleObject ) widgetMouseOver = option->styleObject->property("hover").toBool(); #endif // check enabled state const bool enabled( option->state & State_Enabled ); if( !enabled ) { if( StyleConfigData::animationsEnabled() ) { // finally, global opacity when ScrollBarShowOnMouseOver const qreal globalOpacity( _animations->scrollBarEngine().opacity( widget, QStyle::SC_ScrollBarGroove ) ); if( globalOpacity >= 0 ) color.setAlphaF( globalOpacity ); // no mouse over and no animation in progress, don't draw arrows at all else if( !widgetMouseOver ) return Qt::transparent; } 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 color = _helper->arrowColor( palette, QPalette::Disabled, QPalette::WindowText ); if( StyleConfigData::animationsEnabled() ) { // finally, global opacity when ScrollBarShowOnMouseOver const qreal globalOpacity( _animations->scrollBarEngine().opacity( widget, QStyle::SC_ScrollBarGroove ) ); if( globalOpacity >= 0 ) color.setAlphaF( globalOpacity ); // no mouse over and no animation in progress, don't draw arrows at all else if( !widgetMouseOver ) return Qt::transparent; } return color; } const bool mouseOver( _animations->scrollBarEngine().isHovered( widget, control ) ); const bool animated( _animations->scrollBarEngine().isAnimated( widget, AnimationHover, control ) ); const qreal opacity( _animations->scrollBarEngine().opacity( widget, control ) ); // retrieve mouse position from engine QPoint position( mouseOver ? _animations->scrollBarEngine().position( widget ) : QPoint( -1, -1 ) ); if( mouseOver && rect.contains( position ) ) { /* * need to update the arrow controlRect on fly because there is no * way to get it from the styles directly, outside of repaint events */ _animations->scrollBarEngine().setSubControlRect( widget, control, rect ); } if( rect.intersects( _animations->scrollBarEngine().subControlRect( widget, control ) ) ) { auto highlight = _helper->hoverColor( palette ); if( animated ) { color = KColorUtils::mix( color, highlight, opacity ); } else if( mouseOver ) { color = highlight; } } if( StyleConfigData::animationsEnabled() ) { // finally, global opacity when ScrollBarShowOnMouseOver const qreal globalOpacity( _animations->scrollBarEngine().opacity( widget, QStyle::SC_ScrollBarGroove ) ); if( globalOpacity >= 0 ) color.setAlphaF( globalOpacity ); // no mouse over and no animation in progress, don't draw arrows at all else if( !widgetMouseOver ) return Qt::transparent; } return color; } //____________________________________________________________________________________ void Style::setTranslucentBackground( QWidget* widget ) const { widget->setAttribute( Qt::WA_TranslucentBackground ); #ifdef Q_WS_WIN // FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly widget->setWindowFlags( widget->windowFlags() | Qt::FramelessWindowHint ); #endif } //____________________________________________________________________________________ QStyleOptionToolButton Style::separatorMenuItemOption( const QStyleOptionMenuItem* menuItemOption, const QWidget* widget ) const { // separator can have a title and an icon // in that case they are rendered as sunken flat toolbuttons QStyleOptionToolButton toolButtonOption; toolButtonOption.initFrom( widget ); toolButtonOption.rect = menuItemOption->rect; toolButtonOption.features = QStyleOptionToolButton::None; toolButtonOption.state = State_Enabled|State_AutoRaise; toolButtonOption.subControls = SC_ToolButton; toolButtonOption.icon = QIcon(); toolButtonOption.iconSize = QSize(); toolButtonOption.text = menuItemOption->text; toolButtonOption.toolButtonStyle = Qt::ToolButtonTextBesideIcon; return toolButtonOption; } //____________________________________________________________________________________ QIcon Style::toolBarExtensionIcon( StandardPixmap standardPixmap, const QStyleOption* option, const QWidget* widget ) const { // store palette // due to Qt, it is not always safe to assume that either option, nor widget are defined QPalette palette; if( option ) palette = option->palette; else if( widget ) palette = widget->palette(); else palette = QApplication::palette(); // convenience class to map color to icon mode struct IconData { QColor _color; QIcon::Mode _mode; QIcon::State _state; }; // map colors to icon states const QList iconTypes = { { palette.color( QPalette::Active, QPalette::WindowText ), QIcon::Normal, QIcon::Off }, { palette.color( QPalette::Active, QPalette::WindowText ), QIcon::Selected, QIcon::Off }, { palette.color( QPalette::Active, QPalette::WindowText ), QIcon::Active, QIcon::Off }, { palette.color( QPalette::Disabled, QPalette::WindowText ), QIcon::Disabled, QIcon::Off }, { palette.color( QPalette::Active, QPalette::HighlightedText ), QIcon::Normal, QIcon::On }, { palette.color( QPalette::Active, QPalette::HighlightedText ), QIcon::Selected, QIcon::On }, { palette.color( QPalette::Active, QPalette::WindowText ), QIcon::Active, QIcon::On }, { palette.color( QPalette::Disabled, QPalette::WindowText ), QIcon::Disabled, QIcon::On } }; // default icon sizes static const QList iconSizes = { 8, 16, 22, 32, 48 }; // decide arrow orientation const ArrowOrientation orientation( standardPixmap == SP_ToolBarHorizontalExtensionButton ? ArrowRight : ArrowDown ); // create icon and fill QIcon icon; foreach( const IconData& iconData, iconTypes ) { foreach( const int& iconSize, iconSizes ) { // create pixmap QPixmap pixmap( iconSize, iconSize ); pixmap.fill( Qt::transparent ); // render QPainter painter( &pixmap ); // icon size const int fixedIconSize( pixelMetric( QStyle::PM_SmallIconSize, option, widget ) ); const QRect fixedRect( 0, 0, fixedIconSize, fixedIconSize ); painter.setWindow( fixedRect ); painter.translate( standardPixmap == SP_ToolBarHorizontalExtensionButton ? QPoint( 1, 0 ) : QPoint( 0, 1 ) ); _helper->renderArrow( &painter, fixedRect, iconData._color, orientation ); painter.end(); // add to icon icon.addPixmap( pixmap, iconData._mode, iconData._state ); } } return icon; } //____________________________________________________________________________________ QIcon Style::titleBarButtonIcon( StandardPixmap standardPixmap, const QStyleOption* option, const QWidget* widget ) const { // map standardPixmap to button type ButtonType buttonType; switch( standardPixmap ) { case SP_TitleBarNormalButton: buttonType = ButtonRestore; break; case SP_TitleBarMinButton: buttonType = ButtonMinimize; break; case SP_TitleBarMaxButton: buttonType = ButtonMaximize; break; case SP_TitleBarCloseButton: case SP_DockWidgetCloseButton: buttonType = ButtonClose; break; default: return QIcon(); } // store palette // due to Qt, it is not always safe to assume that either option, nor widget are defined QPalette palette; if( option ) palette = option->palette; else if( widget ) palette = widget->palette(); else palette = QApplication::palette(); const bool isCloseButton( buttonType == ButtonClose && StyleConfigData::outlineCloseButton() ); palette.setCurrentColorGroup( QPalette::Active ); const auto base( palette.color( QPalette::WindowText ) ); const auto selected( palette.color( QPalette::HighlightedText ) ); const auto negative( buttonType == ButtonClose ? _helper->negativeText( palette ):base ); const auto negativeSelected( buttonType == ButtonClose ? _helper->negativeText( palette ):selected ); const bool invertNormalState( isCloseButton ); // convenience class to map color to icon mode struct IconData { QColor _color; bool _inverted; QIcon::Mode _mode; QIcon::State _state; }; // map colors to icon states const QList iconTypes = { // state off icons { KColorUtils::mix( palette.color( QPalette::Window ), base, 0.5 ), invertNormalState, QIcon::Normal, QIcon::Off }, { KColorUtils::mix( palette.color( QPalette::Window ), selected, 0.5 ), invertNormalState, QIcon::Selected, QIcon::Off }, { KColorUtils::mix( palette.color( QPalette::Window ), negative, 0.5 ), true, QIcon::Active, QIcon::Off }, { KColorUtils::mix( palette.color( QPalette::Window ), base, 0.2 ), invertNormalState, QIcon::Disabled, QIcon::Off }, // state on icons { KColorUtils::mix( palette.color( QPalette::Window ), negative, 0.7 ), true, QIcon::Normal, QIcon::On }, { KColorUtils::mix( palette.color( QPalette::Window ), negativeSelected, 0.7 ), true, QIcon::Selected, QIcon::On }, { KColorUtils::mix( palette.color( QPalette::Window ), negative, 0.7 ), true, QIcon::Active, QIcon::On }, { KColorUtils::mix( palette.color( QPalette::Window ), base, 0.2 ), invertNormalState, QIcon::Disabled, QIcon::On } }; // default icon sizes static const QList iconSizes = { 8, 16, 22, 32, 48 }; // output icon QIcon icon; foreach( const IconData& iconData, iconTypes ) { foreach( const int& iconSize, iconSizes ) { // create pixmap QPixmap pixmap( iconSize, iconSize ); pixmap.fill( Qt::transparent ); // create painter and render QPainter painter( &pixmap ); _helper->renderDecorationButton( &painter, pixmap.rect(), iconData._color, buttonType, iconData._inverted ); painter.end(); // store icon.addPixmap( pixmap, iconData._mode, iconData._state ); } } return icon; } //______________________________________________________________________________ const QAbstractItemView* Style::itemViewParent( const QWidget* widget ) const { const QAbstractItemView* itemView( nullptr ); // check widget directly if( ( itemView = qobject_cast( widget ) ) ) return itemView; // check widget grand-parent else if( widget && widget->parentWidget() && ( itemView = qobject_cast( widget->parentWidget()->parentWidget() ) ) && itemView->viewport() == widget->parentWidget() ) { return itemView; } // return null otherwise else return nullptr; } //____________________________________________________________________ bool Style::isSelectedItem( const QWidget* widget, const QPoint& localPosition ) const { // get relevant itemview parent and check const QAbstractItemView* itemView( itemViewParent( widget ) ); if( !( itemView && itemView->hasFocus() && itemView->selectionModel() ) ) return false; #if QT_VERSION >= 0x050000 QPoint position = widget->mapTo( itemView, localPosition ); #else // qt4 misses a const for mapTo argument, although nothing is actually changed to the passed widget QPoint position = widget->mapTo( const_cast( itemView ), localPosition ); #endif // get matching QModelIndex and check const QModelIndex index( itemView->indexAt( position ) ); if( !index.isValid() ) return false; // check whether index is selected return itemView->selectionModel()->isSelected( index ); } //____________________________________________________________________ bool Style::isQtQuickControl( const QStyleOption* option, const QWidget* widget ) const { #if QT_VERSION >= 0x050000 && BREEZE_HAVE_QTQUICK const bool is = (widget == nullptr) && option && option->styleObject && option->styleObject->inherits( "QQuickItem" ); if ( is ) _windowManager->registerQuickItem( static_cast( option->styleObject ) ); return is; #else Q_UNUSED( widget ); Q_UNUSED( option ); return false; #endif } //____________________________________________________________________ bool Style::showIconsInMenuItems() const { const KConfigGroup g(KSharedConfig::openConfig(), "KDE"); return g.readEntry("ShowIconsInMenuItems", true); } //____________________________________________________________________ bool Style::showIconsOnPushButtons() const { const KConfigGroup g(KSharedConfig::openConfig(), "KDE"); return g.readEntry("ShowIconsOnPushButtons", true); } //____________________________________________________________________ bool Style::isMenuTitle( const QWidget* widget ) const { // check widget if( !widget ) return false; // check property const QVariant property( widget->property( PropertyNames::menuTitle ) ); if( property.isValid() ) return property.toBool(); // detect menu toolbuttons QWidget* parent = widget->parentWidget(); if( qobject_cast( parent ) ) { foreach( auto child, parent->findChildren() ) { if( child->defaultWidget() != widget ) continue; const_cast(widget)->setProperty( PropertyNames::menuTitle, true ); return true; } } const_cast(widget)->setProperty( PropertyNames::menuTitle, false ); return false; } //____________________________________________________________________ bool Style::hasAlteredBackground( const QWidget* widget ) const { // check widget if( !widget ) return false; // check property const QVariant property( widget->property( PropertyNames::alteredBackground ) ); if( property.isValid() ) return property.toBool(); // check if widget is of relevant type bool hasAlteredBackground( false ); if( const auto groupBox = qobject_cast( widget ) ) hasAlteredBackground = !groupBox->isFlat(); else if( const auto tabWidget = qobject_cast( widget ) ) hasAlteredBackground = !tabWidget->documentMode(); else if( qobject_cast( widget ) ) hasAlteredBackground = true; else if( StyleConfigData::dockWidgetDrawFrame() && qobject_cast( widget ) ) hasAlteredBackground = true; if( widget->parentWidget() && !hasAlteredBackground ) hasAlteredBackground = this->hasAlteredBackground( widget->parentWidget() ); const_cast(widget)->setProperty( PropertyNames::alteredBackground, hasAlteredBackground ); return hasAlteredBackground; } } diff --git a/kstyle/breezestyle.h b/kstyle/breezestyle.h index 22ab1481..c96e452b 100644 --- a/kstyle/breezestyle.h +++ b/kstyle/breezestyle.h @@ -1,608 +1,608 @@ #ifndef breezestyle_h #define breezestyle_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breeze.h" #include "config-breeze.h" #include "breezehelper.h" #if BREEZE_HAVE_KSTYLE #include #endif #if BREEZE_USE_KDE4 #include "kstylekde4compat.h" #endif #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #include namespace BreezePrivate { class TabBarData; } namespace Breeze { class Animations; class FrameShadowFactory; class Helper; class MdiWindowShadowFactory; class Mnemonics; class ShadowHelper; class SplitterFactory; class WidgetExplorer; class WindowManager; #if !BREEZE_USE_KDE4 class BlurHelper; #endif //* convenience typedef for base class #if BREEZE_USE_KDE4 using ParentStyleClass = KStyleKDE4Compat; #elif !BREEZE_HAVE_KSTYLE using ParentStyleClass = QCommonStyle; #else using ParentStyleClass = KStyle; #endif //* base class for breeze style /** it is responsible to draw all the primitives to be displayed on screen, on request from Qt paint engine */ class Style: public ParentStyleClass { Q_OBJECT /* this tells kde applications that custom style elements are supported, using the kstyle mechanism */ Q_CLASSINFO ("X-KDE-CustomElements", "true") public: //* constructor explicit Style(); //* destructor ~Style() override; //* needed to avoid warnings at compilation time using ParentStyleClass::polish; using ParentStyleClass::unpolish; //* widget polishing void polish( QWidget* ) override; //* widget unpolishing void unpolish( QWidget* ) override; //* polish scrollarea void polishScrollArea( QAbstractScrollArea* ); //* pixel metrics int pixelMetric(PixelMetric, const QStyleOption* = nullptr, const QWidget* = nullptr) const override; //* style hints int styleHint(StyleHint, const QStyleOption* = nullptr, const QWidget* = nullptr, QStyleHintReturn* = nullptr) const override; //* returns rect corresponding to one widget's subelement QRect subElementRect( SubElement, const QStyleOption*, const QWidget* ) const override; //* returns rect corresponding to one widget's subcontrol QRect subControlRect( ComplexControl, const QStyleOptionComplex*, SubControl, const QWidget* ) const override; //* returns size matching contents QSize sizeFromContents( ContentsType, const QStyleOption*, const QSize&, const QWidget* ) const override; //* returns which subcontrol given QPoint corresponds to SubControl hitTestComplexControl( ComplexControl, const QStyleOptionComplex*, const QPoint&, const QWidget* ) const override; //* primitives void drawPrimitive( PrimitiveElement, const QStyleOption*, QPainter*, const QWidget* ) const override; //* controls void drawControl( ControlElement, const QStyleOption*, QPainter*, const QWidget* ) const override; //* complex controls void drawComplexControl( ComplexControl, const QStyleOptionComplex*, QPainter*, const QWidget* ) const override; //* generic text rendering void drawItemText( QPainter*, const QRect&, int alignment, const QPalette&, bool enabled, const QString&, QPalette::ColorRole = QPalette::NoRole) const override; //*@name event filters //@{ bool eventFilter(QObject *, QEvent *) override; bool eventFilterScrollArea( QWidget*, QEvent* ); bool eventFilterComboBoxContainer( QWidget*, QEvent* ); bool eventFilterDockWidget( QDockWidget*, QEvent* ); bool eventFilterMdiSubWindow( QMdiSubWindow*, QEvent* ); #if QT_VERSION >= 0x050000 bool eventFilterCommandLinkButton( QCommandLinkButton*, QEvent* ); #endif //* install event filter to object, in a unique way void addEventFilter( QObject* object ) { object->removeEventFilter( this ); object->installEventFilter( this ); } //@} protected Q_SLOTS: //* update configuration void configurationChanged(); //* standard icons QIcon standardIconImplementation( StandardPixmap, const QStyleOption*, const QWidget* ) const; protected: //* standard icons #if BREEZE_USE_KDE4 QIcon standardIcon( StandardPixmap pixmap, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const { return standardIconImplementation( pixmap, option, widget ); } #else QIcon standardIcon( StandardPixmap pixmap, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override { return standardIconImplementation( pixmap, option, widget ); } #endif + private: + //* load configuration void loadConfiguration(); //*@name subelementRect specialized functions //@{ //* default implementation. Does not change anything QRect defaultSubElementRect( const QStyleOption* option, const QWidget* ) const { return option->rect; } QRect pushButtonContentsRect( const QStyleOption*, const QWidget* ) const; QRect checkBoxContentsRect( const QStyleOption*, const QWidget* ) const; QRect lineEditContentsRect( const QStyleOption*, const QWidget* ) const; QRect progressBarGrooveRect( const QStyleOption*, const QWidget* ) const; QRect progressBarContentsRect( const QStyleOption*, const QWidget* ) const; QRect progressBarLabelRect( const QStyleOption*, const QWidget* ) const; QRect headerArrowRect( const QStyleOption*, const QWidget* ) const; QRect headerLabelRect( const QStyleOption*, const QWidget* ) const; QRect tabBarTabLeftButtonRect( const QStyleOption*, const QWidget* ) const; QRect tabBarTabRightButtonRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetTabBarRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetTabContentsRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetTabPaneRect( const QStyleOption*, const QWidget* ) const; QRect tabWidgetCornerRect( SubElement, const QStyleOption*, const QWidget* widget ) const; QRect toolBoxTabContentsRect( const QStyleOption*, const QWidget* ) const; QRect genericLayoutItemRect( const QStyleOption*, const QWidget* ) const; //@} //*@name subcontrol Rect specialized functions //@{ QRect groupBoxSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect toolButtonSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect comboBoxSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect spinBoxSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect scrollBarInternalSubControlRect( const QStyleOptionComplex*, SubControl ) const; QRect scrollBarSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect dialSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; QRect sliderSubControlRect( const QStyleOptionComplex*, SubControl, const QWidget* ) const; //@} //*@name sizeFromContents //@{ QSize defaultSizeFromContents( const QStyleOption*, const QSize& size, const QWidget* ) const { return size; } QSize checkBoxSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize lineEditSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize comboBoxSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize spinBoxSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize sliderSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize pushButtonSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize toolButtonSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize menuBarItemSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize menuItemSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize progressBarSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize tabWidgetSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize tabBarTabSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize headerSectionSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; QSize itemViewItemSizeFromContents( const QStyleOption*, const QSize&, const QWidget* ) const; //@} //*@name primitives specialized functions //@{ bool emptyPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const { return true; } bool drawFramePrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameLineEditPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameFocusRectPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameMenuPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameGroupBoxPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameTabWidgetPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameTabBarBasePrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawFrameWindowPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorArrowUpPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowUp, option, painter, widget ); } bool drawIndicatorArrowDownPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowDown, option, painter, widget ); } bool drawIndicatorArrowLeftPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowLeft, option, painter, widget ); } bool drawIndicatorArrowRightPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { return drawIndicatorArrowPrimitive( ArrowRight, option, painter, widget ); } bool drawIndicatorArrowPrimitive( ArrowOrientation, const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorHeaderArrowPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelButtonCommandPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelButtonToolPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawTabBarPanelButtonToolPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelScrollAreaCornerPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelMenuPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelTipLabelPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawPanelItemViewItemPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorCheckBoxPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorRadioButtonPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorButtonDropDownPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorTabClosePrimitive( const QStyleOption*, QPainter* painter, const QWidget* widget ) const; bool drawIndicatorTabTearPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorToolBarHandlePrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorToolBarSeparatorPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorBranchPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; //@} //*@name controls specialized functions //@{ bool emptyControl( const QStyleOption*, QPainter*, const QWidget* ) const { return true; } - virtual bool drawPushButtonLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawToolButtonLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawCheckBoxLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawComboBoxLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawMenuBarItemControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawMenuItemControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawProgressBarControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawProgressBarContentsControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawProgressBarGrooveControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawProgressBarLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawScrollBarSliderControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawScrollBarAddLineControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawScrollBarSubLineControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawShapedFrameControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawRubberBandControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawHeaderSectionControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawHeaderEmptyAreaControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawTabBarTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawTabBarTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawToolBoxTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawToolBoxTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; - virtual bool drawDockWidgetTitleControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawPushButtonLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawToolButtonLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawCheckBoxLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawComboBoxLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawMenuBarItemControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawMenuItemControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawProgressBarControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawProgressBarContentsControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawProgressBarGrooveControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawProgressBarLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawScrollBarSliderControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawScrollBarAddLineControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawScrollBarSubLineControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawShapedFrameControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawRubberBandControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawHeaderSectionControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawHeaderEmptyAreaControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawTabBarTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawTabBarTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawToolBoxTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawToolBoxTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawDockWidgetTitleControl( const QStyleOption*, QPainter*, const QWidget* ) const; //*@} //*@name complex ontrols specialized functions //@{ bool drawGroupBoxComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawToolButtonComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawComboBoxComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawSpinBoxComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawSliderComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawDialComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawScrollBarComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; bool drawTitleBarComplexControl( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; //@} //!*@name various utilty functions //@{ //* spinbox arrows void renderSpinBoxArrow( const SubControl&, const QStyleOptionSpinBox*, QPainter*, const QWidget*) const; //* menu title void renderMenuTitle( const QStyleOptionToolButton*, QPainter*, const QWidget* ) const; //* return dial angle based on option and value qreal dialAngle( const QStyleOptionSlider*, int ) const; //* returns relevant scrollbar parent /** needed to detect parent focus */ const QWidget* scrollBarParent( const QWidget* ) const; //* returns true if given scrollbar arrow is animated QColor scrollBarArrowColor( const QStyleOptionSlider*, const SubControl&, const QWidget* ) const; //* scrollbar buttons enum ScrollBarButtonType { NoButton, SingleButton, DoubleButton }; //* returns height for scrollbar buttons depending of button types int scrollBarButtonHeight( const ScrollBarButtonType& type ) const { switch( type ) { case NoButton: return Metrics::ScrollBar_NoButtonHeight; case SingleButton: return Metrics::ScrollBar_SingleButtonHeight; case DoubleButton: return Metrics::ScrollBar_DoubleButtonHeight; default: return 0; } } //@} //* translucent background void setTranslucentBackground( QWidget* ) const; /** separator can have a title and an icon in that case they are rendered as sunken flat toolbuttons return toolbutton option that matches named separator menu items */ QStyleOptionToolButton separatorMenuItemOption( const QStyleOptionMenuItem*, const QWidget* ) const; //* create toolbar extension icon QIcon toolBarExtensionIcon( StandardPixmap, const QStyleOption*, const QWidget* ) const; //* create title bar button icon QIcon titleBarButtonIcon( StandardPixmap, const QStyleOption*, const QWidget* ) const; //* returns item view parent if any /** needed to have correct color on focused checkboxes and radiobuttons */ const QAbstractItemView* itemViewParent( const QWidget* ) const; //* returns true if a given widget is a selected item in a focused list /** This is necessary to have the correct colors used for e.g. checkboxes and radiobuttons in lists @param widget The widget to be checked @param position Used to find the relevant QModelIndex */ bool isSelectedItem( const QWidget*, const QPoint& ) const; //* return true if option corresponds to QtQuick control bool isQtQuickControl( const QStyleOption*, const QWidget* ) const; //@} //* adjust rect based on provided margins QRect insideMargin( const QRect& r, int margin ) const { return insideMargin( r, margin, margin ); } //* adjust rect based on provided margins QRect insideMargin( const QRect& r, int marginWidth, int marginHeight ) const { return r.adjusted( marginWidth, marginHeight, -marginWidth, -marginHeight ); } //* expand size based on margins QSize expandSize( const QSize& size, int margin ) const { return expandSize( size, margin, margin ); } //* expand size based on margins QSize expandSize( const QSize& size, int marginWidth, int marginHeight ) const { return size + 2*QSize( marginWidth, marginHeight ); } //* returns true for vertical tabs bool isVerticalTab( const QStyleOptionTab* option ) const { return isVerticalTab( option->shape ); } bool isVerticalTab( const QTabBar::Shape& shape ) const { return shape == QTabBar::RoundedEast || shape == QTabBar::RoundedWest || shape == QTabBar::TriangularEast || shape == QTabBar::TriangularWest; } //* right to left alignment handling using ParentStyleClass::visualRect; QRect visualRect(const QStyleOption* opt, const QRect& subRect) const { return ParentStyleClass::visualRect(opt->direction, opt->rect, subRect); } //* centering QRect centerRect(const QRect &rect, const QSize& size ) const { return centerRect( rect, size.width(), size.height() ); } QRect centerRect(const QRect &rect, int width, int height) const { return QRect(rect.left() + (rect.width() - width)/2, rect.top() + (rect.height() - height)/2, width, height); } /* Checks whether the point is before the bound rect for bound of given orientation. This is needed to implement custom number of buttons in scrollbars, as well as proper mouse-hover */ inline bool preceeds( const QPoint&, const QRect&, const QStyleOption* ) const; //* return which arrow button is hit by point for scrollbar double buttons inline QStyle::SubControl scrollBarHitTest( const QRect&, const QPoint&, const QStyleOption* ) const; //! return true if one of the widget's parent inherits requested type inline bool hasParent( const QWidget*, const char* ) const; //* return true if one of the widget's parent inherits requested type template bool hasParent( const QWidget* ) const; //* return true if icons should be shown in menus bool showIconsInMenuItems() const; //* return true if icons should be shown on buttons bool showIconsOnPushButtons() const; //* return true if passed widget is a menu title (KMenu::addTitle) bool isMenuTitle( const QWidget* ) const; //* return true if passed widget is a menu title (KMenu::addTitle) bool hasAlteredBackground( const QWidget* ) const; - private: - //*@name scrollbar button types (for addLine and subLine ) //@{ - ScrollBarButtonType _addLineButtons; - ScrollBarButtonType _subLineButtons; + ScrollBarButtonType _addLineButtons = SingleButton; + ScrollBarButtonType _subLineButtons = SingleButton; //@} //* helper Helper* _helper = nullptr; //* shadow helper ShadowHelper* _shadowHelper = nullptr; //* animations Animations* _animations = nullptr; //* keyboard accelerators Mnemonics* _mnemonics = nullptr; #if !BREEZE_USE_KDE4 //* blur helper BlurHelper* _blurHelper = nullptr; #endif //* window manager WindowManager* _windowManager = nullptr; //* frame shadows FrameShadowFactory* _frameShadowFactory = nullptr; //* mdi window shadows MdiWindowShadowFactory* _mdiWindowShadowFactory = nullptr; //* splitter Factory, to extend splitters hit area SplitterFactory* _splitterFactory = nullptr; //* widget explorer WidgetExplorer* _widgetExplorer = nullptr; //* tabbar data BreezePrivate::TabBarData* _tabBarData = nullptr; //* icon hash using IconCache = QHash; IconCache _iconCache; //* pointer to primitive specialized function using StylePrimitive = std::function; StylePrimitive _frameFocusPrimitive; //* pointer to control specialized function using StyleControl = std::function; //* pointer to control specialized function using StyleComplexControl = std::function; //*@name custom elements //@{ //* use Argb Drag and Drop Window QStyle::StyleHint SH_ArgbDndWindow; //! styled painting for KCapacityBar QStyle::ControlElement CE_CapacityBar; //@} }; //_________________________________________________________________________ bool Style::preceeds( const QPoint& point, const QRect& bound, const QStyleOption* option ) const { if( option->state&QStyle::State_Horizontal) { if( option->direction == Qt::LeftToRight) return point.x() < bound.right(); else return point.x() > bound.x(); } else return point.y() < bound.y(); } //_________________________________________________________________________ QStyle::SubControl Style::scrollBarHitTest( const QRect& rect, const QPoint& point, const QStyleOption* option ) const { if( option->state & QStyle::State_Horizontal) { if( option->direction == Qt::LeftToRight ) return point.x() < rect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; else return point.x() > rect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; } else return point.y() < rect.center().y() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; } //_________________________________________________________________________ bool Style::hasParent( const QWidget* widget, const char* className ) const { if( !widget ) return false; while( (widget = widget->parentWidget()) ) { if( widget->inherits( className ) ) return true; } return false; } //_________________________________________________________________________ template< typename T > bool Style::hasParent( const QWidget* widget ) const { if( !widget ) return false; while( (widget = widget->parentWidget()) ) { if( qobject_cast( widget ) ) return true; } return false; } } #endif diff --git a/kstyle/breezestyleplugin.cpp b/kstyle/breezestyleplugin.cpp index bcb10de9..858d16ca 100644 --- a/kstyle/breezestyleplugin.cpp +++ b/kstyle/breezestyleplugin.cpp @@ -1,52 +1,47 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezestyleplugin.h" #include "breezestyle.h" #include #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2( breeze-qt, Breeze::StylePlugin ) #endif namespace Breeze { //_________________________________________________ QStyle* StylePlugin::create( const QString &key ) { if( key.toLower() == QStringLiteral( "breeze" ) ) { return new Style; } return nullptr; } - //_________________________________________________ - StylePlugin::~StylePlugin() - { - } - //_________________________________________________ QStringList StylePlugin::keys() const { return QStringList( QStringLiteral( "Breeze" ) ); } } diff --git a/kstyle/breezestyleplugin.h b/kstyle/breezestyleplugin.h index b560b216..318394c0 100644 --- a/kstyle/breezestyleplugin.h +++ b/kstyle/breezestyleplugin.h @@ -1,57 +1,54 @@ #ifndef breezestyleplugin_h #define breezestyleplugin_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include namespace Breeze { class StylePlugin : public QStylePlugin { Q_OBJECT #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "breeze.json" ) #endif public: //* constructor explicit StylePlugin(QObject *parent = nullptr): QStylePlugin(parent) {} - //* destructor - ~StylePlugin(); - //* returns list of valid keys QStringList keys() const; //* create style - QStyle* create( const QString& ); + QStyle* create( const QString& ) override; }; } #endif diff --git a/kstyle/breezewindowmanager.cpp b/kstyle/breezewindowmanager.cpp index 5ca3fea5..1913fe6a 100644 --- a/kstyle/breezewindowmanager.cpp +++ b/kstyle/breezewindowmanager.cpp @@ -1,974 +1,974 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ ////////////////////////////////////////////////////////////////////////////// // breezewindowmanager.cpp // pass some window mouse press/release/move event actions to window manager // ------------------- // // Copyright (c) 2014 Hugo Pereira Da Costa // // Largely inspired from BeSpin style // Copyright (C) 2007 Thomas Luebking // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "breezewindowmanager.h" #include "breezepropertynames.h" #include "breezehelper.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050300 // needed to deal with device pixel ratio #include #endif #if BREEZE_HAVE_QTQUICK // needed to enable dragging from QQuickWindows #include #include #endif #if BREEZE_HAVE_X11 #include #include #if BREEZE_USE_KDE4 #include #else #include #endif #endif #if BREEZE_HAVE_KWAYLAND #include #include #include #include #include #endif namespace Util { template inline T makeT( std::initializer_list&& reference ) { #if QT_VERSION >= 0x050100 return T( std::move( reference ) ); #else // for old QT versions there is no container constructor from initializer_list T out; for( auto&& value:std::move(reference) ) { out.insert( value ); } return out; #endif } } namespace Breeze { //* provide application-wise event filter /** it us used to unlock dragging and make sure event look is properly restored after a drag has occurred */ class AppEventFilter: public QObject { public: //* constructor explicit AppEventFilter( WindowManager* parent ): QObject( parent ), _parent( parent ) {} //* event filter - virtual bool eventFilter( QObject* object, QEvent* event ) + bool eventFilter( QObject* object, QEvent* event ) override { if( event->type() == QEvent::MouseButtonRelease ) { // stop drag timer if( _parent->_dragTimer.isActive() ) { _parent->resetDrag(); } // unlock if( _parent->isLocked() ) { _parent->setLocked( false ); } } if( !_parent->enabled() ) return false; /* if a drag is in progress, the widget will not receive any event we trigger on the first MouseMove or MousePress events that are received by any widget in the application to detect that the drag is finished */ if( _parent->useWMMoveResize() && _parent->_dragInProgress && _parent->_target && ( event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress ) ) { return appMouseEvent( object, event ); } return false; } protected: //* application-wise event. /** needed to catch end of XMoveResize events */ bool appMouseEvent( QObject*, QEvent* event ) { #if BREEZE_USE_KDE4 // store target window (see later) QWidget* window( _parent->_target.data()->window() ); #else Q_UNUSED( event ); #endif /* post some mouseRelease event to the target, in order to counter balance the mouse press that triggered the drag. Note that it triggers a resetDrag */ QMouseEvent mouseEvent( QEvent::MouseButtonRelease, _parent->_dragPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier ); qApp->sendEvent( _parent->_target.data(), &mouseEvent ); #if BREEZE_USE_KDE4 if( event->type() == QEvent::MouseMove ) { /* HACK: quickly move the main cursor out of the window and back this is needed to get the focus right for the window children the origin of this issue is unknown at the moment. This apparently got fixed with qt5 */ const QPoint cursor = QCursor::pos(); QCursor::setPos(window->mapToGlobal( window->rect().topRight() ) + QPoint(1, 0) ); QCursor::setPos(cursor); } #endif return false; } private: //* parent WindowManager* _parent = nullptr; }; //_____________________________________________________________ WindowManager::WindowManager( QObject* parent ): QObject( parent ) { // install application wise event filter _appEventFilter = new AppEventFilter( this ); qApp->installEventFilter( _appEventFilter ); } //_____________________________________________________________ void WindowManager::initialize() { setEnabled( StyleConfigData::windowDragMode() != StyleConfigData::WD_NONE ); setDragMode( StyleConfigData::windowDragMode() ); setUseWMMoveResize( StyleConfigData::useWMMoveResize() ); setDragDistance( QApplication::startDragDistance() ); setDragDelay( QApplication::startDragTime() ); initializeWhiteList(); initializeBlackList(); initializeWayland(); } //_______________________________________________________ void WindowManager::initializeWayland() { #if BREEZE_HAVE_KWAYLAND if( !Helper::isWayland() ) return; if( _seat ) return; using namespace KWayland::Client; auto connection = ConnectionThread::fromApplication( this ); if( !connection ) return; auto registry = new Registry( this ); registry->create( connection ); connect(registry, &Registry::interfacesAnnounced, this, [registry, this] { const auto interface = registry->interface( Registry::Interface::Seat ); if( interface.name != 0 ) { _seat = registry->createSeat( interface.name, interface.version, this ); connect(_seat, &Seat::hasPointerChanged, this, &WindowManager::waylandHasPointerChanged); } } ); registry->setup(); connection->roundtrip(); #endif } //_______________________________________________________ void WindowManager::waylandHasPointerChanged(bool hasPointer) { #if BREEZE_HAVE_KWAYLAND Q_ASSERT( _seat ); if( hasPointer ) { if( !_pointer ) { _pointer = _seat->createPointer(this); connect(_pointer, &KWayland::Client::Pointer::buttonStateChanged, this, [this] (quint32 serial) { _waylandSerial = serial; } ); } } else { delete _pointer; _pointer = nullptr; } #else Q_UNUSED( hasPointer ); #endif } //_____________________________________________________________ void WindowManager::registerWidget( QWidget* widget ) { if( isBlackListed( widget ) || isDragable( widget ) ) { /* install filter for dragable widgets. also install filter for blacklisted widgets to be able to catch the relevant events and prevent the drag to happen */ widget->removeEventFilter( this ); widget->installEventFilter( this ); } } #if BREEZE_HAVE_QTQUICK //_____________________________________________________________ void WindowManager::registerQuickItem( QQuickItem* item ) { if ( !item ) return; if( auto window = item->window() ) { auto contentItem = window->contentItem(); contentItem->setAcceptedMouseButtons( Qt::LeftButton ); contentItem->removeEventFilter( this ); contentItem->installEventFilter( this ); } } #endif //_____________________________________________________________ void WindowManager::unregisterWidget( QWidget* widget ) { if( widget ) widget->removeEventFilter( this ); } //_____________________________________________________________ void WindowManager::initializeWhiteList() { _whiteList = Util::makeT({ ExceptionId( QStringLiteral( "MplayerWindow" ) ), ExceptionId( QStringLiteral( "ViewSliders@kmix" ) ), ExceptionId( QStringLiteral( "Sidebar_Widget@konqueror" ) ) }); foreach( const QString& exception, StyleConfigData::windowDragWhiteList() ) { ExceptionId id( exception ); if( !id.className().isEmpty() ) { _whiteList.insert( ExceptionId( exception ) ); } } } //_____________________________________________________________ void WindowManager::initializeBlackList() { _blackList = Util::makeT({ ExceptionId( QStringLiteral( "CustomTrackView@kdenlive" ) ), ExceptionId( QStringLiteral( "MuseScore" ) ), ExceptionId( QStringLiteral( "KGameCanvasWidget" ) ) }); foreach( const QString& exception, StyleConfigData::windowDragBlackList() ) { ExceptionId id( exception ); if( !id.className().isEmpty() ) { _blackList.insert( ExceptionId( exception ) ); } } } //_____________________________________________________________ bool WindowManager::eventFilter( QObject* object, QEvent* event ) { if( !enabled() ) return false; switch ( event->type() ) { case QEvent::MouseButtonPress: return mousePressEvent( object, event ); break; case QEvent::MouseMove: if ( object == _target.data() #if BREEZE_HAVE_QTQUICK || object == _quickTarget.data() #endif ) return mouseMoveEvent( object, event ); break; case QEvent::MouseButtonRelease: if ( _target #if BREEZE_HAVE_QTQUICK || _quickTarget #endif ) return mouseReleaseEvent( object, event ); break; default: break; } return false; } //_____________________________________________________________ void WindowManager::timerEvent( QTimerEvent* event ) { if( event->timerId() == _dragTimer.timerId() ) { _dragTimer.stop(); #if BREEZE_USE_KDE4 if( _target ) { startDrag( _target.data()->window(), _globalDragPoint ); } #else if( _target ) startDrag( _target.data()->window()->windowHandle(), _globalDragPoint ); #if BREEZE_HAVE_QTQUICK else if( _quickTarget ) startDrag( _quickTarget.data()->window(), _globalDragPoint ); #endif #endif } else { return QObject::timerEvent( event ); } } //_____________________________________________________________ bool WindowManager::mousePressEvent( QObject* object, QEvent* event ) { // cast event and check buttons/modifiers auto mouseEvent = static_cast( event ); #if !BREEZE_USE_KDE4 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { return false; } #endif if( !( mouseEvent->modifiers() == Qt::NoModifier && mouseEvent->button() == Qt::LeftButton ) ) { return false; } // check lock if( isLocked() ) return false; else setLocked( true ); #if BREEZE_HAVE_QTQUICK // check QQuickItem - we can immediately start drag, because QQuickWindow's contentItem // only receives mouse events that weren't handled by children if( auto item = qobject_cast( object ) ) { _quickTarget = item; _dragPoint = mouseEvent->pos(); _globalDragPoint = mouseEvent->globalPos(); if( _dragTimer.isActive() ) _dragTimer.stop(); _dragTimer.start( _dragDelay, this ); return true; } #endif // cast to widget auto widget = static_cast( object ); // check if widget can be dragged from current position if( isBlackListed( widget ) || !canDrag( widget ) ) return false; // retrieve widget's child at event position auto position( mouseEvent->pos() ); auto child = widget->childAt( position ); if( !canDrag( widget, child, position ) ) return false; // save target and drag point _target = widget; _dragPoint = position; _globalDragPoint = mouseEvent->globalPos(); _dragAboutToStart = true; // send a move event to the current child with same position // if received, it is caught to actually start the drag auto localPoint( _dragPoint ); if( child ) localPoint = child->mapFrom( widget, localPoint ); else child = widget; QMouseEvent localMouseEvent( QEvent::MouseMove, localPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier ); qApp->sendEvent( child, &localMouseEvent ); // never eat event return false; } //_____________________________________________________________ bool WindowManager::mouseMoveEvent( QObject* object, QEvent* event ) { Q_UNUSED( object ); // stop timer if( _dragTimer.isActive() ) _dragTimer.stop(); // cast event and check drag distance auto mouseEvent = static_cast( event ); #if !BREEZE_USE_KDE4 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { return false; } #endif if( !_dragInProgress ) { if( _dragAboutToStart ) { if( mouseEvent->pos() == _dragPoint ) { // start timer, _dragAboutToStart = false; if( _dragTimer.isActive() ) _dragTimer.stop(); _dragTimer.start( _dragDelay, this ); } else resetDrag(); } else if( QPoint( mouseEvent->globalPos() - _globalDragPoint ).manhattanLength() >= _dragDistance ) { _dragTimer.start( 0, this ); } return true; } else if( !useWMMoveResize() && _target ) { // use QWidget::move for the grabbing /* this works only if the sending object and the target are identical */ auto window( _target.data()->window() ); window->move( window->pos() + mouseEvent->pos() - _dragPoint ); return true; } else return false; } //_____________________________________________________________ bool WindowManager::mouseReleaseEvent( QObject* object, QEvent* event ) { Q_UNUSED( object ); Q_UNUSED( event ); resetDrag(); return false; } //_____________________________________________________________ bool WindowManager::isDragable( QWidget* widget ) { // check widget if( !widget ) return false; // accepted default types if( ( qobject_cast( widget ) && widget->isWindow() ) || ( qobject_cast( widget ) && widget->isWindow() ) || qobject_cast( widget ) ) { return true; } // more accepted types, provided they are not dock widget titles if( ( qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) || qobject_cast( widget ) ) && !isDockWidgetTitle( widget ) ) { return true; } if( widget->inherits( "KScreenSaver" ) && widget->inherits( "KCModule" ) ) { return true; } if( isWhiteListed( widget ) ) { return true; } // flat toolbuttons if( auto toolButton = qobject_cast( widget ) ) { if( toolButton->autoRaise() ) return true; } // viewports /* one needs to check that 1/ the widget parent is a scrollarea 2/ it matches its parent viewport 3/ the parent is not blacklisted */ if( auto listView = qobject_cast( widget->parentWidget() ) ) { if( listView->viewport() == widget && !isBlackListed( listView ) ) return true; } if( auto treeView = qobject_cast( widget->parentWidget() ) ) { if( treeView->viewport() == widget && !isBlackListed( treeView ) ) return true; } /* catch labels in status bars. this is because of kstatusbar who captures buttonPress/release events */ if( auto label = qobject_cast( widget ) ) { if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false; QWidget* parent = label->parentWidget(); while( parent ) { if( qobject_cast( parent ) ) return true; parent = parent->parentWidget(); } } return false; } //_____________________________________________________________ bool WindowManager::isBlackListed( QWidget* widget ) { // check against noAnimations propery const auto propertyValue( widget->property( PropertyNames::noWindowGrab ) ); if( propertyValue.isValid() && propertyValue.toBool() ) return true; // list-based blacklisted widgets const auto appName( qApp->applicationName() ); foreach( const ExceptionId& id, _blackList ) { if( !id.appName().isEmpty() && id.appName() != appName ) continue; if( id.className() == QStringLiteral( "*" ) && !id.appName().isEmpty() ) { // if application name matches and all classes are selected // disable the grabbing entirely setEnabled( false ); return true; } if( widget->inherits( id.className().toLatin1().data() ) ) return true; } return false; } //_____________________________________________________________ bool WindowManager::isWhiteListed( QWidget* widget ) const { const auto appName( qApp->applicationName() ); foreach( const ExceptionId& id, _whiteList ) { if( !(id.appName().isEmpty() || id.appName() == appName ) ) continue; if( widget->inherits( id.className().toLatin1().data() ) ) return true; } return false; } //_____________________________________________________________ bool WindowManager::canDrag( QWidget* widget ) { // check if enabled if( !enabled() ) return false; // assume isDragable widget is already passed // check some special cases where drag should not be effective // check mouse grabber if( QWidget::mouseGrabber() ) return false; /* check cursor shape. Assume that a changed cursor means that some action is in progress and should prevent the drag */ if( widget->cursor().shape() != Qt::ArrowCursor ) return false; // accept return true; } //_____________________________________________________________ bool WindowManager::canDrag( QWidget* widget, QWidget* child, const QPoint& position ) { // retrieve child at given position and check cursor again if( child && child->cursor().shape() != Qt::ArrowCursor ) return false; /* check against children from which drag should never be enabled, even if mousePress/Move has been passed to the parent */ if( child && ( qobject_cast(child ) || qobject_cast( child ) || qobject_cast( child ) ) ) { return false; } // tool buttons if( auto toolButton = qobject_cast( widget ) ) { if( dragMode() == StyleConfigData::WD_MINIMAL && !qobject_cast(widget->parentWidget() ) ) return false; return toolButton->autoRaise() && !toolButton->isEnabled(); } // check menubar if( auto menuBar = qobject_cast( widget ) ) { // do not drag from menubars embedded in Mdi windows if( findParent( widget ) ) return false; // check if there is an active action if( menuBar->activeAction() && menuBar->activeAction()->isEnabled() ) return false; // check if action at position exists and is enabled if( auto action = menuBar->actionAt( position ) ) { if( action->isSeparator() ) return true; if( action->isEnabled() ) return false; } // return true in all other cases return true; } /* in MINIMAL mode, anything that has not been already accepted and does not come from a toolbar is rejected */ if( dragMode() == StyleConfigData::WD_MINIMAL ) { if( qobject_cast( widget ) ) return true; else return false; } /* following checks are relevant only for WD_FULL mode */ // tabbar. Make sure no tab is under the cursor if( auto tabBar = qobject_cast( widget ) ) { return tabBar->tabAt( position ) == -1; } /* check groupboxes prevent drag if unchecking grouboxes */ if( auto groupBox = qobject_cast( widget ) ) { // non checkable group boxes are always ok if( !groupBox->isCheckable() ) return true; // gather options to retrieve checkbox subcontrol rect QStyleOptionGroupBox opt; opt.initFrom( groupBox ); #if BREEZE_USE_KDE4 if( groupBox->isFlat() ) opt.features |= QStyleOptionFrameV2::Flat; #else if( groupBox->isFlat() ) opt.features |= QStyleOptionFrame::Flat; #endif opt.lineWidth = 1; opt.midLineWidth = 0; opt.text = groupBox->title(); opt.textAlignment = groupBox->alignment(); opt.subControls = (QStyle::SC_GroupBoxFrame | QStyle::SC_GroupBoxCheckBox); if (!groupBox->title().isEmpty()) opt.subControls |= QStyle::SC_GroupBoxLabel; opt.state |= (groupBox->isChecked() ? QStyle::State_On : QStyle::State_Off); // check against groupbox checkbox if( groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, groupBox ).contains( position ) ) { return false; } // check against groupbox label if( !groupBox->title().isEmpty() && groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, groupBox ).contains( position ) ) { return false; } return true; } // labels if( auto label = qobject_cast( widget ) ) { if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false; } // abstract item views QAbstractItemView* itemView( nullptr ); if( ( itemView = qobject_cast( widget->parentWidget() ) ) || ( itemView = qobject_cast( widget->parentWidget() ) ) ) { if( widget == itemView->viewport() ) { // QListView if( itemView->frameShape() != QFrame::NoFrame ) return false; else if( itemView->selectionMode() != QAbstractItemView::NoSelection && itemView->selectionMode() != QAbstractItemView::SingleSelection && itemView->model() && itemView->model()->rowCount() ) return false; else if( itemView->model() && itemView->indexAt( position ).isValid() ) return false; } } else if( ( itemView = qobject_cast( widget->parentWidget() ) ) ) { if( widget == itemView->viewport() ) { // QAbstractItemView if( itemView->frameShape() != QFrame::NoFrame ) return false; else if( itemView->indexAt( position ).isValid() ) return false; } } else if( auto graphicsView = qobject_cast( widget->parentWidget() ) ) { if( widget == graphicsView->viewport() ) { // QGraphicsView if( graphicsView->frameShape() != QFrame::NoFrame ) return false; else if( graphicsView->dragMode() != QGraphicsView::NoDrag ) return false; else if( graphicsView->itemAt( position ) ) return false; } } return true; } //____________________________________________________________ void WindowManager::resetDrag() { if( (!useWMMoveResize() ) && _target && _cursorOverride ) { qApp->restoreOverrideCursor(); _cursorOverride = false; } _target.clear(); #if BREEZE_HAVE_QTQUICK _quickTarget.clear(); #endif if( _dragTimer.isActive() ) _dragTimer.stop(); _dragPoint = QPoint(); _globalDragPoint = QPoint(); _dragAboutToStart = false; _dragInProgress = false; } //____________________________________________________________ void WindowManager::startDrag( Window* window, const QPoint& position ) { if( !( enabled() && window ) ) return; if( QWidget::mouseGrabber() ) return; // ungrab pointer if( useWMMoveResize() ) { if( Helper::isX11() ) startDragX11( window, position ); else if( Helper::isWayland() ) startDragWayland( window, position ); } else if( !_cursorOverride ) { qApp->setOverrideCursor( Qt::SizeAllCursor ); _cursorOverride = true; } _dragInProgress = true; } //_______________________________________________________ void WindowManager::startDragX11( Window* window, const QPoint& position ) { #if BREEZE_HAVE_X11 // connection auto connection( Helper::connection() ); #if BREEZE_USE_KDE4 auto net_connection = QX11Info::display(); const QPoint native = position; #else auto net_connection = connection; const qreal dpiRatio = window->devicePixelRatio(); const QPoint origin = window->screen()->geometry().topLeft(); const QPoint native = (position - origin) * dpiRatio + origin; #endif xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME ); NETRootInfo( net_connection, NET::WMMoveResize ).moveResizeRequest( window->winId(), native.x(), native.y(), NET::Move ); #else Q_UNUSED( window ); Q_UNUSED( position ); #endif } //_______________________________________________________ void WindowManager::startDragWayland( Window* window, const QPoint& ) { #if BREEZE_HAVE_KWAYLAND if( !_seat ) { return; } auto shellSurface = KWayland::Client::ShellSurface::fromWindow(window); if( !shellSurface ) { // TODO: also check for xdg-shell in future return; } shellSurface->requestMove( _seat, _waylandSerial ); #else Q_UNUSED( window ); #endif } //____________________________________________________________ bool WindowManager::supportWMMoveResize() const { #if BREEZE_HAVE_KWAYLAND if( Helper::isWayland() ) { return true; } #endif #if BREEZE_HAVE_X11 return Helper::isX11(); #else return false; #endif } //____________________________________________________________ bool WindowManager::isDockWidgetTitle( const QWidget* widget ) const { if( !widget ) return false; if( auto dockWidget = qobject_cast( widget->parent() ) ) { return widget == dockWidget->titleBarWidget(); } else return false; } } diff --git a/kstyle/debug/breezewidgetexplorer.cpp b/kstyle/debug/breezewidgetexplorer.cpp index d4f599e6..dff6e15a 100644 --- a/kstyle/debug/breezewidgetexplorer.cpp +++ b/kstyle/debug/breezewidgetexplorer.cpp @@ -1,165 +1,163 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezewidgetexplorer.h" #include "breeze.h" #include #include #include #include namespace Breeze { //________________________________________________ WidgetExplorer::WidgetExplorer( QObject* parent ): - QObject( parent ), - _enabled( false ), - _drawWidgetRects( false ) + QObject( parent ) { _eventTypes.insert( QEvent::Enter, QStringLiteral( "Enter" ) ); _eventTypes.insert( QEvent::Leave, QStringLiteral( "Leave" ) ); _eventTypes.insert( QEvent::HoverMove, QStringLiteral( "HoverMove" ) ); _eventTypes.insert( QEvent::HoverEnter, QStringLiteral( "HoverEnter" ) ); _eventTypes.insert( QEvent::HoverLeave, QStringLiteral( "HoverLeave" ) ); _eventTypes.insert( QEvent::MouseMove, QStringLiteral( "MouseMove" ) ); _eventTypes.insert( QEvent::MouseButtonPress, QStringLiteral( "MouseButtonPress" ) ); _eventTypes.insert( QEvent::MouseButtonRelease, QStringLiteral( "MouseButtonRelease" ) ); _eventTypes.insert( QEvent::FocusIn, QStringLiteral( "FocusIn" ) ); _eventTypes.insert( QEvent::FocusOut, QStringLiteral( "FocusOut" ) ); // _eventTypes.insert( QEvent::Paint, "Paint" ); } //________________________________________________ void WidgetExplorer::setEnabled( bool value ) { if( value == _enabled ) return; _enabled = value; qApp->removeEventFilter( this ); if( _enabled ) qApp->installEventFilter( this ); } //________________________________________________ bool WidgetExplorer::eventFilter( QObject* object, QEvent* event ) { // if( object->isWidgetType() ) // { // QString type( _eventTypes[event->type()] ); // if( !type.isEmpty() ) // { // QTextStream( stdout ) << "Breeze::WidgetExplorer::eventFilter - widget: " << object << " (" << object->metaObject()->className() << ")"; // QTextStream( stdout ) << " type: " << type << endl; // } // } switch( event->type() ) { case QEvent::Paint: if( _drawWidgetRects ) { QWidget* widget( qobject_cast( object ) ); if( !widget ) return false; QPainter painter( widget ); painter.setRenderHints(QPainter::Antialiasing); painter.setBrush( Qt::NoBrush ); painter.setPen( Qt::red ); painter.drawRect( widget->rect() ); painter.end(); } break; case QEvent::MouseButtonPress: { // cast event and check button QMouseEvent* mouseEvent( static_cast( event ) ); if( mouseEvent->button() != Qt::LeftButton ) break; // case widget and check (should not be necessary) QWidget* widget( qobject_cast(object) ); if( !widget ) return false; QTextStream( stdout ) << "Breeze::WidgetExplorer::eventFilter -" << " event: " << event << " type: " << eventType( event->type() ) << " widget: " << widgetInformation( widget ) << endl; // print parent information QWidget* parent( widget->parentWidget() ); while( parent ) { QTextStream( stdout ) << " parent: " << widgetInformation( parent ) << endl; parent = parent->parentWidget(); } QTextStream( stdout ) << "" << endl; } break; default: break; } // always return false to go on with normal chain return false; } //________________________________________________ QString WidgetExplorer::eventType( const QEvent::Type& type ) const { switch( type ) { case QEvent::MouseButtonPress: return QStringLiteral( "MouseButtonPress" ); case QEvent::MouseButtonRelease: return QStringLiteral( "MouseButtonRelease" ); case QEvent::MouseMove: return QStringLiteral( "MouseMove" ); default: return QStringLiteral( "Unknown" ); } } //________________________________________________ QString WidgetExplorer::widgetInformation( const QWidget* widget ) const { QRect r( widget->geometry() ); const char* className( widget->metaObject()->className() ); QString out; QTextStream( &out ) << widget << " (" << className << ")" << " position: " << r.x() << "," << r.y() << " size: " << r.width() << "," << r.height() << " sizeHint: " << widget->sizeHint().width() << "," << widget->sizeHint().height() << " minimumSizeHint: " << widget->minimumSizeHint().width() << "," << widget->minimumSizeHint().height() << " hover: " << widget->testAttribute( Qt::WA_Hover ); return out; } } diff --git a/kstyle/debug/breezewidgetexplorer.h b/kstyle/debug/breezewidgetexplorer.h index 401ad95a..b9ea3281 100644 --- a/kstyle/debug/breezewidgetexplorer.h +++ b/kstyle/debug/breezewidgetexplorer.h @@ -1,79 +1,79 @@ #ifndef breezewidgetexplorer_h #define breezewidgetexplorer_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include #include #include #include #include namespace Breeze { //* print widget's and parent's information on mouse click class WidgetExplorer: public QObject { Q_OBJECT public: //* constructor explicit WidgetExplorer( QObject* ); //* enable bool enabled() const; //* enable void setEnabled( bool ); //* widget rects void setDrawWidgetRects( bool value ) { _drawWidgetRects = value; } //* event filter - virtual bool eventFilter( QObject*, QEvent* ); + bool eventFilter( QObject*, QEvent* ) override; protected: //* event type QString eventType( const QEvent::Type& ) const; //* print widget information QString widgetInformation( const QWidget* ) const; private: //* enable state - bool _enabled; + bool _enabled = false; //* widget rects - bool _drawWidgetRects; + bool _drawWidgetRects = false; //* map event types to string QMap _eventTypes; }; } #endif