#ifndef adwaitastyle_h #define adwaitastyle_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 "adwaita.h" #include "config-adwaita.h" #if ADWAITA_USE_KDE4 #include "kstylekde4compat.h" #endif #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif namespace AdwaitaPrivate { class TabBarData; } namespace Adwaita { class Animations; class Helper; class Mnemonics; class SplitterFactory; class WidgetExplorer; class WindowManager; //* convenience typedef for base class #if ADWAITA_USE_KDE4 using ParentStyleClass = KStyleKDE4Compat; #else using ParentStyleClass = QCommonStyle; #endif //* base class for adwaita 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( bool dark ); //* destructor virtual ~Style( void ); //* needed to avoid warnings at compilation time using ParentStyleClass::polish; using ParentStyleClass::unpolish; //* widget polishing virtual void polish( QWidget* ); //* widget unpolishing virtual void unpolish( QWidget* ); //* palette polishing virtual void polish( QPalette &palette ); //* polish scrollarea void polishScrollArea( QAbstractScrollArea* ); //* pixel metrics virtual int pixelMetric(PixelMetric, const QStyleOption* = nullptr, const QWidget* = nullptr) const; //* style hints virtual int styleHint(StyleHint, const QStyleOption* = nullptr, const QWidget* = nullptr, QStyleHintReturn* = nullptr) const; //* returns rect corresponding to one widget's subelement virtual QRect subElementRect( SubElement, const QStyleOption*, const QWidget* ) const; //* returns rect corresponding to one widget's subcontrol virtual QRect subControlRect( ComplexControl, const QStyleOptionComplex*, SubControl, const QWidget* ) const; //* returns size matching contents QSize sizeFromContents( ContentsType, const QStyleOption*, const QSize&, const QWidget* ) const; //* returns which subcontrol given QPoint corresponds to SubControl hitTestComplexControl( ComplexControl, const QStyleOptionComplex*, const QPoint&, const QWidget* ) const; //* primitives void drawPrimitive( PrimitiveElement, const QStyleOption*, QPainter*, const QWidget* ) const; //* controls void drawControl( ControlElement, const QStyleOption*, QPainter*, const QWidget* ) const; //* complex controls void drawComplexControl( ComplexControl, const QStyleOptionComplex*, QPainter*, const QWidget* ) const; //* generic text rendering virtual void drawItemText( QPainter*, const QRect&, int alignment, const QPalette&, bool enabled, const QString&, QPalette::ColorRole = QPalette::NoRole) const; //*@name event filters //@{ virtual bool eventFilter(QObject *, QEvent *); 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( void ); //* standard icons virtual QIcon standardIconImplementation( StandardPixmap, const QStyleOption*, const QWidget* ) const; protected: //* standard icons virtual QIcon standardIcon( StandardPixmap pixmap, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const { return standardIconImplementation( pixmap, option, widget ); } //* 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 pushButtonFocusRect( const QStyleOption*, const QWidget* ) const; QRect checkBoxContentsRect( const QStyleOption*, const QWidget* ) const; QRect checkBoxIndicatorRect( const QStyleOption*, const QWidget* ) const; QRect checkBoxFocusRect( 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 sliderFocusRect( 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 drawMenuBarEmptyArea( const QStyleOption*, QPainter* , const QWidget*) const; virtual bool drawMenuBarItemControl( const QStyleOption*, QPainter*, const QWidget* ) const; virtual bool drawMenuEmptyAreaControl( 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 drawHeaderLabelControl( 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; //*@} //*@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( void ) const; //* return true if icons should be shown on buttons bool showIconsOnPushButtons( void ) 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; //@} //* helper Helper* _helper; //* animations Animations* _animations; //* keyboard accelerators Mnemonics* _mnemonics; //* window manager WindowManager* _windowManager; //* splitter Factory, to extend splitters hit area SplitterFactory* _splitterFactory; //* widget explorer WidgetExplorer* _widgetExplorer; //* tabbar data AdwaitaPrivate::TabBarData* _tabBarData; //* icon hash using IconCache = QHash; IconCache _iconCache; //* pointer to primitive specialized function using StylePrimitive = bool(Style::*)(const QStyleOption*, QPainter*, const QWidget* ) const; StylePrimitive _frameFocusPrimitive = nullptr; //* pointer to control specialized function using StyleControl = bool (Style::*)( const QStyleOption*, QPainter*, const QWidget* ) const; //* pointer to control specialized function using StyleComplexControl = bool (Style::*)( const QStyleOptionComplex*, QPainter*, const QWidget* ) const; //*@name custom elements //@{ //* use Argb Drag and Drop Window QStyle::StyleHint SH_ArgbDndWindow; //! styled painting for KCapacityBar QStyle::ControlElement CE_CapacityBar; bool _dark { false }; bool _isGNOME { false }; bool _isKDE { false }; //@} }; //_________________________________________________________________________ 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