manhattanstyle.cpp 34.9 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
Eike Ziller's avatar
Eike Ziller committed
7
** Contact: http://www.qt-project.org/
con's avatar
con committed
8
**
9
**
10
** GNU Lesser General Public License Usage
11
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
**
29
**************************************************************************/
con's avatar
con committed
30 31

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

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

35
#include <QLibrary>
hjk's avatar
hjk committed
36

37 38
#include <coreplugin/coreconstants.h>

39 40 41
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>

42 43
#include <utils/fancymainwindow.h>

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#include <QApplication>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QDockWidget>
#include <QLabel>
#include <QLineEdit>
#include <QPainter>
#include <QPixmap>
#include <QPixmapCache>
#include <QPushButton>
#include <QScrollArea>
#include <QSplitter>
#include <QStatusBar>
#include <QStyleFactory>
#include <QStyleOption>
#include <QToolBar>
#include <QTreeView>
#include <QToolButton>
#include <QAbstractItemView>
hjk's avatar
hjk committed
63

con's avatar
con committed
64
// We define a currently unused state for indicating animations
65
const QStyle::State State_Animating = QStyle::State(0x00000040);
con's avatar
con committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

// 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)
{
83 84 85
    if (!widget)
        return false;

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

90 91 92
    if (qobject_cast<const Utils::FancyMainWindow *>(widget))
        return true;

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
93 94 95
    if (qobject_cast<const QTabBar *>(widget))
        return styleEnabled(widget);

96
    const QWidget *p = widget;
con's avatar
con committed
97
    while (p) {
98 99
        if (qobject_cast<const QToolBar *>(p) ||
            qobject_cast<const QStatusBar *>(p) ||
100
            p->property("panelwidget").toBool())
101
            return styleEnabled(widget);
con's avatar
con committed
102 103 104 105 106
        p = p->parentWidget();
    }
    return false;
}

107 108 109 110 111 112 113
// Consider making this a QStyle state
bool lightColored(const QWidget *widget)
{
    if (!widget)
        return false;

    // Don't style dialogs or explicitly ignored widgets
114
    if ((widget->window()->windowFlags() & Qt::WindowType_Mask) == Qt::Dialog)
115 116 117 118 119 120 121 122 123 124 125
        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
126 127 128
class ManhattanStylePrivate
{
public:
129
    explicit ManhattanStylePrivate();
con's avatar
con committed
130
    void init();
hjk's avatar
hjk committed
131 132

public:
133 134 135 136
    const QImage lineeditImage;
    const QImage lineeditImage_disabled;
    const QPixmap extButtonPixmap;
    const QPixmap closeButtonPixmap;
con's avatar
con committed
137 138 139
    StyleAnimator animator;
};

140
ManhattanStylePrivate::ManhattanStylePrivate() :
141 142 143
    lineeditImage(QLatin1String(":/core/images/inputfield.png")),
    lineeditImage_disabled(QLatin1String(":/core/images/inputfield_disabled.png")),
    extButtonPixmap(QLatin1String(":/core/images/extension.png")),
144
    closeButtonPixmap(QLatin1String(Core::Constants::ICON_CLOSE))
145 146 147
{
}

con's avatar
con committed
148
ManhattanStyle::ManhattanStyle(const QString &baseStyleName)
149 150
    : QProxyStyle(QStyleFactory::create(baseStyleName)),
    d(new ManhattanStylePrivate())
con's avatar
con committed
151 152 153 154 155 156 157 158 159 160 161
{
}

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

QPixmap ManhattanStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
{
162
    return QProxyStyle::generatedIconPixmap(iconMode, pixmap, opt);
con's avatar
con committed
163 164 165 166 167
}

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

con's avatar
con committed
170 171
    if (type == CT_Splitter && widget && widget->property("minisplitter").toBool())
        return QSize(1, 1);
172
    else if (type == CT_ComboBox && panelWidget(widget))
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
173
        newSize += QSize(14, 0);
174
    return newSize;
con's avatar
con committed
175 176 177 178
}

