manhattanstyle.cpp 38.4 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
**
hjk's avatar
hjk committed
24
25
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
con's avatar
con committed
29
30

#include "manhattanstyle.h"
hjk's avatar
hjk committed
31

con's avatar
con committed
32
#include "styleanimator.h"
hjk's avatar
hjk committed
33

34
35
#include <coreplugin/coreconstants.h>

36
#include <utils/hostosinfo.h>
37
38
#include <utils/stylehelper.h>

39
40
#include <utils/fancymainwindow.h>

41
42
43
44
45
#include <QApplication>
#include <QComboBox>
#include <QDockWidget>
#include <QLabel>
#include <QLineEdit>
46
#include <QMenuBar>
47
48
49
50
51
52
53
#include <QPainter>
#include <QPixmap>
#include <QStatusBar>
#include <QStyleFactory>
#include <QStyleOption>
#include <QToolBar>
#include <QToolButton>
hjk's avatar
hjk committed
54

con's avatar
con committed
55
// We define a currently unused state for indicating animations
56
const QStyle::State State_Animating = QStyle::State(0x00000040);
con's avatar
con committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

// Because designer needs to disable this for widget previews
// we have a custom property that is inherited
bool styleEnabled(const QWidget *widget)
{
    const QWidget *p = widget;
    while (p) {
        if (p->property("_q_custom_style_disabled").toBool())
            return false;
            p = p->parentWidget();
    }
    return true;
}

// Consider making this a QStyle state
bool panelWidget(const QWidget *widget)
{
74
75
76
    if (!widget)
        return false;

Tobias Hunger's avatar
Tobias Hunger committed
77
    // Do not style dialogs or explicitly ignored widgets
78
    if ((widget->window()->windowFlags() & Qt::WindowType_Mask) == Qt::Dialog)
79
        return false;
con's avatar
con committed
80

81
82
83
    if (qobject_cast<const Utils::FancyMainWindow *>(widget))
        return true;

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
84
85
86
    if (qobject_cast<const QTabBar *>(widget))
        return styleEnabled(widget);

87
    const QWidget *p = widget;
con's avatar
con committed
88
    while (p) {
89
90
        if (qobject_cast<const QToolBar *>(p) ||
            qobject_cast<const QStatusBar *>(p) ||
91
            qobject_cast<const QMenuBar *>(p) ||
92
            p->property("panelwidget").toBool())
93
            return styleEnabled(widget);
con's avatar
con committed
94
95
96
97
98
        p = p->parentWidget();
    }
    return false;
}

99
100
101
102
103
104
105
// Consider making this a QStyle state
bool lightColored(const QWidget *widget)
{
    if (!widget)
        return false;

    // Don't style dialogs or explicitly ignored widgets
106
    if ((widget->window()->windowFlags() & Qt::WindowType_Mask) == Qt::Dialog)
107
108
109
110
111
112
113
114
115
116
117
        return false;

    const QWidget *p = widget;
    while (p) {
        if (p->property("lightColored").toBool())
            return true;
        p = p->parentWidget();
    }
    return false;
}

con's avatar
con committed
118
119
120
class ManhattanStylePrivate
{
public:
121
    explicit ManhattanStylePrivate();
con's avatar
con committed
122
    void init();
hjk's avatar
hjk committed
123
124

public:
125
126
127
128
    const QImage lineeditImage;
    const QImage lineeditImage_disabled;
    const QPixmap extButtonPixmap;
    const QPixmap closeButtonPixmap;
con's avatar
con committed
129
130
131
    StyleAnimator animator;
};

132
ManhattanStylePrivate::ManhattanStylePrivate() :
133
134
135
    lineeditImage(QLatin1String(":/core/images/inputfield.png")),
    lineeditImage_disabled(QLatin1String(":/core/images/inputfield_disabled.png")),
    extButtonPixmap(QLatin1String(":/core/images/extension.png")),
136
    closeButtonPixmap(QLatin1String(Core::Constants::ICON_CLOSE))
137
138
139
{
}

con's avatar
con committed
140
ManhattanStyle::ManhattanStyle(const QString &baseStyleName)
141
142
    : QProxyStyle(QStyleFactory::create(baseStyleName)),
    d(new ManhattanStylePrivate())
con's avatar
con committed
143
144
145
146
147
148
149
150
151
152
153
{
}

ManhattanStyle::~ManhattanStyle()
{
    delete d;
    d = 0;
}

QPixmap ManhattanStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
{
154
    return QProxyStyle::generatedIconPixmap(iconMode, pixmap, opt);
con's avatar
con committed
155
156
157
158
159
}

