manhattanstyle.cpp 38.1 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
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
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
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
con's avatar
con committed
30
**
31
**************************************************************************/
con's avatar
con committed
32 33

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

con's avatar
con committed
35
#include "styleanimator.h"
hjk's avatar
hjk committed
36 37 38

#include <QtCore/QLibrary>

39 40
#include <coreplugin/coreconstants.h>

41 42 43
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>

44 45
#include <utils/fancymainwindow.h>

hjk's avatar
hjk committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#include <QtGui/QApplication>
#include <QtGui/QComboBox>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QDockWidget>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QMainWindow>
#include <QtGui/QMenuBar>
#include <QtGui/QPainter>
#include <QtGui/QPixmap>
#include <QtGui/QPixmapCache>
#include <QtGui/QPushButton>
#include <QtGui/QScrollArea>
#include <QtGui/QSplitter>
#include <QtGui/QStatusBar>
#include <QtGui/QStyleFactory>
#include <QtGui/QStyleOption>
#include <QtGui/QToolBar>
64
#include <QtGui/QTreeView>
hjk's avatar
hjk committed
65
#include <QtGui/QToolButton>
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
66
#include <QtGui/QAbstractItemView>
hjk's avatar
hjk committed
67

con's avatar
con committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
// We define a currently unused state for indicating animations
#define State_Animating 0x00000040

// 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)
{
87 88 89
    if (!widget)
        return false;

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

94 95 96
    if (qobject_cast<const Utils::FancyMainWindow *>(widget))
        return true;

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
97 98 99
    if (qobject_cast<const QTabBar *>(widget))
        return styleEnabled(widget);

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

112 113 114 115 116 117 118
// Consider making this a QStyle state
bool lightColored(const QWidget *widget)
{
    if (!widget)
        return false;

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

public:
138 139 140 141
    const QImage lineeditImage;
    const QImage lineeditImage_disabled;
    const QPixmap extButtonPixmap;
    const QPixmap closeButtonPixmap;
con's avatar
con committed
142 143 144
    StyleAnimator animator;
};

145
ManhattanStylePrivate::ManhattanStylePrivate() :
146 147 148
    lineeditImage(QLatin1String(":/core/images/inputfield.png")),
    lineeditImage_disabled(QLatin1String(":/core/images/inputfield_disabled.png")),
    extButtonPixmap(QLatin1String(":/core/images/extension.png")),
149
    closeButtonPixmap(QLatin1String(Core::Constants::ICON_CLOSE))
150 151 152
{
}

con's avatar
con committed
153
ManhattanStyle::ManhattanStyle(const QString &baseStyleName)
154 155
    : QProxyStyle(QStyleFactory::create(baseStyleName)),
    d(new ManhattanStylePrivate())
con's avatar
con committed
156 157 158 159 160 161 162 163 164 165 166
{
}

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

QPixmap ManhattanStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
{
167
    return QProxyStyle::generatedIconPixmap(iconMode, pixmap, opt);
con's avatar
con committed
168 169 170 171 172
}

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

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

QRect ManhattanStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
184
    return QProxyStyle::subElementRect(element, option, widget);
con's avatar
con committed
185 186 187 188 189
}

QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
                                     SubControl subControl, const QWidget *widget) const
{
190
    return QProxyStyle::subControlRect(control, option, subControl, widget);
con's avatar
con committed
191 192 193 194 195
}

QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                                         const QPoint &pos, const QWidget *widget) const
{
196
    return QProxyStyle::hitTestComplexControl(control, option, pos, widget);
con's avatar
con committed
197 198 199 200 201
}

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

void ManhattanStyle::polish(QApplication *app)
{
247
    return QProxyStyle::polish(app);
con's avatar
con committed
248 249 250 251
}

void ManhattanStyle::unpolish(QApplication *app)
{
252
    return QProxyStyle::unpolish(app);
con's avatar
con committed
253 254
}