QRect ManhattanStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
179
    return QProxyStyle::subElementRect(element, option, widget);
con's avatar
con committed
180 181 182 183 184
}

QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
                                     SubControl subControl, const QWidget *widget) const
{
185
    return QProxyStyle::subControlRect(control, option, subControl, widget);
con's avatar
con committed
186 187 188 189 190
}

QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                                         const QPoint &pos, const QWidget *widget) const
{
191
    return QProxyStyle::hitTestComplexControl(control, option, pos, widget);
con's avatar
con committed
192 193 194 195 196
}

int ManhattanStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
    int retval = 0;
197
    retval = QProxyStyle::pixelMetric(metric, option, widget);
con's avatar
con committed
198 199 200 201 202 203 204 205 206
    switch (metric) {
    case PM_SplitterWidth:
        if (widget && widget->property("minisplitter").toBool())
            retval = 1;
        break;
    case PM_ToolBarIconSize:
        if (panelWidget(widget))
            retval = 16;
        break;
207
    case PM_DockWidgetHandleExtent:
208 209
    case PM_DockWidgetSeparatorExtent:
        return 1;
con's avatar
con committed
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
    case PM_ToolBarFrameWidth:
        if (panelWidget(widget))
            retval = 1;
        break;
    case PM_ButtonShiftVertical:
    case PM_ButtonShiftHorizontal:
    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
{
233
    return QProxyStyle::standardPalette();
con's avatar
con committed
234 235 236 237
}

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

void ManhattanStyle::unpolish(QApplication *app)
{
243
    return QProxyStyle::unpolish(app);
con's avatar
con committed
244 245
}

246
QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false)
con's avatar
con committed
247
{
248
    QColor color = Utils::StyleHelper::panelTextColor(lightColored);
con's avatar
con committed
249 250 251 252 253 254 255 256 257 258 259 260 261
    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)
{
262
    QProxyStyle::polish(widget);
con's avatar
con committed
263

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

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

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

void ManhattanStyle::unpolish(QWidget *widget)
{
301
    QProxyStyle::unpolish(widget);
con's avatar
con committed
302
    if (panelWidget(widget)) {
con's avatar
con committed
303
        widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
con's avatar
con committed
304 305 306 307
        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
308 309
        else if (qobject_cast<QComboBox*>(widget))
            widget->setAttribute(Qt::WA_Hover, false);
con's avatar
con committed
310 311 312 313 314
    }
}

void ManhattanStyle::polish(QPalette &pal)
{
315
    QProxyStyle::polish(pal);
con's avatar
con committed
316 317
}

318
QIcon ManhattanStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
con's avatar
con committed
319 320 321 322
{
    QIcon icon;
    switch (standardIcon) {
    case QStyle::SP_TitleBarCloseButton:
323 324
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        return QIcon(standardPixmap(standardIcon, option, widget));
con's avatar
con committed
325
    default:
326
        icon = baseStyle()->standardIcon(standardIcon, option, widget);
con's avatar
con committed
327 328 329 330 331 332 333
    }
    return icon;
}

QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
                                       const QWidget *widget) const
{
334
    if (widget && !panelWidget(widget))
335
        return QProxyStyle::standardPixmap(standardPixmap, opt, widget);
336

con's avatar
con committed
337 338
    QPixmap pixmap;
    switch (standardPixmap) {
339 340
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        pixmap = d->extButtonPixmap;
341
        break;
342 343
    case QStyle::SP_TitleBarCloseButton:
        pixmap = d->closeButtonPixmap;
con's avatar
con committed
344 345
        break;
    default:
346
        pixmap = QProxyStyle::standardPixmap(standardPixmap, opt, widget);
347
        break;
con's avatar
con committed
348 349 350 351 352 353 354
    }
    return pixmap;
}