QSize ManhattanStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
                                       const QSize &size, const QWidget *widget) const
{
160
    QSize newSize = QProxyStyle::sizeFromContents(type, option, size, widget);
161

con's avatar
con committed
162
163
    if (type == CT_Splitter && widget && widget->property("minisplitter").toBool())
        return QSize(1, 1);
164
    else if (type == CT_ComboBox && panelWidget(widget))
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
165
        newSize += QSize(14, 0);
166
    return newSize;
con's avatar
con committed
167
168
169
170
}

QRect ManhattanStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
171
    return QProxyStyle::subElementRect(element, option, widget);
con's avatar
con committed
172
173
174
175
176
}

QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
                                     SubControl subControl, const QWidget *widget) const
{
177
    return QProxyStyle::subControlRect(control, option, subControl, widget);
con's avatar
con committed
178
179
180
181
182
}

QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                                         const QPoint &pos, const QWidget *widget) const
{
183
    return QProxyStyle::hitTestComplexControl(control, option, pos, widget);
con's avatar
con committed
184
185
186
187
188
}

int ManhattanStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
    int retval = 0;
189
    retval = QProxyStyle::pixelMetric(metric, option, widget);
con's avatar
con committed
190
191
192
193
194
195
196
197
198
    switch (metric) {
    case PM_SplitterWidth:
        if (widget && widget->property("minisplitter").toBool())
            retval = 1;
        break;
    case PM_ToolBarIconSize:
        if (panelWidget(widget))
            retval = 16;
        break;
199
    case PM_DockWidgetHandleExtent:
200
201
    case PM_DockWidgetSeparatorExtent:
        return 1;
202
203
204
    case PM_MenuPanelWidth:
    case PM_MenuBarHMargin:
    case PM_MenuBarVMargin:
con's avatar
con committed
205
206
207
208
209
210
    case PM_ToolBarFrameWidth:
        if (panelWidget(widget))
            retval = 1;
        break;
    case PM_ButtonShiftVertical:
    case PM_ButtonShiftHorizontal:
211
    case PM_MenuBarPanelWidth:
con's avatar
con committed
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
    case PM_ToolBarItemMargin:
    case PM_ToolBarItemSpacing:
        if (panelWidget(widget))
            retval = 0;
        break;
    case PM_DefaultFrameWidth:
        if (qobject_cast<const QLineEdit*>(widget) && panelWidget(widget))
            return 1;
        break;
    default:
        break;
    }
    return retval;
}

QPalette ManhattanStyle::standardPalette() const
{
229
    return QProxyStyle::standardPalette();
con's avatar
con committed
230
231
232
233
}

void ManhattanStyle::polish(QApplication *app)
{
234
    return QProxyStyle::polish(app);
con's avatar
con committed
235
236
237
238
}

void ManhattanStyle::unpolish(QApplication *app)
{
239
    return QProxyStyle::unpolish(app);
con's avatar
con committed
240
241
}

242
QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false)
con's avatar
con committed
243
{
244
    QColor color = Utils::StyleHelper::panelTextColor(lightColored);
con's avatar
con committed
245
246
247
248
249
250
251
252
253
254
255
256
257
    QPalette pal = oldPalette;
    pal.setBrush(QPalette::All, QPalette::WindowText, color);
    pal.setBrush(QPalette::All, QPalette::ButtonText, color);
    pal.setBrush(QPalette::All, QPalette::Foreground, color);
    color.setAlpha(100);
    pal.setBrush(QPalette::Disabled, QPalette::WindowText, color);
    pal.setBrush(QPalette::Disabled, QPalette::ButtonText, color);
    pal.setBrush(QPalette::Disabled, QPalette::Foreground, color);
    return pal;
}

void ManhattanStyle::polish(QWidget *widget)
{
258
    QProxyStyle::polish(widget);
con's avatar
con committed
259

260
    // OxygenStyle forces a rounded widget mask on toolbars and dock widgets
Daniel Teske's avatar
Daniel Teske committed
261
    if (baseStyle()->inherits("OxygenStyle") || baseStyle()->inherits("Oxygen::Style")) {
262
        if (qobject_cast<QToolBar*>(widget) || qobject_cast<QDockWidget*>(widget)) {
263
            widget->removeEventFilter(baseStyle());
264
265
            widget->setContentsMargins(0, 0, 0, 0);
        }
con's avatar
con committed
266
267
    }
    if (panelWidget(widget)) {
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
268
269
270
271
272

        // Oxygen and possibly other styles override this
        if (qobject_cast<QDockWidget*>(widget))
            widget->setContentsMargins(0, 0, 0, 0);

con's avatar
con committed
273
        widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
con's avatar
con committed
274
275
        if (qobject_cast<QToolButton*>(widget)) {
            widget->setAttribute(Qt::WA_Hover);
276
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
277
        } else if (qobject_cast<QLineEdit*>(widget)) {
con's avatar
con committed
278
            widget->setAttribute(Qt::WA_Hover);
279
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
280
        } else if (qobject_cast<QLabel*>(widget)) {
con's avatar
con committed
281
            widget->setPalette(panelPalette(widget->palette()));
282
        } else if (widget->property("panelwidget_singlerow").toBool()) {
283
            widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight());
284
        } else if (qobject_cast<QStatusBar*>(widget)) {
285
            widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight() + 2);
286
        } else if (qobject_cast<QComboBox*>(widget)) {
287
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
288
289
            widget->setAttribute(Qt::WA_Hover);
        }
