breezestyle.cpp 290 KB
Newer Older
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*************************************************************************
 * Copyright (C) 2014 by Hugo Pereira Da Costa <hugo.pereira@free.fr>    *
 *                                                                       *
 * 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 .        *
 *************************************************************************/
19
20
21

#include "breezestyle.h"

22
#include "breezeanimations.h"
23
#include "breezeframeshadow.h"
24
#include "breezemdiwindowshadow.h"
25
#include "breezemnemonics.h"
26
#include "breezepropertynames.h"
27
#include "breezeshadowhelper.h"
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
28
#include "breezesplitterproxy.h"
29
#include "breezestyleconfigdata.h"
30
#include "breezewidgetexplorer.h"
31
#include "breezewindowmanager.h"
32
#include "breezeblurhelper.h"
33
34
35
36
37
38
39
40
41

#include <KColorUtils>

#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QDial>
#include <QDBusConnection>
#include <QDockWidget>
42
#include <QFormLayout>
43
#include <QGraphicsView>
44
45
#include <QGroupBox>
#include <QLineEdit>
46
#include <QMainWindow>
47
#include <QMdiSubWindow>
48
#include <QMenu>
49
50
51
52
#include <QPainter>
#include <QPushButton>
#include <QRadioButton>
#include <QScrollBar>
53
#include <QItemDelegate>
54
55
#include <QSplitterHandle>
#include <QTextEdit>
56
#include <QToolBar>
57
58
#include <QToolBox>
#include <QToolButton>
59
#include <QTreeView>
60
#include <QWidgetAction>
61

62
63
64
65
#if BREEZE_HAVE_QTQUICK
#include <QQuickWindow>
#endif

66
67
namespace BreezePrivate
{
68

69
70
71
72
73
74
    // needed to keep track of tabbars when being dragged
    class TabBarData: public QObject
    {

        public:

Hugo Pereira Da Costa's avatar
doxygen    
Hugo Pereira Da Costa committed
75
        //* constructor
76
77
78
79
        explicit TabBarData( QObject* parent ):
            QObject( parent )
        {}

Hugo Pereira Da Costa's avatar
doxygen    
Hugo Pereira Da Costa committed
80
        //* assign target tabBar
81
82
83
        void lock( const QWidget* widget )
        { _tabBar = widget; }

Hugo Pereira Da Costa's avatar
doxygen    
Hugo Pereira Da Costa committed
84
        //* true if tabbar is locked
85
86
87
        bool isLocked( const QWidget* widget ) const
        { return _tabBar && _tabBar.data() == widget; }

Hugo Pereira Da Costa's avatar
doxygen    
Hugo Pereira Da Costa committed
88
        //* release
89
        void release()
90
91
92
93
        { _tabBar.clear(); }

        private:

Hugo Pereira Da Costa's avatar
doxygen    
Hugo Pereira Da Costa committed
94
        //* pointer to target tabBar
95
        Breeze::WeakPointer<const QWidget> _tabBar;
96
97
98

    };

99
    //* needed to have spacing added to items in combobox
100
101
102
103
104
    class ComboBoxItemDelegate: public QItemDelegate
    {

        public:

105
        //* constructor
106
        explicit ComboBoxItemDelegate( QAbstractItemView* parent ):
107
108
109
110
111
            QItemDelegate( parent ),
            _proxy( parent->itemDelegate() ),
            _itemMargin( Breeze::Metrics::ItemView_ItemMarginWidth )
        {}

112
        //* paint
113
        void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
114
115
116
117
118
119
        {
            // call either proxy or parent class
            if( _proxy ) _proxy.data()->paint( painter, option, index );
            else QItemDelegate::paint( painter, option, index );
        }

120
        //* size hint for index
121
        QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override
122
123
124
        {

            // get size from either proxy or parent class
125
            auto size( _proxy ?
126
127
128
129
130
131
132
133
134
135
136
                _proxy.data()->sizeHint( option, index ):
                QItemDelegate::sizeHint( option, index ) );

            // adjust and return
            if( size.isValid() ) { size.rheight() += _itemMargin*2; }
            return size;

        }

        private:

137
        //* proxy
138
139
        Breeze::WeakPointer<QAbstractItemDelegate> _proxy;

140
        //* margin
141
142
143
144
        int _itemMargin;

    };

145
146
147
148
    //_______________________________________________________________
    bool isProgressBarHorizontal( const QStyleOptionProgressBar* option )
    {  return option && ( (option->state & QStyle::State_Horizontal ) || option->orientation == Qt::Horizontal ); }

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    enum class ToolButtonMenuArrowStyle {
        None,
        InlineLarge,
        InlineSmall,
        SubControl
    };

    ToolButtonMenuArrowStyle toolButtonMenuArrowStyle( const QStyleOption* option )
    {
        const auto toolButtonOption = qstyleoption_cast<const QStyleOptionToolButton*>( option );
        if (!toolButtonOption) {
            return ToolButtonMenuArrowStyle::None;
        }

        const bool hasPopupMenu( toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup );
        const bool hasInlineIndicator( toolButtonOption->features&QStyleOptionToolButton::HasMenu && !hasPopupMenu );
        const bool hasDelayedMenu( hasInlineIndicator && toolButtonOption->features & QStyleOptionToolButton::PopupDelay );

        const bool hasIcon = !toolButtonOption->icon.isNull() || ( toolButtonOption->features & QStyleOptionToolButton::Arrow );
        const bool iconOnly = toolButtonOption->toolButtonStyle == Qt::ToolButtonIconOnly
                              || (toolButtonOption->text.isEmpty() && hasIcon);

        if( hasPopupMenu )
        {
            return ToolButtonMenuArrowStyle::SubControl;
        }

        if( hasDelayedMenu )
        {
            return ToolButtonMenuArrowStyle::InlineSmall;
        }

        if ( hasInlineIndicator && !iconOnly )
        {
            return ToolButtonMenuArrowStyle::InlineLarge;
        }

        return ToolButtonMenuArrowStyle::None;
    }

189
190
}