int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
                              QStyleHintReturn *returnData) const
{
355
    int ret = QProxyStyle::styleHint(hint, option, widget, returnData);
con's avatar
con committed
356
    switch (hint) {
357 358 359 360 361
    // 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
362
    case QStyle::SH_EtchDisabledText:
363 364
        if (panelWidget(widget))
            ret = false;
con's avatar
con committed
365
        break;
366 367 368
    case QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren:
        ret = true;
        break;
con's avatar
con committed
369
    default:
370
        break;
con's avatar
con committed
371 372 373 374 375 376 377 378
    }
    return ret;
}

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

    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;
409
            opt.state |= State_Animating;
con's avatar
con committed
410 411 412 413 414 415 416 417 418 419 420
            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;
421
            endOpt.state |= State_Animating;
con's avatar
con committed
422 423 424 425 426 427
            t->setStartImage(startImage);
            d->animator.startAnimation(t);
            endImage.fill(0);
            QPainter endPainter(&endImage);
            drawPrimitive(element, &endOpt, &endPainter, widget);
            t->setEndImage(endImage);
428 429 430 431
            if (oldState & State_MouseOver)
                t->setDuration(150);
            else
                t->setDuration(75);
con's avatar
con committed
432 433 434 435 436
            t->setStartTime(QTime::currentTime());
        }
    }

    switch (element) {
437 438 439 440 441 442
    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
443 444 445
    case PE_PanelLineEdit:
        {
            painter->save();
446 447 448 449 450 451

            // 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
452
            if (option->state & State_Enabled)
453
                Utils::StyleHelper::drawCornerImage(d->lineeditImage, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
454
            else
455
                Utils::StyleHelper::drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
456 457

            if (option->state & State_HasFocus || option->state & State_MouseOver) {
458
                QColor hover = Utils::StyleHelper::baseColor();
con's avatar
con committed
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
                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) {
483 484 485
                    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
486
                    painter->drawLine(rect.topLeft(), rect.bottomLeft());
487 488
                    painter->drawLine(rect.topRight(), rect.bottomRight());
                   // painter->drawLine(rect.bottomLeft()  + QPoint(1, 0), rect.bottomRight()  - QPoint(1, 0));
con's avatar
con committed
489 490 491
                    QColor highlight(255, 255, 255, 30);
                    painter->setPen(highlight);
                }
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
492 493
                else if (option->state & State_Enabled &&
                         option->state & State_MouseOver) {
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
494
                    QColor lighter(255, 255, 255, 37);
con's avatar
con committed
495 496
                    painter->fillRect(rect, lighter);
                }
497 498 499 500 501 502 503 504 505 506 507
                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
508 509 510 511 512 513 514 515
           }
        }
        break;

    case PE_PanelStatusBar:
        {
            painter->save();
            QLinearGradient grad(option->rect.topLeft(), QPoint(rect.center().x(), rect.bottom()));
516 517
            QColor startColor = Utils::StyleHelper::shadowColor().darker(164);
            QColor endColor = Utils::StyleHelper::baseColor().darker(130);
con's avatar
con committed
518 519 520 521 522 523
            grad.setColorAt(0, startColor);
            grad.setColorAt(1, endColor);
            painter->fillRect(option->rect, grad);
            painter->setPen(QColor(255, 255, 255, 60));
            painter->drawLine(rect.topLeft() + QPoint(0,1),
                              rect.topRight()+ QPoint(0,1));
524
            painter->setPen(Utils::StyleHelper::borderColor().darker(110));
con's avatar
con committed
525 526 527 528 529 530 531
            painter->drawLine(rect.topLeft(), rect.topRight());
            painter->restore();
        }
        break;

    case PE_IndicatorToolBarSeparator:
        {
532
            QColor separatorColor = Utils::StyleHelper::borderColor();
con's avatar
con committed
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
            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;
558 559
            int x = option->rect.x() + (horizontal ? 2 : 6);
            int y = option->rect.y() + (horizontal ? 6 : 2);
con's avatar
con committed
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
            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);
576
            QColor dark = Utils::StyleHelper::borderColor();
con's avatar
con committed
577 578
            dark.setAlphaF(0.4);

579
            QColor light = Utils::StyleHelper::baseColor();
con's avatar
con committed
580 581 582 583 584 585 586 587 588 589 590 591 592 593
            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;
594 595 596 597 598
    case PE_IndicatorArrowUp:
    case PE_IndicatorArrowDown:
    case PE_IndicatorArrowRight:
    case PE_IndicatorArrowLeft:
        {
599
            Utils::StyleHelper::drawArrow(element, painter, option);
600 601
        }
        break;
con's avatar
con committed
602 603

    default:
604
        QProxyStyle::drawPrimitive(element, option, painter, widget);
con's avatar
con committed
605 606 607 608 609 610 611 612
        break;
    }
}

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

    switch (element) {
616 617 618 619 620 621 622 623 624 625
    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;
626 627 628 629
            if (tab->cornerWidgets == QStyleOptionTab::NoCornerWidgets && (
                    tab->position == QStyleOptionTab::Beginning ||
                    tab->position == QStyleOptionTab::OnlyOneTab))
            {
630 631 632 633 634 635 636 637 638 639
                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;

con's avatar
con committed
640 641 642
    case CE_ComboBoxLabel:
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
            if (panelWidget(widget)) {
643
                painter->save();
con's avatar
con committed
644 645
                QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
                QPalette customPal = cb->palette;
646
                bool drawIcon = !(widget && widget->property("hideicon").toBool());
con's avatar
con committed
647

648
                if (!cb->currentIcon.isNull() && drawIcon) {
con's avatar
con committed
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
                    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
665 666 667

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

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
670
                QString text = option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, editRect.width());
671 672
                if ((option->state & State_Enabled)) {
                    painter->setPen(QColor(0, 0, 0, 70));
673
                    painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
674
                } else {
675
                    painter->setOpacity(0.8);
676 677
                }
                painter->setPen(Utils::StyleHelper::panelTextColor());
678
                painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
679 680

                painter->restore();
con's avatar
con committed
681
            } else {
682
                QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
            }
        }
        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;

    case CE_ToolBar:
        {
            QRect rect = option->rect;
723
            bool horizontal = option->state & State_Horizontal;
724 725 726 727 728 729 730 731 732 733 734 735 736 737
            rect = option->rect;

            // 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
738

739 740 741 742
            if (!drawLightColored)
                painter->setPen(Utils::StyleHelper::borderColor());
            else
                painter->setPen(QColor(0x888888));
con's avatar
con committed
743 744

            if (horizontal) {
745 746 747
                // 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
748
                QColor lighter(Utils::StyleHelper::sidebarHighlight());
749 750
                if (drawLightColored)
                    lighter = QColor(255, 255, 255, 180);
751
                if (widget && widget->property("topBorder").toBool()) {
752 753 754
                    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
755
                } else {
756 757 758
                    painter->drawLine(rect.bottomLeft(), rect.bottomRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft(), rect.topRight());
con's avatar
con committed
759 760
                }
            } else {
761 762
                painter->drawLine(rect.topLeft(), rect.bottomLeft());
                painter->drawLine(rect.topRight(), rect.bottomRight());
con's avatar
con committed
763 764 765
            }
        }
        break;
766

con's avatar
con committed
767
    default:
768
        QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
769 770 771 772 773 774 775 776
        break;
    }
}