255
QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false)
con's avatar
con committed
256
{
257
    QColor color = Utils::StyleHelper::panelTextColor(lightColored);
con's avatar
con committed
258 259 260 261 262 263 264 265 266 267 268 269 270
    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)
{
271
    QProxyStyle::polish(widget);
con's avatar
con committed
272

273
    // OxygenStyle forces a rounded widget mask on toolbars and dock widgets
Daniel Teske's avatar
Daniel Teske committed
274
    if (baseStyle()->inherits("OxygenStyle") || baseStyle()->inherits("Oxygen::Style")) {
275
        if (qobject_cast<QToolBar*>(widget) || qobject_cast<QDockWidget*>(widget)) {
276
            widget->removeEventFilter(baseStyle());
277 278
            widget->setContentsMargins(0, 0, 0, 0);
        }
con's avatar
con committed
279 280
    }
    if (panelWidget(widget)) {
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
281 282 283 284 285

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

con's avatar
con committed
286
        widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
con's avatar
con committed
287 288
        if (qobject_cast<QToolButton*>(widget)) {
            widget->setAttribute(Qt::WA_Hover);
289
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
con's avatar
con committed
290 291 292
        }
        else if (qobject_cast<QLineEdit*>(widget)) {
            widget->setAttribute(Qt::WA_Hover);
293
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
con's avatar
con committed
294 295 296
        }
        else if (qobject_cast<QLabel*>(widget))
            widget->setPalette(panelPalette(widget->palette()));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
297
        else if (widget->property("panelwidget_singlerow").toBool())
298
            widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight());
con's avatar
con committed
299
        else if (qobject_cast<QStatusBar*>(widget))
300
            widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight() + 2);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
301
        else if (qobject_cast<QComboBox*>(widget)) {
302
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
303 304
            widget->setAttribute(Qt::WA_Hover);
        }
con's avatar
con committed
305 306 307 308 309
    }
}

void ManhattanStyle::unpolish(QWidget *widget)
{
310
    QProxyStyle::unpolish(widget);
con's avatar
con committed
311
    if (panelWidget(widget)) {
con's avatar
con committed
312
        widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
con's avatar
con committed
313 314 315 316
        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
317 318
        else if (qobject_cast<QComboBox*>(widget))
            widget->setAttribute(Qt::WA_Hover, false);
con's avatar
con committed
319 320 321 322 323
    }
}

void ManhattanStyle::polish(QPalette &pal)
{
324
    QProxyStyle::polish(pal);
con's avatar
con committed
325 326
}

327
QIcon ManhattanStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
con's avatar
con committed
328 329 330 331
{
    QIcon icon;
    switch (standardIcon) {
    case QStyle::SP_TitleBarCloseButton:
332 333
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        return QIcon(standardPixmap(standardIcon, option, widget));
con's avatar
con committed
334
    default:
335
        icon = baseStyle()->standardIcon(standardIcon, option, widget);
con's avatar
con committed
336 337 338 339 340 341 342
    }
    return icon;
}

QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
                                       const QWidget *widget) const
{
343
    if (widget && !panelWidget(widget))
344
        return QProxyStyle::standardPixmap(standardPixmap, opt, widget);
345

con's avatar
con committed
346 347
    QPixmap pixmap;
    switch (standardPixmap) {
348 349
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        pixmap = d->extButtonPixmap;
350
        break;
351 352
    case QStyle::SP_TitleBarCloseButton:
        pixmap = d->closeButtonPixmap;
con's avatar
con committed
353 354
        break;
    default:
355
        pixmap = QProxyStyle::standardPixmap(standardPixmap, opt, widget);
356
        break;
con's avatar
con committed
357 358 359 360 361 362 363
    }
    return pixmap;
}

int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
                              QStyleHintReturn *returnData) const
{
364
    int ret = QProxyStyle::styleHint(hint, option, widget, returnData);
con's avatar
con committed
365
    switch (hint) {
366 367 368 369 370
    // 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
371
    case QStyle::SH_EtchDisabledText:
372 373
        if (panelWidget(widget))
            ret = false;
con's avatar
con committed
374
        break;
375 376 377
    case QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren:
        ret = true;
        break;
con's avatar
con committed
378
    default:
379
        break;
con's avatar
con committed
380 381 382 383 384 385 386 387
    }
    return ret;
}

void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                                   QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
388
        return QProxyStyle::drawPrimitive(element, option, painter, widget);
con's avatar
con committed
389 390 391 392 393 394 395 396 397 398 399 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 431 432 433 434 435 436

    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;
            opt.state |= (State)State_Animating;
            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;
            endOpt.state |= (State)State_Animating;
            t->setStartImage(startImage);
            d->animator.startAnimation(t);
            endImage.fill(0);
            QPainter endPainter(&endImage);
            drawPrimitive(element, &endOpt, &endPainter, widget);
            t->setEndImage(endImage);