con's avatar
con committed
290
291
292
293
294
    }
}

void ManhattanStyle::unpolish(QWidget *widget)
{
295
    QProxyStyle::unpolish(widget);
con's avatar
con committed
296
    if (panelWidget(widget)) {
con's avatar
con committed
297
        widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
con's avatar
con committed
298
299
300
301
        if (qobject_cast<QTabBar*>(widget))
            widget->setAttribute(Qt::WA_Hover, false);
        else if (qobject_cast<QToolBar*>(widget))
            widget->setAttribute(Qt::WA_Hover, false);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
302
303
        else if (qobject_cast<QComboBox*>(widget))
            widget->setAttribute(Qt::WA_Hover, false);
con's avatar
con committed
304
305
306
307
308
    }
}

void ManhattanStyle::polish(QPalette &pal)
{
309
    QProxyStyle::polish(pal);
con's avatar
con committed
310
311
}

312
QIcon ManhattanStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
con's avatar
con committed
313
314
315
316
{
    QIcon icon;
    switch (standardIcon) {
    case QStyle::SP_TitleBarCloseButton:
317
318
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        return QIcon(standardPixmap(standardIcon, option, widget));
con's avatar
con committed
319
    default:
320
        icon = baseStyle()->standardIcon(standardIcon, option, widget);
con's avatar
con committed
321
322
323
324
325
326
327
    }
    return icon;
}

QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
                                       const QWidget *widget) const
{
328
    if (widget && !panelWidget(widget))
329
        return QProxyStyle::standardPixmap(standardPixmap, opt, widget);
330

con's avatar
con committed
331
332
    QPixmap pixmap;
    switch (standardPixmap) {
333
334
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        pixmap = d->extButtonPixmap;
335
        break;
336
337
    case QStyle::SP_TitleBarCloseButton:
        pixmap = d->closeButtonPixmap;
con's avatar
con committed
338
339
        break;
    default:
340
        pixmap = QProxyStyle::standardPixmap(standardPixmap, opt, widget);
341
        break;
con's avatar
con committed
342
343
344
345
346
347
348
    }
    return pixmap;
}

int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
                              QStyleHintReturn *returnData) const
{
349
    int ret = QProxyStyle::styleHint(hint, option, widget, returnData);
con's avatar
con committed
350
    switch (hint) {
351
352
353
354
355
    // Make project explorer alternate rows all the way
    case QStyle::SH_ItemView_PaintAlternatingRowColorsForEmptyArea:
        if (widget && widget->property("AlternateEmpty").toBool())
            ret = true;
        break;
con's avatar
con committed
356
    case QStyle::SH_EtchDisabledText:
357
358
        if (panelWidget(widget))
            ret = false;
con's avatar
con committed
359
        break;
360
361
362
    case QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren:
        ret = true;
        break;
con's avatar
con committed
363
    default:
364
        break;
con's avatar
con committed
365
366
367
368
369
370
371
372
    }
    return ret;
}

void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                                   QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
373
        return QProxyStyle::drawPrimitive(element, option, painter, widget);
