manhattanstyle.cpp 37.8 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.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
Tobias Hunger's avatar
Tobias Hunger committed
29
** Nokia at info@qt.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
274
    if (baseStyle()->inherits("OxygenStyle")) {
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 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
            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;
            int x = option->rect.x() + horizontal ? 2 : 6;
            int y = option->rect.y() + horizontal ? 6 : 2;
            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 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
                QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
                QPalette customPal = cb->palette;

                if (!cb->currentIcon.isNull()) {
                    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
719 720 721

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

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

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

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

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

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

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

void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                        QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
840
         return     QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857

    QRect rect = option->rect;
    switch (control) {
    case CC_ToolButton:
        if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
            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;
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));
con's avatar
con committed
876 877
            int fw = pixelMetric(PM_DefaultFrameWidth, option, widget);
            label.rect = button.adjusted(fw, fw, -fw, -fw);
878

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

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

            // Draw tool button
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
            if (drawborder) {
                QLinearGradient grad(option->rect.topRight(), option->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());
            }
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
940
            QStyleOption toolbutton = *option;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
941 942
            if (isEmpty)
                toolbutton.state &= ~(State_Enabled | State_Sunken);
943
            painter->save();
944 945
            if (drawborder)
                painter->setClipRect(toolbutton.rect.adjusted(0, 0, -2, 0));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
946
            drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget);
947
            painter->restore();
con's avatar
con committed
948
            // Draw arrow
949
            int menuButtonWidth = 12;
con's avatar
con committed
950 951
            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
952
            QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9);
953 954

            if (!alignarrow) {
955 956 957 958 959
                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));
960
            }
con's avatar
con committed
961
            if (option->state & State_On)
962 963
                arrowRect.translate(QProxyStyle::pixelMetric(PM_ButtonShiftHorizontal, option, widget),
                                    QProxyStyle::pixelMetric(PM_ButtonShiftVertical, option, widget));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
964

con's avatar
con committed
965 966
            QStyleOption arrowOpt = *option;
            arrowOpt.rect = arrowRect;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
967 968 969
            if (isEmpty)
                arrowOpt.state &= ~(State_Enabled | State_Sunken);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
970 971 972 973 974 975 976 977
            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);
            }
978

con's avatar
con committed
979 980 981
            painter->restore();
        }
        break;
982

con's avatar
con committed
983
    default:
984
        QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
985 986 987
        break;
    }
}