void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                        QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
777
         return     QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
778 779 780 781 782

    QRect rect = option->rect;
    switch (control) {
    case CC_ToolButton:
        if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
783 784 785 786 787 788
            bool reverse = option->direction == Qt::RightToLeft;
            bool drawborder = (widget && widget->property("showborder").toBool());

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

con's avatar
con committed
789 790 791 792 793 794 795 796 797 798 799 800
            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) {
                if (!(bflags & State_MouseOver)) {
                    bflags &= ~State_Raised;
                }
            }

            State mflags = bflags;
801 802 803 804 805 806
            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
807 808 809 810

            QStyleOption tool(0);
            tool.palette = toolbutton->palette;
            if (toolbutton->subControls & SC_ToolButton) {
811 812 813
                tool.rect = button;
                tool.state = bflags;
                drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
con's avatar
con committed
814 815 816
            }

            QStyleOptionToolButton label = *toolbutton;
817 818

            label.palette = panelPalette(option->palette, lightColored(widget));
con's avatar
con committed
819 820
            int fw = pixelMetric(PM_DefaultFrameWidth, option, widget);
            label.rect = button.adjusted(fw, fw, -fw, -fw);
821

con's avatar
con committed
822 823 824 825 826 827 828 829 830 831 832 833
            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);
                    }