con's avatar
con committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

    bool animating = (option->state & State_Animating);
    int state = option->state;
    QRect rect = option->rect;
    QRect oldRect;
    QRect newRect;
    if (widget && (element == PE_PanelButtonTool) && !animating) {
        QWidget *w = const_cast<QWidget *> (widget);
        int oldState = w->property("_q_stylestate").toInt();
        oldRect = w->property("_q_stylerect").toRect();
        newRect = w->rect();
        w->setProperty("_q_stylestate", (int)option->state);
        w->setProperty("_q_stylerect", w->rect());

        // Determine the animated transition
        bool doTransition = ((state & State_On)         != (oldState & State_On)     ||
                             (state & State_MouseOver)  != (oldState & State_MouseOver));
        if (oldRect != newRect)
        {
            doTransition = false;
            d->animator.stopAnimation(widget);
        }

        if (doTransition) {
            QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
            QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
            Animation *anim = d->animator.widgetAnimation(widget);
            QStyleOption opt = *option;
            opt.state = (QStyle::State)oldState;
403
            opt.state |= State_Animating;
con's avatar
con committed
404
405
406
407
408
409
410
411
412
413
414
            startImage.fill(0);
            Transition *t = new Transition;
            t->setWidget(w);
            QPainter startPainter(&startImage);
            if (!anim) {
                drawPrimitive(element, &opt, &startPainter, widget);
            } else {
                anim->paint(&startPainter, &opt);
                d->animator.stopAnimation(widget);
            }
            QStyleOption endOpt = *option;
415
            endOpt.state |= State_Animating;
con's avatar
con committed
416
417
418
419
420
421
            t->setStartImage(startImage);
            d->animator.startAnimation(t);
            endImage.fill(0);
            QPainter endPainter(&endImage);
            drawPrimitive(element, &endOpt, &endPainter, widget);
            t->setEndImage(endImage);
422
423
424
425
            if (oldState & State_MouseOver)
                t->setDuration(150);
            else
                t->setDuration(75);
con's avatar
con committed
426
427
428
429
430
            t->setStartTime(QTime::currentTime());
        }
    }

    switch (element) {
431
432
433
434
435
436
    case PE_IndicatorDockWidgetResizeHandle:
        painter->fillRect(option->rect, Utils::StyleHelper::borderColor());
        break;
    case PE_FrameDockWidget:
        QCommonStyle::drawPrimitive(element, option, painter, widget);
        break;
con's avatar
con committed
437
438
439
    case PE_PanelLineEdit:
        {
            painter->save();
440
441
442
443
444
445

            // Fill the line edit background
            QRect filledRect = option->rect.adjusted(1, 1, -1, -1);
            painter->setBrushOrigin(filledRect.topLeft());
            painter->fillRect(filledRect, option->palette.base());

con's avatar
con committed
446
            if (option->state & State_Enabled)
447
                Utils::StyleHelper::drawCornerImage(d->lineeditImage, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
448
            else
449
                Utils::StyleHelper::drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
450
451

            if (option->state & State_HasFocus || option->state & State_MouseOver) {
452
                QColor hover = Utils::StyleHelper::baseColor();
con's avatar
con committed
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
                if (state & State_HasFocus)
                    hover.setAlpha(100);
                else
                    hover.setAlpha(50);

                painter->setPen(QPen(hover, 1));
                painter->drawRect(option->rect.adjusted(1, 1, -2 ,-2));
            }
            painter->restore();
        }
        break;

    case PE_FrameStatusBarItem:
        break;

    case PE_PanelButtonTool: {
            Animation *anim = d->animator.widgetAnimation(widget);
            if (!animating && anim) {
                anim->paint(painter, option);
            } else {
                bool pressed = option->state & State_Sunken || option->state & State_On;
                QColor shadow(0, 0, 0, 30);
                painter->setPen(shadow);
                if (pressed) {
477
478
479
                    QColor shade(0, 0, 0, 40);
                    painter->fillRect(rect, shade);
                    painter->drawLine(rect.topLeft() + QPoint(1, 0), rect.topRight() - QPoint(1, 0));
con's avatar
con committed
480
                    painter->drawLine(rect.topLeft(), rect.bottomLeft());
481
482
                    painter->drawLine(rect.topRight(), rect.bottomRight());
                   // painter->drawLine(rect.bottomLeft()  + QPoint(1, 0), rect.bottomRight()  - QPoint(1, 0));
con's avatar
con committed
483
484
                    QColor highlight(255, 255, 255, 30);
                    painter->setPen(highlight);
485
                } else if (option->state & State_Enabled && option->state & State_MouseOver) {
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
486
                    QColor lighter(255, 255, 255, 37);
con's avatar
con committed
487
                    painter->fillRect(rect, lighter);
488
489
490
                } else if (widget && widget->property("highlightWidget").toBool()) {
                    QColor shade(0, 0, 0, 128);
                    painter->fillRect(rect, shade);
con's avatar
con committed
491
                }
492
493
494
495
496
497
498
499
500
501
502
                if (option->state & State_HasFocus && (option->state & State_KeyboardFocusChange)) {
                    QColor highlight = option->palette.highlight().color();
                    highlight.setAlphaF(0.4);
                    painter->setPen(QPen(highlight.lighter(), 1));
                    highlight.setAlphaF(0.3);
                    painter->setBrush(highlight);
                    painter->setRenderHint(QPainter::Antialiasing);
                    QRectF rect = option->rect;
                    rect.translate(0.5, 0.5);
                    painter->drawRoundedRect(rect.adjusted(2, 2, -3, -3), 2, 2);
                }
con's avatar
con committed
503
504
505
506
507
508
509
           }
        }
        break;

    case PE_PanelStatusBar:
        {
            painter->save();
510
511
            QLinearGradient grad = Utils::StyleHelper::statusBarGradient(rect);
            painter->fillRect(rect, grad);
con's avatar
con committed
512
513
514
            painter->setPen(QColor(255, 255, 255, 60));
            painter->drawLine(rect.topLeft() + QPoint(0,1),
                              rect.topRight()+ QPoint(0,1));
515
            painter->setPen(Utils::StyleHelper::borderColor().darker(110));
con's avatar
con committed
516
517
518
519
520
521
522
            painter->drawLine(rect.topLeft(), rect.topRight());
            painter->restore();
        }
        break;

    case PE_IndicatorToolBarSeparator:
        {
523
            QColor separatorColor = Utils::StyleHelper::borderColor();
con's avatar
con committed
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
            separatorColor.setAlpha(100);
            painter->setPen(separatorColor);
            const int margin = 6;
            if (option->state & State_Horizontal) {
                const int offset = rect.width()/2;
                painter->drawLine(rect.bottomLeft().x() + offset,
                            rect.bottomLeft().y() - margin,
                            rect.topLeft().x() + offset,
                            rect.topLeft().y() + margin);
            } else { //Draw vertical separator
                const int offset = rect.height()/2;
                painter->setPen(QPen(option->palette.background().color().darker(110)));
                painter->drawLine(rect.topLeft().x() + margin ,
                            rect.topLeft().y() + offset,
                            rect.topRight().x() - margin,
                            rect.topRight().y() + offset);
            }
        }
        break;

    case PE_IndicatorToolBarHandle:
        {
            bool horizontal = option->state & State_Horizontal;
            painter->save();
            QPainterPath path;
549
550
            int x = option->rect.x() + (horizontal ? 2 : 6);
            int y = option->rect.y() + (horizontal ? 6 : 2);
con's avatar
con committed
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
            static const int RectHeight = 2;
            if (horizontal) {
                while (y < option->rect.height() - RectHeight - 6) {
                    path.moveTo(x, y);
                    path.addRect(x, y, RectHeight, RectHeight);
                    y += 6;
                }
            } else {
                while (x < option->rect.width() - RectHeight - 6) {
                    path.moveTo(x, y);
                    path.addRect(x, y, RectHeight, RectHeight);
                    x += 6;
                }
            }

            painter->setPen(Qt::NoPen);
567
            QColor dark = Utils::StyleHelper::borderColor();
con's avatar
con committed
568
569
            dark.setAlphaF(0.4);

570
            QColor light = Utils::StyleHelper::baseColor();
con's avatar
con committed
571
572
573
574
575
576
577
578
579
580
581
582
583
584
            light.setAlphaF(0.4);

            painter->fillPath(path, light);
            painter->save();
            painter->translate(1, 1);
            painter->fillPath(path, dark);
            painter->restore();
            painter->translate(3, 3);
            painter->fillPath(path, light);
            painter->translate(1, 1);
            painter->fillPath(path, dark);
            painter->restore();
        }
        break;
585
586
587
588
589
    case PE_IndicatorArrowUp:
    case PE_IndicatorArrowDown:
    case PE_IndicatorArrowRight:
    case PE_IndicatorArrowLeft:
        {
590
            Utils::StyleHelper::drawArrow(element, painter, option);
591
592
        }
        break;
con's avatar
con committed
593
594

    default:
595
        QProxyStyle::drawPrimitive(element, option, painter, widget);
con's avatar
con committed
596
597
598
599
600
601
602
603
        break;
    }
}