437 438 439 440
            if (oldState & State_MouseOver)
                t->setDuration(150);
            else
                t->setDuration(75);
con's avatar
con committed
441 442 443 444 445
            t->setStartTime(QTime::currentTime());
        }
    }

    switch (element) {
446 447 448 449 450 451
    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
452 453 454
    case PE_PanelLineEdit:
        {
            painter->save();
455 456 457 458 459 460

            // 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
461
            if (option->state & State_Enabled)
462
                Utils::StyleHelper::drawCornerImage(d->lineeditImage, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
463
            else
464
                Utils::StyleHelper::drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
465 466

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

    case PE_PanelStatusBar:
        {
            painter->save();
            QLinearGradient grad(option->rect.topLeft(), QPoint(rect.center().x(), rect.bottom()));
525 526
            QColor startColor = Utils::StyleHelper::shadowColor().darker(164);
            QColor endColor = Utils::StyleHelper::baseColor().darker(130);
con's avatar
con committed
527 528 529 530 531 532
            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));
533
            painter->setPen(Utils::StyleHelper::borderColor().darker(110));
con's avatar
con committed
534 535 536 537 538 539 540
            painter->drawLine(rect.topLeft(), rect.topRight());
            painter->restore();
        }
        break;

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

588
            QColor light = Utils::StyleHelper::baseColor();
con's avatar
con committed
589 590 591 592 593 594 595 596 597 598 599 600 601 602
            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;
603 604 605 606 607
    case PE_IndicatorArrowUp:
    case PE_IndicatorArrowDown:
    case PE_IndicatorArrowRight:
    case PE_IndicatorArrowLeft:
        {
608
            Utils::StyleHelper::drawArrow(element, painter, option);
609 610
        }
        break;
con's avatar
con committed
611 612

    default:
613
        QProxyStyle::drawPrimitive(element, option, painter, widget);
con's avatar
con committed
614 615 616 617 618 619 620 621
        break;
    }
}

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

    switch (element) {
625 626 627 628 629 630 631 632 633 634
    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;
635 636 637 638
            if (tab->cornerWidgets == QStyleOptionTab::NoCornerWidgets && (
                    tab->position == QStyleOptionTab::Beginning ||
                    tab->position == QStyleOptionTab::OnlyOneTab))
            {
639 640 641 642 643 644 645 646 647 648
                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
649 650 651
    case CE_MenuBarItem:
        painter->save();
        if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
652
            QColor highlightOutline = Utils::StyleHelper::borderColor().lighter(120);
con's avatar
con committed
653 654
            bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
            bool dis = !(mbi->state & State_Enabled);
655
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
con's avatar
con committed
656 657 658 659 660 661 662 663 664 665
            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|
666
                QColor baseColor = Utils::StyleHelper::baseColor();
con's avatar
con committed
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
                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;

    case CE_ComboBoxLabel:
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
            if (panelWidget(widget)) {
698
                painter->save();
con's avatar
con committed
699 700
                QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
                QPalette customPal = cb->palette;
701
                bool drawIcon = !(widget && widget->property("hideicon").toBool());
con's avatar
con committed
702

703
                if (!cb->currentIcon.isNull() && drawIcon) {
con's avatar
con committed
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
                    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
720 721 722

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

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
725
                QString text = option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, editRect.width());
726 727
                if ((option->state & State_Enabled)) {
                    painter->setPen(QColor(0, 0, 0, 70));
728
                    painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
729
                } else {
730
                    painter->setOpacity(0.8);
731 732
                }
                painter->setPen(Utils::StyleHelper::panelTextColor());
733
                painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
734 735

                painter->restore();
con's avatar
con committed
736
            } else {
737
                QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
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 770 771 772 773 774 775
            }
        }
        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_MenuBarEmptyArea: {
776
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
con's avatar
con committed
777
            painter->save();
778
            painter->setPen(Utils::StyleHelper::borderColor());
con's avatar
con committed
779 780 781 782 783 784 785 786
            painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
            painter->restore();
        }
        break;

    case CE_ToolBar:
        {
            QRect rect = option->rect;
787
            bool horizontal = option->state & State_Horizontal;
788 789 790 791 792 793 794 795 796 797 798 799 800 801
            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
802

803 804 805 806
            if (!drawLightColored)
                painter->setPen(Utils::StyleHelper::borderColor());
            else
                painter->setPen(QColor(0x888888));
con's avatar
con committed
807 808

            if (horizontal) {
809 810 811
                // 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
812
                QColor lighter(Utils::StyleHelper::sidebarHighlight());
813 814
                if (drawLightColored)
                    lighter = QColor(255, 255, 255, 180);
815
                if (widget && widget->property("topBorder").toBool()) {
816 817 818
                    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
819
                } else {
820 821 822
                    painter->drawLine(rect.bottomLeft(), rect.bottomRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft(), rect.topRight());
con's avatar
con committed
823 824
                }
            } else {
825 826
                painter->drawLine(rect.topLeft(), rect.bottomLeft());
                painter->drawLine(rect.topRight(), rect.bottomRight());
con's avatar
con committed
827 828 829
            }
        }
        break;
830

con's avatar
con committed
831
    default:
832
        QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
833 834 835 836 837 838 839 840
        break;
    }
}