834
#ifndef Q_OS_MAC
con's avatar
con committed
835 836 837 838 839 840 841 842
                    else if (mflags & (State_MouseOver)) {
                        QColor shade(255, 255, 255, 50);
                        painter->fillRect(tool.rect.adjusted(0, -1, 1, 1), shade);
                    }
#endif
                }
                tool.rect = tool.rect.adjusted(2, 2, -2, -2);
                drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
843 844
            } else if (toolbutton->features & QStyleOptionToolButton::HasMenu
                       && !widget->property("noArrow").toBool()) {
845
                int arrowSize = 6;
con's avatar
con committed
846 847 848
                QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1);
                QStyleOptionToolButton newBtn = *toolbutton;
                newBtn.palette = panelPalette(option->palette);
849 850
                newBtn.rect = QRect(ir.right() - arrowSize - 1,
                                    ir.height() - arrowSize - 2, arrowSize, arrowSize);
851
                drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
con's avatar
con committed
852 853 854 855 856
            }
        }
        break;

    case CC_ComboBox:
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
857
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
con's avatar
con committed
858
            painter->save();
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
859 860
            bool isEmpty = cb->currentText.isEmpty() && cb->currentIcon.isNull();
            bool reverse = option->direction == Qt::RightToLeft;
861 862
            bool drawborder = !(widget && widget->property("hideborder").toBool());
            bool alignarrow = !(widget && widget->property("alignarrow").toBool());
con's avatar
con committed
863

864 865 866
            if (drawborder)
                drawButtonSeparator(painter, rect, reverse);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
867
            QStyleOption toolbutton = *option;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
868 869
            if (isEmpty)
                toolbutton.state &= ~(State_Enabled | State_Sunken);
870
            painter->save();
871 872
            if (drawborder)
                painter->setClipRect(toolbutton.rect.adjusted(0, 0, -2, 0));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
873
            drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget);
874
            painter->restore();
con's avatar
con committed
875
            // Draw arrow
876
            int menuButtonWidth = 12;
con's avatar
con committed
877 878
            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
879
            QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9);
880 881

            if (!alignarrow) {
882 883 884 885 886
                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));
887
            }
con's avatar
con committed
888
            if (option->state & State_On)
889 890
                arrowRect.translate(QProxyStyle::pixelMetric(PM_ButtonShiftHorizontal, option, widget),
                                    QProxyStyle::pixelMetric(PM_ButtonShiftVertical, option, widget));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
891

con's avatar
con committed
892 893
            QStyleOption arrowOpt = *option;
            arrowOpt.rect = arrowRect;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
894 895 896
            if (isEmpty)
                arrowOpt.state &= ~(State_Enabled | State_Sunken);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
897 898 899 900 901 902 903 904
            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);
            }
905

con's avatar
con committed
906 907 908
            painter->restore();
        }
        break;
909

con's avatar
con committed
910
    default:
911
        QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
912 913 914
        break;
    }
}
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934

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());
 }