191
192
193
194
namespace Breeze
{

    //______________________________________________________________
195
    Style::Style():
196

197
        _helper( new Helper( StyleConfigData::self()->sharedConfig() ) )
198
199
200
        , _shadowHelper( new ShadowHelper( this, *_helper ) )
        , _animations( new Animations( this ) )
        , _mnemonics( new Mnemonics( this ) )
201
        , _blurHelper( new BlurHelper( this ) )
202
203
204
205
        , _windowManager( new WindowManager( this ) )
        , _frameShadowFactory( new FrameShadowFactory( this ) )
        , _mdiWindowShadowFactory( new MdiWindowShadowFactory( this ) )
        , _splitterFactory( new SplitterFactory( this ) )
206
        , _widgetExplorer( new WidgetExplorer( this ) )
207
        , _tabBarData( new BreezePrivate::TabBarData( this ) )
208
        #if BREEZE_HAVE_KSTYLE
209
        , SH_ArgbDndWindow( newStyleHint( QStringLiteral( "SH_ArgbDndWindow" ) ) )
210
        , CE_CapacityBar( newControlElement( QStringLiteral( "CE_CapacityBar" ) ) )
211
        #endif
212
213
214
    {

        // use DBus connection to update on breeze configuration change
215
        auto dbus = QDBusConnection::sessionBus();
216
217
218
219
220
        dbus.connect( QString(),
            QStringLiteral( "/BreezeStyle" ),
            QStringLiteral( "org.kde.Breeze.Style" ),
            QStringLiteral( "reparseConfiguration" ), this, SLOT(configurationChanged()) );

221
222
223
224
        dbus.connect( QString(),
            QStringLiteral( "/BreezeDecoration" ),
            QStringLiteral( "org.kde.Breeze.Style" ),
            QStringLiteral( "reparseConfiguration" ), this, SLOT(configurationChanged()) );
225
226
227
228
        dbus.connect( QString(),
            QStringLiteral( "/KGlobalSettings" ),
            QStringLiteral( "org.kde.KGlobalSettings" ),
            QStringLiteral( "notifyChange" ), this, SLOT(configurationChanged()) );
229
230
231
        #if QT_VERSION < 0x050D00 // Check if Qt version < 5.13
        this->addEventFilter(qApp);
        #else
232
        connect(qApp, &QApplication::paletteChanged, this, &Style::configurationChanged);
233
        #endif
234
235
236
237
238
239
240
        // call the slot directly; this initial call will set up things that also
        // need to be reset when the system palette changes
        loadConfiguration();

    }

    //______________________________________________________________
241
    Style::~Style()
242
243
244
245
    {
        delete _shadowHelper;
        delete _helper;
    }
246
247
248
249
250
251
252