void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option,
                                 QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
604
        return QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
605
606

    switch (element) {
607
608
609
610
611
612
613
614
615
616
    case CE_Splitter:
        painter->fillRect(option->rect, Utils::StyleHelper::borderColor());
        break;

    case CE_TabBarTabShape:
        // Most styles draw a single dark outline. This looks rather ugly when combined with our
        // single pixel dark separator so we adjust the first tab to compensate for this

        if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
            QStyleOptionTabV3 adjustedTab = *tab;
617
618
619
620
            if (tab->cornerWidgets == QStyleOptionTab::NoCornerWidgets && (
                    tab->position == QStyleOptionTab::Beginning ||
                    tab->position == QStyleOptionTab::OnlyOneTab))
            {
621
622
623
624
625
626
627
628
629
630
                if (option->direction == Qt::LeftToRight)
                    adjustedTab.rect = adjustedTab.rect.adjusted(-1, 0, 0, 0);
                else
                    adjustedTab.rect = adjustedTab.rect.adjusted(0, 0, 1 ,0);
            }
            QProxyStyle::drawControl(element, &adjustedTab, painter, widget);
            return;
        }
        break;

631
632
633
634
    case CE_MenuBarItem:
        painter->save();
        if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
            QColor highlightOutline = Utils::StyleHelper::borderColor().lighter(120);