void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                        QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
841
         return     QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
842 843 844 845 846

    QRect rect = option->rect;
    switch (control) {
    case CC_ToolButton:
        if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
847 848 849 850 851 852
            bool reverse = option->direction == Qt::RightToLeft;
            bool drawborder = (widget && widget->property("showborder").toBool());

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

con's avatar
con committed
853 854 855 856 857 858 859 860 861 862 863 864
            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;
865 866 867 868 869 870
            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
871 872 873 874

            QStyleOption tool(0);
            tool.palette = toolbutton->palette;
            if (toolbutton->subControls & SC_ToolButton) {
875 876 877
                tool.rect = button;
                tool.state = bflags;
                drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
con's avatar
con committed
878 879 880
            }

            QStyleOptionToolButton label = *toolbutton;
881 882

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

con's avatar
con committed
886 887 888 889 890 891 892 893 894 895 896 897
            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);
                    }
898
#ifndef Q_OS_MAC
con's avatar
con committed
899 900 901 902 903 904 905 906
                    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);
907 908
            } else if (toolbutton->features & QStyleOptionToolButton::HasMenu
                       && !widget->property("noArrow").toBool()) {
909
                int arrowSize = 6;
con's avatar
con committed
910 911 912
                QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1);
                QStyleOptionToolButton newBtn = *toolbutton;
                newBtn.palette = panelPalette(option->palette);
913 914
                newBtn.rect = QRect(ir.right() - arrowSize - 1,
                                    ir.height() - arrowSize - 2, arrowSize, arrowSize);
915
                drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
con's avatar
con committed
916 917 918 919 920
            }
        }
        break;

    case CC_ComboBox:
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
921
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
con's avatar
con committed
922
            painter->save();
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
923 924
            bool isEmpty = cb->currentText.isEmpty() && cb->currentIcon.isNull();
            bool reverse = option->direction == Qt::RightToLeft;
925 926
            bool drawborder = !(widget && widget->property("hideborder").toBool());
            bool alignarrow = !(widget && widget->property("alignarrow").toBool());
con's avatar
con committed
927

928 929 930
            if (drawborder)
                drawButtonSeparator(painter, rect, reverse);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
931
            QStyleOption toolbutton = *option;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
932 933
            if (isEmpty)
                toolbutton.state &= ~(State_Enabled | State_Sunken);
934
            painter->save();
935 936
            if (drawborder)
                painter->setClipRect(toolbutton.rect.adjusted(0, 0, -2, 0));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
937
            drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget);
938
            painter->restore();
con's avatar
con committed
939
            // Draw arrow
940
            int menuButtonWidth = 12;
con's avatar
con committed
941 942
            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
943
            QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9);
944 945

            if (!alignarrow) {
946 947 948 949 950
                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));
951
            }
con's avatar
con committed
952
            if (option->state & State_On)
953 954
                arrowRect.translate(QProxyStyle::pixelMetric(PM_ButtonShiftHorizontal, option, widget),
                                    QProxyStyle::pixelMetric(PM_ButtonShiftVertical, option, widget));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
955

con's avatar
con committed
956 957
            QStyleOption arrowOpt = *option;
            arrowOpt.rect = arrowRect;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
958 959 960
            if (isEmpty)
                arrowOpt.state &= ~(State_Enabled | State_Sunken);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
961 962 963 964 965 966 967 968
            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);
            }
969

con's avatar
con committed
970 971 972
            painter->restore();
        }
        break;
973

con's avatar
con committed
974
    default:
975
        QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
976 977 978
        break;
    }
}
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998

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