    //______________________________________________________________
    void Style::polish( QWidget* widget )
    {
        if( !widget ) return;

        // register widget to animations
253
254
        _animations->registerWidget( widget );
        _windowManager->registerWidget( widget );
255
        _frameShadowFactory->registerWidget( widget, *_helper );
256
        _mdiWindowShadowFactory->registerWidget( widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
257
258
        _shadowHelper->registerWidget( widget );
        _splitterFactory->registerWidget( widget );
259

260
        // enable mouse over effects for all necessary widgets
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
        if(
            qobject_cast<QAbstractItemView*>( widget )
            || qobject_cast<QAbstractSpinBox*>( widget )
            || qobject_cast<QCheckBox*>( widget )
            || qobject_cast<QComboBox*>( widget )
            || qobject_cast<QDial*>( widget )
            || qobject_cast<QLineEdit*>( widget )
            || qobject_cast<QPushButton*>( widget )
            || qobject_cast<QRadioButton*>( widget )
            || qobject_cast<QScrollBar*>( widget )
            || qobject_cast<QSlider*>( widget )
            || qobject_cast<QSplitterHandle*>( widget )
            || qobject_cast<QTabBar*>( widget )
            || qobject_cast<QTextEdit*>( widget )
            || qobject_cast<QToolButton*>( widget )
276
            || widget->inherits( "KTextEditor::View" )
277
278
279
            )
        { widget->setAttribute( Qt::WA_Hover ); }

280
281
282
283
284
285
286
        // enforce translucency for drag and drop window
        if( widget->testAttribute( Qt::WA_X11NetWmWindowTypeDND ) && _helper->compositingActive() )
        {
            widget->setAttribute( Qt::WA_TranslucentBackground );
            widget->clearMask();
        }

287
288
289
        // scrollarea polishing is somewhat complex. It is moved to a dedicated method
        polishScrollArea( qobject_cast<QAbstractScrollArea*>( widget ) );

290
        if( auto itemView = qobject_cast<QAbstractItemView*>( widget ) )
291
292
        {

293
            // enable mouse over effects in itemviews' viewport
294
295
            itemView->viewport()->setAttribute( Qt::WA_Hover );

296
        } else if( auto groupBox = qobject_cast<QGroupBox*>( widget ) )  {
297
298
299
300
301
302
303
304
305
306
307
308
309

            // checkable group boxes
            if( groupBox->isCheckable() )
            { groupBox->setAttribute( Qt::WA_Hover ); }

        } else if( qobject_cast<QAbstractButton*>( widget ) && qobject_cast<QDockWidget*>( widget->parent() ) ) {

            widget->setAttribute( Qt::WA_Hover );

        } else if( qobject_cast<QAbstractButton*>( widget ) && qobject_cast<QToolBox*>( widget->parent() ) ) {

            widget->setAttribute( Qt::WA_Hover );

310
311
312
        } else if( qobject_cast<QFrame*>( widget ) && widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ) {

            widget->setAutoFillBackground( false );
313
314
            if( !StyleConfigData::titleWidgetDrawFrame() )
            { widget->setBackgroundRole( QPalette::Window ); }
315

316
317
318
319
        }

        if( qobject_cast<QScrollBar*>( widget ) )
        {
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
320

321
            // remove opaque painting for scrollbars
322
323
            widget->setAttribute( Qt::WA_OpaquePaintEvent, false );

324
325
326
327
        } else if( widget->inherits( "KTextEditor::View" ) ) {

            addEventFilter( widget );

328
        } else if( auto toolButton = qobject_cast<QToolButton*>( widget ) ) {
329

330
331
332
333
334
335
            if( toolButton->autoRaise() )
            {
                // for flat toolbuttons, adjust foreground and background role accordingly
                widget->setBackgroundRole( QPalette::NoRole );
                widget->setForegroundRole( QPalette::WindowText );
            }
336

337
338
339
340
341
            if( widget->parentWidget() &&
                widget->parentWidget()->parentWidget() &&
                widget->parentWidget()->parentWidget()->inherits( "Gwenview::SideBarGroup" ) )
            { widget->setProperty( PropertyNames::toolButtonAlignment, Qt::AlignLeft ); }

342
343
        } else if( qobject_cast<QDockWidget*>( widget ) ) {

344
345
            // add event filter on dock widgets
            // and alter palette
346
347
348
349
            widget->setAutoFillBackground( false );
            widget->setContentsMargins( Metrics::Frame_FrameWidth, Metrics::Frame_FrameWidth, Metrics::Frame_FrameWidth, Metrics::Frame_FrameWidth );
            addEventFilter( widget );

350
351
352
        } else if( qobject_cast<QMdiSubWindow*>( widget ) ) {

            widget->setAutoFillBackground( false );
353
            addEventFilter( widget );
354

355
356
357
358
359
360
361
362
363
364
365
        } else if( qobject_cast<QToolBox*>( widget ) ) {

            widget->setBackgroundRole( QPalette::NoRole );
            widget->setAutoFillBackground( false );

        } else if( widget->parentWidget() && widget->parentWidget()->parentWidget() && qobject_cast<QToolBox*>( widget->parentWidget()->parentWidget()->parentWidget() ) ) {

            widget->setBackgroundRole( QPalette::NoRole );
            widget->setAutoFillBackground( false );
            widget->parentWidget()->setAutoFillBackground( false );

366
367
368
369
        } else if( qobject_cast<QMenu*>( widget ) ) {

            setTranslucentBackground( widget );

370
371
372
373
            if ( _helper->hasAlphaChannel( widget ) && StyleConfigData::menuOpacity() < 100 ) {
                _blurHelper->registerWidget( widget->window() );
            }

374
375
376
        } else if( qobject_cast<QCommandLinkButton*>( widget ) ) {

            addEventFilter( widget );
377

378
        } else if( auto comboBox = qobject_cast<QComboBox*>( widget ) ) {
379

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
380
381
            if( !hasParent( widget, "QWebView" ) )
            {
382
                auto itemView( comboBox->view() );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
383
384
385
                if( itemView && itemView->itemDelegate() && itemView->itemDelegate()->inherits( "QComboBoxDelegate" ) )
                { itemView->setItemDelegate( new BreezePrivate::ComboBoxItemDelegate( itemView ) ); }
            }
386

387
388
389
390
391
392
393
394
        } else if( widget->inherits( "QComboBoxPrivateContainer" ) ) {

            addEventFilter( widget );
            setTranslucentBackground( widget );

        } else if( widget->inherits( "QTipLabel" ) ) {

            setTranslucentBackground( widget );
395

396
397
398
        }

        // base class polishing
399
        ParentStyleClass::polish( widget );
400
401
402

    }

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
    //______________________________________________________________
    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
431
            auto font( scrollArea->font() );
432
433
434
435
436
437
438
439
440
441
            font.setBold( false );
            scrollArea->setFont( font );
        }