635
            bool act = mbi->state & State_Sunken;
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
            bool dis = !(mbi->state & State_Enabled);
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
            QStyleOptionMenuItem item = *mbi;
            item.rect = mbi->rect;
            QPalette pal = mbi->palette;
            pal.setBrush(QPalette::ButtonText, dis ? Qt::gray : Qt::black);
            item.palette = pal;
            QCommonStyle::drawControl(element, &item, painter, widget);
            QRect r = option->rect;

            if (act) {
                // Fill|
                QColor baseColor = Utils::StyleHelper::baseColor();
                QLinearGradient grad(option->rect.topLeft(), option->rect.bottomLeft());
                grad.setColorAt(0, baseColor.lighter(120));
                grad.setColorAt(1, baseColor.lighter(130));
                painter->fillRect(option->rect.adjusted(1, 1, -1, 0), grad);

                // Outline
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom()));
                painter->drawLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom()));
                painter->drawLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top()));
                highlightOutline.setAlpha(60);
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawPoint(r.topLeft());
                painter->drawPoint(r.topRight());

                QPalette pal = mbi->palette;
                uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
                if (!styleHint(SH_UnderlineShortcut, mbi, widget))
                    alignment |= Qt::TextHideMnemonic;
                pal.setBrush(QPalette::Text, dis ? Qt::gray : QColor(0, 0, 0, 60));
                drawItemText(painter, item.rect.translated(0, 1), alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
                pal.setBrush(QPalette::Text, dis ? Qt::gray : Qt::white);
                drawItemText(painter, item.rect, alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
            }
        }
        painter->restore();
        break;

con's avatar
con committed
677
678
679
    case CE_ComboBoxLabel:
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
            if (panelWidget(widget)) {
680
                painter->save();
con's avatar
con committed
681
682
                QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
                QPalette customPal = cb->palette;
683
                bool drawIcon = !(widget && widget->property("hideicon").toBool());
con's avatar
con committed
684

685
                if (!cb->currentIcon.isNull() && drawIcon) {
con's avatar
con committed
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
                    QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
                                                                 : QIcon::Disabled;
                    QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
                    QRect iconRect(editRect);
                    iconRect.setWidth(cb->iconSize.width() + 4);
                    iconRect = alignedRect(cb->direction,
                                           Qt::AlignLeft | Qt::AlignVCenter,
                                           iconRect.size(), editRect);
                    if (cb->editable)
                        painter->fillRect(iconRect, customPal.brush(QPalette::Base));
                    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);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
702
703
704

                    // Reserve some space for the down-arrow
                    editRect.adjust(0, 0, -13, 0);
con's avatar
con committed
705
706
                }

707
708
709
710
711
712
713
714
715
716
717
718
719
720
                QLatin1Char asterisk('*');
                int elideWidth = editRect.width();

                bool notElideAsterisk = widget && widget->property("notelideasterisk").toBool()
                                        && cb->currentText.endsWith(asterisk)
                                        && option->fontMetrics.width(cb->currentText) > elideWidth;

                QString text;
                if (notElideAsterisk) {
                    elideWidth -= option->fontMetrics.width(asterisk);
                    text = asterisk;
                }
                text.prepend(option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, elideWidth));

721
722
                if ((option->state & State_Enabled)) {
                    painter->setPen(QColor(0, 0, 0, 70));
723
                    painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
724
                } else {
725
                    painter->setOpacity(0.8);
726
727
                }
                painter->setPen(Utils::StyleHelper::panelTextColor());
728
                painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
729
730

                painter->restore();
con's avatar
con committed
731
            } else {
732
                QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
            }
        }
        break;

    case CE_SizeGrip: {
            painter->save();
            QColor dark = Qt::white;
            dark.setAlphaF(0.1);
            int x, y, w, h;
            option->rect.getRect(&x, &y, &w, &h);
            int sw = qMin(h, w);
            if (h > w)
                painter->translate(0, h - w);
            else
                painter->translate(w - h, 0);
            int sx = x;
            int sy = y;
            int s = 4;
            painter->setPen(dark);
            if (option->direction == Qt::RightToLeft) {
                sx = x + sw;
                for (int i = 0; i < 4; ++i) {
                    painter->drawLine(x, sy, sx, sw);
                    sx -= s;
                    sy += s;
                }
            } else {
                for (int i = 0; i < 4; ++i) {
                    painter->drawLine(sx, sw, sw, sy);
                    sx += s;
                    sy += s;
                }
            }
            painter->restore();
        }
        break;

770
771
772
773
774
775
776
777
778
    case CE_MenuBarEmptyArea: {
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
            painter->save();
            painter->setPen(Utils::StyleHelper::borderColor());
            painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
            painter->restore();
        }
        break;