        // 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
442
        auto viewport( scrollArea->viewport() );
443
444
445
446
447
448
449
450
451
452
453
454
        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<QWidget*> children( viewport->findChildren<QWidget*>() );
        foreach( QWidget* child, children )
        {
            if( child->parent() == viewport && child->backgroundRole() == QPalette::Window )
            { child->setAutoFillBackground( false ); }
        }

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
        /*
        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<QTreeView *>( scrollArea ) )
        {
            if (treeView->isAnimated())
            {
                QPalette pal( treeView->palette() );
                pal.setColor( QPalette::Active, QPalette::Base, treeView->palette().color( treeView->backgroundRole() ) );
                treeView->setPalette(pal);
            }
        }

471
472
    }

473
474
475
476
477
    //_______________________________________________________________
    void Style::unpolish( QWidget* widget )
    {

        // register widget to animations
478
479
        _animations->unregisterWidget( widget );
        _frameShadowFactory->unregisterWidget( widget );
480
        _mdiWindowShadowFactory->unregisterWidget( widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
481
482
483
        _shadowHelper->unregisterWidget( widget );
        _windowManager->unregisterWidget( widget );
        _splitterFactory->unregisterWidget( widget );
484
485
        _blurHelper->unregisterWidget( widget );

486
487
488
489
490
491
492
        // remove event filter
        if( qobject_cast<QAbstractScrollArea*>( widget ) ||
            qobject_cast<QDockWidget*>( widget ) ||
            qobject_cast<QMdiSubWindow*>( widget ) ||
            widget->inherits( "QComboBoxPrivateContainer" ) )
            { widget->removeEventFilter( this ); }

493
        ParentStyleClass::unpolish( widget );
494
495
496
497
498
499
500
501
502
503
504

    }

    //______________________________________________________________
    int Style::pixelMetric( PixelMetric metric, const QStyleOption* option, const QWidget* widget ) const
    {

        // handle special cases
        switch( metric )
        {

505
            // frame width
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
506
            case PM_DefaultFrameWidth:
507
            if( qobject_cast<const QMenu*>( widget ) ) return Metrics::Menu_FrameWidth;
508
            if( qobject_cast<const QLineEdit*>( widget ) ) return Metrics::LineEdit_FrameWidth;
509
            else if( isQtQuickControl( option, widget ) )
510
511
            {
                const QString &elementType = option->styleObject->property( "elementType" ).toString();
512
                if( elementType == QLatin1String( "edit" ) || elementType == QLatin1String( "spinbox" ) )
513
514
                {

515
                    return Metrics::LineEdit_FrameWidth;
516

517
                } else if( elementType == QLatin1String( "combobox" ) ) {
518

519
                    return Metrics::ComboBox_FrameWidth;
520
521
522
523
524
525
526
                }

            }

            // fallback
            return Metrics::Frame_FrameWidth;

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
527
            case PM_ComboBoxFrameWidth:
528
            {
529
                const auto comboBoxOption( qstyleoption_cast< const QStyleOptionComboBox*>( option ) );
530
531
532
                return comboBoxOption && comboBoxOption->editable ? Metrics::LineEdit_FrameWidth : Metrics::ComboBox_FrameWidth;
            }

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
533
534
535
            case PM_SpinBoxFrameWidth: return Metrics::SpinBox_FrameWidth;
            case PM_ToolBarFrameWidth: return Metrics::ToolBar_FrameWidth;
            case PM_ToolTipLabelFrameWidth: return Metrics::ToolTip_FrameWidth;
536

537
538
539
540
541
542
543
            // layout
            case PM_LayoutLeftMargin:
            case PM_LayoutTopMargin:
            case PM_LayoutRightMargin:
            case PM_LayoutBottomMargin:
            {
                /*
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
544
545
546
                 * use either Child margin or TopLevel margin,
                 * depending on  widget type
                 */
547
548
549
550
551
                if( ( option && ( option->state & QStyle::State_Window ) ) || ( widget && widget->isWindow() ) )
                {

                    return Metrics::Layout_TopLevelMarginWidth;

552
553
554
555
                } else if( widget && widget->inherits( "KPageView" ) ) {

                    return 0;

556
557
558
559
560
561
562
563
                } else {

                    return Metrics::Layout_ChildMarginWidth;

                }

            }

564
565
            case PM_LayoutHorizontalSpacing: return Metrics::Layout_DefaultSpacing;
            case PM_LayoutVerticalSpacing: return Metrics::Layout_DefaultSpacing;
566

567
            // buttons
568
569
            case PM_ButtonMargin:
            {
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
570
                // needs special case for kcalc buttons, to prevent the application to set too small margins
571
572
573
574
                if( widget && widget->inherits( "KCalcButton" ) ) return Metrics::Button_MarginWidth + 4;
                else return Metrics::Button_MarginWidth;
            }

575
576
577
578
            case PM_ButtonDefaultIndicator: return 0;
            case PM_ButtonShiftHorizontal: return 0;
            case PM_ButtonShiftVertical: return 0;

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
579
580
581
582
583
584
585
            // 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;

586
            // menu buttons
587
            case PM_MenuButtonIndicator: return Metrics::MenuButton_IndicatorWidth;
588

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
589
            // toolbars
590
            case PM_ToolBarHandleExtent: return Metrics::ToolBar_HandleExtent;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
591
            case PM_ToolBarSeparatorExtent: return Metrics::ToolBar_SeparatorWidth;
592
593
            case PM_ToolBarExtensionExtent:
            return pixelMetric( PM_SmallIconSize, option, widget ) + 2*Metrics::ToolButton_MarginWidth;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
594
595
596
597
598

            case PM_ToolBarItemMargin: return 0;
            case PM_ToolBarItemSpacing: return Metrics::ToolBar_ItemSpacing;

            // tabbars
599
600
            case PM_TabBarTabShiftVertical: return 0;
            case PM_TabBarTabShiftHorizontal: return 0;
601
602
            case PM_TabBarTabOverlap: return Metrics::TabBar_TabOverlap;
            case PM_TabBarBaseOverlap: return Metrics::TabBar_BaseOverlap;
603
            case PM_TabBarTabHSpace: return 2*Metrics::TabBar_TabMarginWidth;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
604
            case PM_TabBarTabVSpace: return 2*Metrics::TabBar_TabMarginHeight;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
605
606
607
            case PM_TabCloseIndicatorWidth:
            case PM_TabCloseIndicatorHeight:
            return pixelMetric( PM_SmallIconSize, option, widget );
608

609
            // scrollbars
610
611
612
            case PM_ScrollBarExtent: return Metrics::ScrollBar_Extend;
            case PM_ScrollBarSliderMin: return Metrics::ScrollBar_MinSliderHeight;

613
614
615
            // title bar
            case PM_TitleBarHeight: return 2*Metrics::TitleBar_MarginWidth + pixelMetric( PM_SmallIconSize, option, widget );

616
            // sliders
617
            case PM_SliderThickness: return Metrics::Slider_ControlThickness;
618
619
620
            case PM_SliderControlThickness: return Metrics::Slider_ControlThickness;
            case PM_SliderLength: return Metrics::Slider_ControlThickness;

621
            // checkboxes and radio buttons
622
623
624
625
            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;
626

627
            // list heaaders
628
            case PM_HeaderMarkSize: return Metrics::Header_ArrowSize;
629
            case PM_HeaderMargin: return Metrics::Header_MarginWidth;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
630

631
632
633
            // dock widget
            // return 0 here, since frame is handled directly in polish
            case PM_DockWidgetFrameWidth: return 0;
634
635
636
637
            case PM_DockWidgetTitleMargin: return Metrics::Frame_FrameWidth;
            case PM_DockWidgetTitleBarButtonMargin: return Metrics::ToolButton_MarginWidth;

            case PM_SplitterWidth: return Metrics::Splitter_SplitterWidth;
638
            case PM_DockWidgetSeparatorExtent: return Metrics::Splitter_SplitterWidth;
639

640
            // fallback
641
            default: return ParentStyleClass::pixelMetric( metric, option, widget );