con's avatar
con committed
779
780
781
    case CE_ToolBar:
        {
            QRect rect = option->rect;
782
            bool horizontal = option->state & State_Horizontal;
783
784
785
786
787
788
789
790
791
792
793
794
795

            // Map offset for global window gradient
            QPoint offset = widget->window()->mapToGlobal(option->rect.topLeft()) -
                            widget->mapToGlobal(option->rect.topLeft());
            QRect gradientSpan;
            if (widget)
                gradientSpan = QRect(offset, widget->window()->size());

            bool drawLightColored = lightColored(widget);
            if (horizontal)
                Utils::StyleHelper::horizontalGradient(painter, gradientSpan, rect, drawLightColored);
            else
                Utils::StyleHelper::verticalGradient(painter, gradientSpan, rect, drawLightColored);
con's avatar
con committed
796

797
798
799
800
            if (!drawLightColored)
                painter->setPen(Utils::StyleHelper::borderColor());
            else
                painter->setPen(QColor(0x888888));
con's avatar
con committed
801
802

            if (horizontal) {
803
804
805
                // Note: This is a hack to determine if the
                // toolbar should draw the top or bottom outline
                // (needed for the find toolbar for instance)
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
806
                QColor lighter(Utils::StyleHelper::sidebarHighlight());
807
808
                if (drawLightColored)
                    lighter = QColor(255, 255, 255, 180);
809
                if (widget && widget->property("topBorder").toBool()) {
810
811
812
                    painter->drawLine(rect.topLeft(), rect.topRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1));
con's avatar
con committed
813
                } else {
814
815
816
                    painter->drawLine(rect.bottomLeft(), rect.bottomRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft(), rect.topRight());
con's avatar
con committed
817
818
                }
            } else {
819
820
                painter->drawLine(rect.topLeft(), rect.bottomLeft());
                painter->drawLine(rect.topRight(), rect.bottomRight());
con's avatar
con committed
821
822
823
            }
        }
        break;
824

con's avatar
con committed
825
    default:
826
        QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
827
828
829
830
831
832
833
834
        break;
    }
}

void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                        QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
835
         return     QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
836
837
838
839
840

    QRect rect = option->rect;
    switch (control) {
    case CC_ToolButton:
        if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
841
842
843
844
845
846
            bool reverse = option->direction == Qt::RightToLeft;
            bool drawborder = (widget && widget->property("showborder").toBool());

            if (drawborder)
                drawButtonSeparator(painter, rect, reverse);

con's avatar
con committed
847
848
849
850
851
852
            QRect button, menuarea;
            button = subControlRect(control, toolbutton, SC_ToolButton, widget);
            menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);

            State bflags = toolbutton->state;
            if (bflags & State_AutoRaise) {
853
                if (!(bflags & State_MouseOver))
con's avatar
con committed
854
855
856
857
                    bflags &= ~State_Raised;
            }

            State mflags = bflags;
858
859
860
861
862
863
            if (toolbutton->state & State_Sunken) {
                if (toolbutton->activeSubControls & SC_ToolButton)
                    bflags |= State_Sunken;
                if (toolbutton->activeSubControls & SC_ToolButtonMenu)
                    mflags |= State_Sunken;
            }
con's avatar
con committed
864
865
866
867

            QStyleOption tool(0);
            tool.palette = toolbutton->palette;
            if (toolbutton->subControls & SC_ToolButton) {
868
869
870
                tool.rect = button;
                tool.state = bflags;
                drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
con's avatar
con committed
871
872
873
            }

            QStyleOptionToolButton label = *toolbutton;
874
875

            label.palette = panelPalette(option->palette, lightColored(widget));
876
877
            if (widget && widget->property("highlightWidget").toBool())
                label.palette.setColor(QPalette::ButtonText, Qt::red);
con's avatar
con committed
878
879
            int fw = pixelMetric(PM_DefaultFrameWidth, option, widget);
            label.rect = button.adjusted(fw, fw, -fw, -fw);
880

con's avatar
con committed
881
882
883
884
885
886
887
888
889
890
891
            drawControl(CE_ToolButtonLabel, &label, painter, widget);

            if (toolbutton->subControls & SC_ToolButtonMenu) {
                tool.state = mflags;
                tool.rect = menuarea.adjusted(1, 1, -1, -1);
                if (mflags & (State_Sunken | State_On | State_Raised)) {
                    painter->setPen(Qt::gray);
                    painter->drawLine(tool.rect.topLeft(), tool.rect.bottomLeft());
                    if (mflags & (State_Sunken)) {
                        QColor shade(0, 0, 0, 50);
                        painter->fillRect(tool.rect.adjusted(0, -1, 1, 1), shade);
892
                    } else if (!Utils::HostOsInfo::isMacHost() && (mflags & State_MouseOver)) {
con's avatar
con committed
893
894
895
896
897
898
                        QColor shade(255, 255, 255, 50);
                        painter->fillRect(tool.rect.adjusted(0, -1, 1, 1), shade);
                    }
                }
                tool.rect = tool.rect.adjusted(2, 2, -2, -2);
                drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
899
900
            } else if (toolbutton->features & QStyleOptionToolButton::HasMenu
                       && !widget->property("noArrow").toBool()) {
901
                int arrowSize = 6;
con's avatar
con committed
902
903
904
                QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1);
                QStyleOptionToolButton newBtn = *toolbutton;
                newBtn.palette = panelPalette(option->palette);
905
906
                newBtn.rect = QRect(ir.right() - arrowSize - 1,
                                    ir.height() - arrowSize - 2, arrowSize, arrowSize);
907
                drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
con's avatar
con committed
908
909
910
911
912
            }
        }
        break;

    case CC_ComboBox:
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
913
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
con's avatar
con committed
914
            painter->save();
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
915
916
            bool isEmpty = cb->currentText.isEmpty() && cb->currentIcon.isNull();
            bool reverse = option->direction == Qt::RightToLeft;
917
918
            bool drawborder = !(widget && widget->property("hideborder").toBool());
            bool alignarrow = !(widget && widget->property("alignarrow").toBool());
con's avatar
con committed
919

920
921
922
            if (drawborder)
                drawButtonSeparator(painter, rect, reverse);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
923
            QStyleOption toolbutton = *option;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
924
925
            if (isEmpty)
                toolbutton.state &= ~(State_Enabled | State_Sunken);
926
            painter->save();
927
928
            if (drawborder)
                painter->setClipRect(toolbutton.rect.adjusted(0, 0, -2, 0));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
929
            drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget);
930
            painter->restore();
con's avatar
con committed
931
            // Draw arrow
932
            int menuButtonWidth = 12;
con's avatar
con committed
933
934
            int left = !reverse ? rect.right() - menuButtonWidth : rect.left();
            int right = !reverse ? rect.right() : rect.left() + menuButtonWidth;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
935
            QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9);
936
937

            if (!alignarrow) {
938
939
940
941
942
                int labelwidth = option->fontMetrics.width(cb->currentText);
                if (reverse)
                    arrowRect.moveLeft(qMax(rect.width() - labelwidth - menuButtonWidth - 2, 4));
                else
                    arrowRect.moveLeft(qMin(labelwidth + menuButtonWidth - 2, rect.width() - menuButtonWidth - 4));
943
            }
con's avatar
con committed
944
            if (option->state & State_On)
945
946
                arrowRect.translate(QProxyStyle::pixelMetric(PM_ButtonShiftHorizontal, option, widget),
                                    QProxyStyle::pixelMetric(PM_ButtonShiftVertical, option, widget));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
947

con's avatar
con committed
948
949
            QStyleOption arrowOpt = *option;
            arrowOpt.rect = arrowRect;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
950
951
952
            if (isEmpty)
                arrowOpt.state &= ~(State_Enabled | State_Sunken);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
953
954
955
956
957
958
959
960
            if (styleHint(SH_ComboBox_Popup, option, widget)) {
                arrowOpt.rect.translate(0, -3);
                drawPrimitive(PE_IndicatorArrowUp, &arrowOpt, painter, widget);
                arrowOpt.rect.translate(0, 6);
                drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
            } else {
                drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
            }
961

con's avatar
con committed
962
963
964
            painter->restore();
        }
        break;
965

con's avatar
con committed
966
    default:
967
        QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
968
969
970
        break;
    }
}
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990

void ManhattanStyle::drawButtonSeparator(QPainter *painter, const QRect &rect, bool reverse) const
{
    QLinearGradient grad(rect.topRight(), rect.bottomRight());
    grad.setColorAt(0, QColor(255, 255, 255, 20));
    grad.setColorAt(0.4, QColor(255, 255, 255, 60));
    grad.setColorAt(0.7, QColor(255, 255, 255, 50));
    grad.setColorAt(1, QColor(255, 255, 255, 40));
    painter->setPen(QPen(grad, 0));
    painter->drawLine(rect.topRight(), rect.bottomRight());
    grad.setColorAt(0, QColor(0, 0, 0, 30));
    grad.setColorAt(0.4, QColor(0, 0, 0, 70));
    grad.setColorAt(0.7, QColor(0, 0, 0, 70));
    grad.setColorAt(1, QColor(0, 0, 0, 40));
    painter->setPen(QPen(grad, 0));
    if (!reverse)
       painter->drawLine(rect.topRight() - QPoint(1,0), rect.bottomRight() - QPoint(1,0));
    else
       painter->drawLine(rect.topLeft(), rect.bottomLeft());
 }