642
643
644
645
646
647
648
649
650
651
652

        }

    }

    //______________________________________________________________
    int Style::styleHint( StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData ) const
    {
        switch( hint )
        {

653
654
655
            case SH_RubberBand_Mask:
            {

656
                if( auto mask = qstyleoption_cast<QStyleHintReturnMask*>( returnData ) )
657
658
659
660
                {

                    mask->region = option->rect;

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
661
662
663
664
665
666
                    /*
                     * 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
                     */
667
668
669
670
671
672
673
674
675
676
677
678
679
                    if( widget && (
                        qobject_cast<const QAbstractItemView*>( widget->parent() ) ||
                        qobject_cast<const QGraphicsView*>( widget->parent() ) ||
                        qobject_cast<const QMainWindow*>( widget->parent() ) ) )
                    { return true; }

                    // also check if widget's parent is some itemView viewport
                    if( widget && widget->parent() &&
                        qobject_cast<const QAbstractItemView*>( widget->parent()->parent() ) &&
                        static_cast<const QAbstractItemView*>( widget->parent()->parent() )->viewport() == widget->parent() )
                    { return true; }

                    // mask out center
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
680
                    mask->region -= insideMargin( option->rect, 1 );
681
682
683
684
685
686

                    return true;
                }
                return false;
            }

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
687
688
689
            case SH_ComboBox_ListMouseTracking: return true;
            case SH_MenuBar_MouseTracking: return true;
            case SH_Menu_MouseTracking: return true;
690
691
            case SH_Menu_SubMenuPopupDelay: return 150;
            case SH_Menu_SloppySubMenus: return true;
692

693
            // TODO Qt6: drop deprecated SH_Widget_Animate
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
694
            case SH_Widget_Animate: return StyleConfigData::animationsEnabled();
695
            case SH_Menu_SupportsSections: return true;
696
            case SH_Widget_Animation_Duration: return StyleConfigData::animationsEnabled() ? StyleConfigData::animationsDuration() : 0;
697

698
699
            case SH_DialogButtonBox_ButtonsHaveIcons: return true;

700
            case SH_GroupBox_TextLabelVerticalAlignment: return Qt::AlignVCenter;
701
            case SH_TabBar_Alignment: return StyleConfigData::tabBarDrawCenteredTabs() ? Qt::AlignCenter:Qt::AlignLeft;
702
            case SH_ToolBox_SelectedPageTitleBold: return false;
703
            case SH_ScrollBar_MiddleClickAbsolutePosition: return true;
704
            case SH_ScrollView_FrameOnlyAroundContents: return false;
705
706
707
708
709
            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;
710
711
            case SH_ProgressDialog_CenterCancelButton: return false;
            case SH_MessageBox_CenterButtons: return false;
712
713

            case SH_RequestSoftwareInputPanel: return RSIP_OnMouseClick;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
714
            case SH_TitleBar_NoBorder: return true;
715
            case SH_DockWidget_ButtonsHaveFrame: return false;
716
            default: return ParentStyleClass::styleHint( hint, option, widget, returnData );
717
718
719
720
721
722
723
724
725
726
727

        }

    }

    //______________________________________________________________
    QRect Style::subElementRect( SubElement element, const QStyleOption* option, const QWidget* widget ) const
    {
        switch( element )
        {

728
            case SE_PushButtonContents: return pushButtonContentsRect( option, widget );
729
            case SE_CheckBoxContents: return checkBoxContentsRect( option, widget );
730
            case SE_RadioButtonContents: return checkBoxContentsRect( option, widget );
731
            case SE_LineEditContents: return lineEditContentsRect( option, widget );
732
733
734
            case SE_ProgressBarGroove: return progressBarGrooveRect( option, widget );
            case SE_ProgressBarContents: return progressBarContentsRect( option, widget );
            case SE_ProgressBarLabel: return progressBarLabelRect( option, widget );
735
            case SE_FrameContents: return frameContentsRect( option, widget );
736
737
            case SE_HeaderArrow: return headerArrowRect( option, widget );
            case SE_HeaderLabel: return headerLabelRect( option, widget );
738
739
            case SE_TabBarTabLeftButton: return tabBarTabLeftButtonRect( option, widget );
            case SE_TabBarTabRightButton: return tabBarTabRightButtonRect( option, widget );
740
            case SE_TabWidgetTabBar: return tabWidgetTabBarRect( option, widget );
741
742
            case SE_TabWidgetTabContents: return tabWidgetTabContentsRect( option, widget );
            case SE_TabWidgetTabPane: return tabWidgetTabPaneRect( option, widget );
743
744
            case SE_TabWidgetLeftCorner: return tabWidgetCornerRect( SE_TabWidgetLeftCorner, option, widget );
            case SE_TabWidgetRightCorner: return tabWidgetCornerRect( SE_TabWidgetRightCorner, option, widget );
745
746
            case SE_ToolBoxTabContents: return toolBoxTabContentsRect( option, widget );

747
            // fallback
748
            default: return ParentStyleClass::subElementRect( element, option, widget );
749
750
751
752
753
754
755

        }
    }

    //______________________________________________________________
    QRect Style::subControlRect( ComplexControl element, const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget ) const
    {
756

757
758
759
        switch( element )
        {

760
            case CC_GroupBox: return groupBoxSubControlRect( option, subControl, widget );
761
            case CC_ToolButton: return toolButtonSubControlRect( option, subControl, widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
762
            case CC_ComboBox: return comboBoxSubControlRect( option, subControl, widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
763
            case CC_SpinBox: return spinBoxSubControlRect( option, subControl, widget );
764
            case CC_ScrollBar: return scrollBarSubControlRect( option, subControl, widget );
765
            case CC_Dial: return dialSubControlRect( option, subControl, widget );
766
            case CC_Slider: return sliderSubControlRect( option, subControl, widget );
767
768

            // fallback
769
            default: return ParentStyleClass::subControlRect( element, option, subControl, widget );
770
771
772
773
774
775
776
777
778
779
780

        }

    }

    //______________________________________________________________
    QSize Style::sizeFromContents( ContentsType element, const QStyleOption* option, const QSize& size, const QWidget* widget ) const
    {

        switch( element )
        {
781
782
            case CT_CheckBox: return checkBoxSizeFromContents( option, size, widget );
            case CT_RadioButton: return checkBoxSizeFromContents( option, size, widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
783
784
            case CT_LineEdit: return lineEditSizeFromContents( option, size, widget );
            case CT_ComboBox: return comboBoxSizeFromContents( option, size, widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
785
            case CT_SpinBox: return spinBoxSizeFromContents( option, size, widget );
786
            case CT_Slider: return sliderSizeFromContents( option, size, widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
787
            case CT_PushButton: return pushButtonSizeFromContents( option, size, widget );
788
            case CT_ToolButton: return toolButtonSizeFromContents( option, size, widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
789
790
            case CT_MenuBar: return defaultSizeFromContents( option, size, widget );
            case CT_MenuBarItem: return menuBarItemSizeFromContents( option, size, widget );
791
            case CT_MenuItem: return menuItemSizeFromContents( option, size, widget );
792
            case CT_ProgressBar: return progressBarSizeFromContents( option, size, widget );
793
            case CT_TabWidget: return tabWidgetSizeFromContents( option, size, widget );
794
            case CT_TabBarTab: return tabBarTabSizeFromContents( option, size, widget );
795
796
797
            case CT_HeaderSection: return headerSectionSizeFromContents( option, size, widget );
            case CT_ItemViewItem: return itemViewItemSizeFromContents( option, size, widget );

798
            // fallback
799
            default: return ParentStyleClass::sizeFromContents( element, option, size, widget );
800
801
802
803
804
805
806
807
808
809
810
811
        }

    }

    //______________________________________________________________
    QStyle::SubControl Style::hitTestComplexControl( ComplexControl control, const QStyleOptionComplex* option, const QPoint& point, const QWidget* widget ) const
    {
        switch( control )
        {
            case CC_ScrollBar:
            {

812
                auto grooveRect = subControlRect( CC_ScrollBar, option, SC_ScrollBarGroove, widget );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
813
                if( grooveRect.contains( point ) )
814
                {
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
815
                    // Must be either page up/page down, or just click on the slider.
816
                    auto sliderRect = subControlRect( CC_ScrollBar, option, SC_ScrollBarSlider, widget );
817

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
818
819
                    if( sliderRect.contains( point ) ) return SC_ScrollBarSlider;
                    else if( preceeds( point, sliderRect, option ) ) return SC_ScrollBarSubPage;
820
821
822
823
                    else return SC_ScrollBarAddPage;

                }

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
824
                // This is one of the up/down buttons. First, decide which one it is.
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
825
                if( preceeds( point, grooveRect, option ) )
826
827
828
829
                {

                    if( _subLineButtons == DoubleButton )
                    {
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
830

831
                        auto buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarSubLine );
832
                        return scrollBarHitTest( buttonRect, point, option );
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
833

834
835
836
837
838
839
840
                    } else return SC_ScrollBarSubLine;

                }

                if( _addLineButtons == DoubleButton )
                {

841
                    auto buttonRect = scrollBarInternalSubControlRect( option, SC_ScrollBarAddLine );
842
843
844
845
846
847
                    return scrollBarHitTest( buttonRect, point, option );

                } else return SC_ScrollBarAddLine;
            }

            // fallback
848
            default: return ParentStyleClass::hitTestComplexControl( control, option, point, widget );
849
850
851
852
853
854
855
856
857

        }

    }

    //______________________________________________________________
    void Style::drawPrimitive( PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
    {

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
858
        StylePrimitive fcn;
859
860
861
        switch( element )
        {

862
            case PE_PanelButtonCommand: fcn = &Style::drawPanelButtonCommandPrimitive; break;
863
            case PE_PanelButtonTool: fcn = &Style::drawPanelButtonToolPrimitive; break;
864
            case PE_PanelScrollAreaCorner: fcn = &Style::drawPanelScrollAreaCornerPrimitive; break;
865
866
            case PE_PanelMenu: fcn = &Style::drawPanelMenuPrimitive; break;
            case PE_PanelTipLabel: fcn = &Style::drawPanelTipLabelPrimitive; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
867
            case PE_PanelItemViewItem: fcn = &Style::drawPanelItemViewItemPrimitive; break;
868
869
            case PE_IndicatorCheckBox: fcn = &Style::drawIndicatorCheckBoxPrimitive; break;
            case PE_IndicatorRadioButton: fcn = &Style::drawIndicatorRadioButtonPrimitive; break;
870
            case PE_IndicatorButtonDropDown: fcn = &Style::drawIndicatorButtonDropDownPrimitive; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
871
            case PE_IndicatorTabClose: fcn = &Style::drawIndicatorTabClosePrimitive; break;
872
            case PE_IndicatorTabTear: fcn = &Style::drawIndicatorTabTearPrimitive; break;
873
874
875
876
            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;
877
            case PE_IndicatorHeaderArrow: fcn = &Style::drawIndicatorHeaderArrowPrimitive; break;
878
            case PE_IndicatorToolBarHandle: fcn = &Style::drawIndicatorToolBarHandlePrimitive; break;
879
            case PE_IndicatorToolBarSeparator: fcn = &Style::drawIndicatorToolBarSeparatorPrimitive; break;
880
            case PE_IndicatorBranch: fcn = &Style::drawIndicatorBranchPrimitive; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
881
882
            case PE_FrameStatusBar: fcn = &Style::emptyPrimitive; break;
            case PE_Frame: fcn = &Style::drawFramePrimitive; break;
883
            case PE_FrameLineEdit: fcn = &Style::drawFrameLineEditPrimitive; break;
884
            case PE_FrameMenu: fcn = &Style::drawFrameMenuPrimitive; break;
885
            case PE_FrameGroupBox: fcn = &Style::drawFrameGroupBoxPrimitive; break;
886
            case PE_FrameTabWidget: fcn = &Style::drawFrameTabWidgetPrimitive; break;
887
            case PE_FrameTabBarBase: fcn = &Style::drawFrameTabBarBasePrimitive; break;
888
            case PE_FrameWindow: fcn = &Style::drawFrameWindowPrimitive; break;
889
            case PE_FrameFocusRect: fcn = _frameFocusPrimitive; break;
890

891
            // fallback
892
            default: break;
893
894
895

        }

896
897
898
        painter->save();

        // call function if implemented
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
899
        if( !( fcn && fcn( *this, option, painter, widget ) ) )
900
        { ParentStyleClass::drawPrimitive( element, option, painter, widget ); }
901
902
903

        painter->restore();

904
905
906
907
908
909
    }

    //______________________________________________________________
    void Style::drawControl( ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
    {

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
910
        StyleControl fcn;
911

912
        #if BREEZE_HAVE_KSTYLE
913
        if( element == CE_CapacityBar )
914
        {
915
916
917
918
919
920
            fcn = &Style::drawProgressBarControl;

        } else
        #endif

        switch( element ) {
921

922
923
            case CE_PushButtonBevel: fcn = &Style::drawPanelButtonCommandPrimitive; break;
            case CE_PushButtonLabel: fcn = &Style::drawPushButtonLabelControl; break;
924
925
            case CE_CheckBoxLabel: fcn = &Style::drawCheckBoxLabelControl; break;
            case CE_RadioButtonLabel: fcn = &Style::drawCheckBoxLabelControl; break;
926
            case CE_ToolButtonLabel: fcn = &Style::drawToolButtonLabelControl; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
927
            case CE_ComboBoxLabel: fcn = &Style::drawComboBoxLabelControl; break;
928
            case CE_MenuBarEmptyArea: fcn = &Style::emptyControl; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
929
            case CE_MenuBarItem: fcn = &Style::drawMenuBarItemControl; break;
930
            case CE_MenuItem: fcn = &Style::drawMenuItemControl; break;
931
            case CE_ToolBar: fcn = &Style::emptyControl; break;
932
933
934
935
            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;
936
937
938
            case CE_ScrollBarSlider: fcn = &Style::drawScrollBarSliderControl; break;
            case CE_ScrollBarAddLine: fcn = &Style::drawScrollBarAddLineControl; break;
            case CE_ScrollBarSubLine: fcn = &Style::drawScrollBarSubLineControl; break;
939
940
            case CE_ScrollBarAddPage: fcn = &Style::emptyControl; break;
            case CE_ScrollBarSubPage: fcn = &Style::emptyControl; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
941
            case CE_ShapedFrame: fcn = &Style::drawShapedFrameControl; break;
942
            case CE_RubberBand: fcn = &Style::drawRubberBandControl; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
943
            case CE_SizeGrip: fcn = &Style::emptyControl; break;
944
945
            case CE_HeaderSection: fcn = &Style::drawHeaderSectionControl; break;
            case CE_HeaderEmptyArea: fcn = &Style::drawHeaderEmptyAreaControl; break;
946
            case CE_TabBarTabLabel: fcn = &Style::drawTabBarTabLabelControl; break;
947
            case CE_TabBarTabShape: fcn = &Style::drawTabBarTabShapeControl; break;
948
949
            case CE_ToolBoxTabLabel: fcn = &Style::drawToolBoxTabLabelControl; break;
            case CE_ToolBoxTabShape: fcn = &Style::drawToolBoxTabShapeControl; break;
950
951
            case CE_DockWidgetTitle: fcn = &Style::drawDockWidgetTitleControl; break;

952
953
954
955
956
957
958
959
            // fallback
            default: break;

        }

        painter->save();

        // call function if implemented
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
960
        if( !( fcn && fcn( *this, option, painter, widget ) ) )
961
        { ParentStyleClass::drawControl( element, option, painter, widget ); }
962
963
964
965
966
967
968
969
970

        painter->restore();

    }

    //______________________________________________________________
    void Style::drawComplexControl( ComplexControl element, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const
    {

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
971
        StyleComplexControl fcn;
972
973
        switch( element )
        {
974
            case CC_GroupBox: fcn = &Style::drawGroupBoxComplexControl; break;
975
            case CC_ToolButton: fcn = &Style::drawToolButtonComplexControl; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
976
            case CC_ComboBox: fcn = &Style::drawComboBoxComplexControl; break;
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
977
            case CC_SpinBox: fcn = &Style::drawSpinBoxComplexControl; break;
978
            case CC_Slider: fcn = &Style::drawSliderComplexControl; break;
979
            case CC_Dial: fcn = &Style::drawDialComplexControl; break;
980
            case CC_ScrollBar: fcn = &Style::drawScrollBarComplexControl; break;
981
            case CC_TitleBar: fcn = &Style::drawTitleBarComplexControl; break;
982

983
            // fallback
984
            default: break;
985
986
        }

987
988
989
990

        painter->save();

        // call function if implemented
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
991
        if( !( fcn && fcn( *this, option, painter, widget ) ) )
992
        { ParentStyleClass::drawComplexControl( element, option, painter, widget ); }
993
994
995

        painter->restore();

996
997
998
999
1000
    }


    //___________________________________________________________________________________
    void Style::drawItemText(
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
1001
        QPainter* painter, const QRect& rect, int flags, const QPalette& palette, bool enabled,
1002
1003
1004
        const QString &text, QPalette::ColorRole textRole ) const
    {

1005
        // hide mnemonics if requested
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
1006
        if( !_mnemonics->enabled() && ( flags&Qt::TextShowMnemonic ) && !( flags&Qt::TextHideMnemonic ) )
1007
1008
1009
1010
1011
        {
            flags &= ~Qt::TextShowMnemonic;
            flags |= Qt::TextHideMnemonic;
        }

1012
1013
1014
1015
        // make sure vertical alignment is defined
        // fallback on Align::VCenter if not
        if( !(flags&Qt::AlignVertical_Mask) ) flags |= Qt::AlignVCenter;

1016
1017
1018
1019
        if( _animations->widgetEnabilityEngine().enabled() )
        {

            /*
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
1020
1021
1022
1023
             * 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.
             */
1024
1025
1026
1027
            const QWidget* widget( static_cast<const QWidget*>( painter->device() ) );
            if( _animations->widgetEnabilityEngine().isAnimated( widget, AnimationEnable ) )
            {

Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
1028
1029
                const QPalette copy( _helper->disabledPalette( palette, _animations->widgetEnabilityEngine().opacity( widget, AnimationEnable ) ) );
                return ParentStyleClass::drawItemText( painter, rect, flags, copy, enabled, text, textRole );
1030
1031
1032
1033
1034

            }

        }

1035
        // fallback
Hugo Pereira Da Costa's avatar
Hugo Pereira Da Costa committed
1036
        return ParentStyleClass::drawItemText( painter, rect, flags, palette, enabled, text, textRole );
1037
1038
1039
1040
1041
1042

    }

    //_____________________________________________________________________
    bool Style::eventFilter( QObject *object, QEvent *event )
    {
1043

1044
1045
1046
        if( auto dockWidget = qobject_cast<QDockWidget*>( object ) ) { return eventFilterDockWidget( dockWidget, event ); }
        else if( auto subWindow = qobject_cast<QMdiSubWindow*>( object ) ) { return eventFilterMdiSubWindow( subWindow, event ); }
        else if( auto commandLinkButton = qobject_cast<QCommandLinkButton*>( object ) ) { return eventFilterCommandLinkButton( commandLinkButton, event ); }
1047
1048
1049
        #if QT_VERSION < 0x050D00 // Check if Qt version < 5.13
        else if( object == qApp && event->type() == QEvent::ApplicationPaletteChange ) { configurationChanged(); }
        #endif