manhattanstyle.cpp 39.7 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
5
** Copyright (c) 2009 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
** Commercial Usage
10
**
11 12 13 14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18 19 20 21 22 23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
con's avatar
con committed
29 30

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

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

#include <QtCore/QLibrary>

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

hjk's avatar
hjk committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
#include <QtGui/QApplication>
#include <QtGui/QComboBox>
#include <QtGui/QDialog>
#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>
#include <QtGui/QToolButton>
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
59
#include <QtGui/QAbstractItemView>
hjk's avatar
hjk committed
60

con's avatar
con committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
// 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)
{
80 81 82
    if (!widget)
        return false;

Tobias Hunger's avatar
Tobias Hunger committed
83
    // Do not style dialogs or explicitly ignored widgets
84 85
    if (qobject_cast<const QDialog *>(widget->window()))
        return false;
con's avatar
con committed
86

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

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
// Consider making this a QStyle state
bool lightColored(const QWidget *widget)
{
    if (!widget)
        return false;

    // Don't style dialogs or explicitly ignored widgets
    if (qobject_cast<const QDialog *>(widget->window()))
        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
120 121 122
class ManhattanStylePrivate
{
public:
123
    explicit ManhattanStylePrivate();
con's avatar
con committed
124
    void init();
hjk's avatar
hjk committed
125 126

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

134
ManhattanStylePrivate::ManhattanStylePrivate() :
135 136 137 138 139 140 141
    lineeditImage(QLatin1String(":/core/images/inputfield.png")),
    lineeditImage_disabled(QLatin1String(":/core/images/inputfield_disabled.png")),
    extButtonPixmap(QLatin1String(":/core/images/extension.png")),
    closeButtonPixmap(QLatin1String(":/core/images/closebutton.png"))
{
}

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

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

// Draws a CSS-like border image where the defined borders are not stretched
void drawCornerImage(const QImage &img, QPainter *painter, QRect rect,
                     int left = 0, int top = 0, int right = 0,
                     int bottom = 0)
{
    QSize size = img.size();
    if (top > 0) { //top
        painter->drawImage(QRect(rect.left() + left, rect.top(), rect.width() -right - left, top), img,
                           QRect(left, 0, size.width() -right - left, top));
hjk's avatar
hjk committed
163
        if (left > 0) //top-left
con's avatar
con committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
            painter->drawImage(QRect(rect.left(), rect.top(), left, top), img,
                               QRect(0, 0, left, top));
        if (right > 0) //top-right
            painter->drawImage(QRect(rect.left() + rect.width() - right, rect.top(), right, top), img,
                               QRect(size.width() - right, 0, right, top));
    }
    //left
    if (left > 0)
        painter->drawImage(QRect(rect.left(), rect.top()+top, left, rect.height() - top - bottom), img,
                           QRect(0, top, left, size.height() - bottom - top));
    //center
    painter->drawImage(QRect(rect.left() + left, rect.top()+top, rect.width() -right - left,
                             rect.height() - bottom - top), img,
                       QRect(left, top, size.width() -right -left,
                             size.height() - bottom - top));
    if (right > 0) //right
        painter->drawImage(QRect(rect.left() +rect.width() - right, rect.top()+top, right, rect.height() - top - bottom), img,
                           QRect(size.width() - right, top, right, size.height() - bottom - top));
    if (bottom > 0) { //bottom
        painter->drawImage(QRect(rect.left() +left, rect.top() + rect.height() - bottom,
                                 rect.width() - right - left, bottom), img,
                           QRect(left, size.height() - bottom,
                                 size.width() - right - left, bottom));
    if (left > 0) //bottom-left
        painter->drawImage(QRect(rect.left(), rect.top() + rect.height() - bottom, left, bottom), img,
                           QRect(0, size.height() - bottom, left, bottom));
    if (right > 0) //bottom-right
        painter->drawImage(QRect(rect.left() + rect.width() - right, rect.top() + rect.height() - bottom, right, bottom), img,
                           QRect(size.width() - right, size.height() - bottom, right, bottom));
    }
}

QPixmap ManhattanStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
{
198
    return QProxyStyle::generatedIconPixmap(iconMode, pixmap, opt);
con's avatar
con committed
199 200 201 202 203
}

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

con's avatar
con committed
206 207
    if (type == CT_Splitter && widget && widget->property("minisplitter").toBool())
        return QSize(1, 1);
208
    else if (type == CT_ComboBox && panelWidget(widget))
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
209
        newSize += QSize(14, 0);
210
    return newSize;
con's avatar
con committed
211 212 213 214
}

QRect ManhattanStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
215
    return QProxyStyle::subElementRect(element, option, widget);
con's avatar
con committed
216 217 218 219 220
}

QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
                                     SubControl subControl, const QWidget *widget) const
{
221
    return QProxyStyle::subControlRect(control, option, subControl, widget);
con's avatar
con committed
222 223 224 225 226
}

QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                                         const QPoint &pos, const QWidget *widget) const
{
227
    return QProxyStyle::hitTestComplexControl(control, option, pos, widget);
con's avatar
con committed
228 229 230 231 232
}

int ManhattanStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
    int retval = 0;
233
    retval = QProxyStyle::pixelMetric(metric, option, widget);
con's avatar
con committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
    switch (metric) {
    case PM_SplitterWidth:
        if (widget && widget->property("minisplitter").toBool())
            retval = 1;
        break;
    case PM_ToolBarIconSize:
        if (panelWidget(widget))
            retval = 16;
        break;
    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
{
270
    return QProxyStyle::standardPalette();
con's avatar
con committed
271 272 273 274
}

void ManhattanStyle::polish(QApplication *app)
{
275
    return QProxyStyle::polish(app);
con's avatar
con committed
276 277 278 279
}

void ManhattanStyle::unpolish(QApplication *app)
{
280
    return QProxyStyle::unpolish(app);
con's avatar
con committed
281 282
}

283
QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false)
con's avatar
con committed
284
{
285
    QColor color = Utils::StyleHelper::panelTextColor(lightColored);
con's avatar
con committed
286 287 288 289 290 291 292 293 294 295 296 297 298
    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)
{
299
    QProxyStyle::polish(widget);
con's avatar
con committed
300 301

    // OxygenStyle forces a rounded widget mask on toolbars
302
    if (baseStyle()->inherits("OxygenStyle")) {
con's avatar
con committed
303
        if (qobject_cast<QToolBar*>(widget))
304
            widget->removeEventFilter(baseStyle());
con's avatar
con committed
305 306
    }
    if (panelWidget(widget)) {
con's avatar
con committed
307
        widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
con's avatar
con committed
308 309
        if (qobject_cast<QToolButton*>(widget)) {
            widget->setAttribute(Qt::WA_Hover);
310
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
con's avatar
con committed
311 312 313
        }
        else if (qobject_cast<QLineEdit*>(widget)) {
            widget->setAttribute(Qt::WA_Hover);
314
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
con's avatar
con committed
315 316 317
        }
        else if (qobject_cast<QLabel*>(widget))
            widget->setPalette(panelPalette(widget->palette()));
con's avatar
con committed
318
        else if (qobject_cast<QToolBar*>(widget) || widget->property("panelwidget_singlerow").toBool())
319
            widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight());
con's avatar
con committed
320
        else if (qobject_cast<QStatusBar*>(widget))
321
            widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight() + 2);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
322
        else if (qobject_cast<QComboBox*>(widget)) {
323
            widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
324 325
            widget->setAttribute(Qt::WA_Hover);
        }
con's avatar
con committed
326 327 328 329 330
    }
}

void ManhattanStyle::unpolish(QWidget *widget)
{
331
    QProxyStyle::unpolish(widget);
con's avatar
con committed
332
    if (panelWidget(widget)) {
con's avatar
con committed
333
        widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
con's avatar
con committed
334 335 336 337
        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
338 339
        else if (qobject_cast<QComboBox*>(widget))
            widget->setAttribute(Qt::WA_Hover, false);
con's avatar
con committed
340 341 342 343 344
    }
}

void ManhattanStyle::polish(QPalette &pal)
{
345
    QProxyStyle::polish(pal);
con's avatar
con committed
346 347
}

348
QIcon ManhattanStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
con's avatar
con committed
349 350 351 352
{
    QIcon icon;
    switch (standardIcon) {
    case QStyle::SP_TitleBarCloseButton:
353 354
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        return QIcon(standardPixmap(standardIcon, option, widget));
con's avatar
con committed
355
    default:
356
        icon = baseStyle()->standardIcon(standardIcon, option, widget);
con's avatar
con committed
357 358 359 360 361 362 363
    }
    return icon;
}

QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
                                       const QWidget *widget) const
{
364
    if (widget && !panelWidget(widget))
365
        return QProxyStyle::standardPixmap(standardPixmap, opt, widget);
366

con's avatar
con committed
367 368
    QPixmap pixmap;
    switch (standardPixmap) {
369 370
    case QStyle::SP_ToolBarHorizontalExtensionButton:
        pixmap = d->extButtonPixmap;
371
        break;
372 373
    case QStyle::SP_TitleBarCloseButton:
        pixmap = d->closeButtonPixmap;
con's avatar
con committed
374 375
        break;
    default:
376
        pixmap = QProxyStyle::standardPixmap(standardPixmap, opt, widget);
377
        break;
con's avatar
con committed
378 379 380 381 382 383 384
    }
    return pixmap;
}

int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
                              QStyleHintReturn *returnData) const
{
385
    int ret = QProxyStyle::styleHint(hint, option, widget, returnData);
con's avatar
con committed
386
    switch (hint) {
387 388 389 390 391
    // 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
392
    case QStyle::SH_EtchDisabledText:
393 394
        if (panelWidget(widget))
            ret = false;
con's avatar
con committed
395
        break;
396 397 398
    case QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren:
        ret = true;
        break;
con's avatar
con committed
399
    default:
400
        break;
con's avatar
con committed
401 402 403 404 405 406 407 408
    }
    return ret;
}

void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                                   QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
409
        return QProxyStyle::drawPrimitive(element, option, painter, widget);
con's avatar
con committed
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 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457

    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);
458 459 460 461
            if (oldState & State_MouseOver)
                t->setDuration(150);
            else
                t->setDuration(75);
con's avatar
con committed
462 463 464 465 466
            t->setStartTime(QTime::currentTime());
        }
    }

    switch (element) {
467 468
/*
case PE_PanelItemViewItem:
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
469 470 471 472 473 474 475
        if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
            if (vopt->state & State_Selected) {
                QLinearGradient gradient;
                gradient.setStart(option->rect.topLeft());
                gradient.setFinalStop(option->rect.bottomRight());
                gradient.setColorAt(0, option->palette.highlight().color().lighter(115));
                gradient.setColorAt(1, option->palette.highlight().color().darker(135));
476
                painter->fillRect(option->rect, gradient);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
477 478 479 480 481 482 483 484 485 486
            } else {
                if (vopt->backgroundBrush.style() != Qt::NoBrush) {
                    QPointF oldBO = painter->brushOrigin();
                    painter->setBrushOrigin(vopt->rect.topLeft());
                    painter->fillRect(vopt->rect, vopt->backgroundBrush);
                    painter->setBrushOrigin(oldBO);
                }
            }
        }
        break;
487
*/
con's avatar
con committed
488 489 490
    case PE_PanelLineEdit:
        {
            painter->save();
491 492 493 494 495 496

            // 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
497
            if (option->state & State_Enabled)
498
                drawCornerImage(d->lineeditImage, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
499
            else
500
                drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 5, 5, 5, 5);
con's avatar
con committed
501 502

            if (option->state & State_HasFocus || option->state & State_MouseOver) {
503
                QColor hover = Utils::StyleHelper::baseColor();
con's avatar
con committed
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
                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) {
528 529 530
                    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
531
                    painter->drawLine(rect.topLeft(), rect.bottomLeft());
532 533
                    painter->drawLine(rect.topRight(), rect.bottomRight());
                   // painter->drawLine(rect.bottomLeft()  + QPoint(1, 0), rect.bottomRight()  - QPoint(1, 0));
con's avatar
con committed
534 535 536
                    QColor highlight(255, 255, 255, 30);
                    painter->setPen(highlight);
                }
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
537 538
                else if (option->state & State_Enabled &&
                         option->state & State_MouseOver) {
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
539
                    QColor lighter(255, 255, 255, 37);
con's avatar
con committed
540 541 542 543 544 545 546 547 548 549
                    painter->fillRect(rect, lighter);
                }
           }
        }
        break;

    case PE_PanelStatusBar:
        {
            painter->save();
            QLinearGradient grad(option->rect.topLeft(), QPoint(rect.center().x(), rect.bottom()));
550 551
            QColor startColor = Utils::StyleHelper::shadowColor().darker(164);
            QColor endColor = Utils::StyleHelper::baseColor().darker(130);
con's avatar
con committed
552 553 554 555 556 557
            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));
558
            painter->setPen(Utils::StyleHelper::borderColor().darker(110));
con's avatar
con committed
559 560 561 562 563 564 565
            painter->drawLine(rect.topLeft(), rect.topRight());
            painter->restore();
        }
        break;

    case PE_IndicatorToolBarSeparator:
        {
566
            QColor separatorColor = Utils::StyleHelper::borderColor();
con's avatar
con committed
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
            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);
610
            QColor dark = Utils::StyleHelper::borderColor();
con's avatar
con committed
611 612
            dark.setAlphaF(0.4);

613
            QColor light = Utils::StyleHelper::baseColor();
con's avatar
con committed
614 615 616 617 618 619 620 621 622 623 624 625 626 627
            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;
628 629 630 631 632
    case PE_IndicatorArrowUp:
    case PE_IndicatorArrowDown:
    case PE_IndicatorArrowRight:
    case PE_IndicatorArrowLeft:
        {
633
            Utils::StyleHelper::drawArrow(element, painter, option);
634 635
        }
        break;
con's avatar
con committed
636 637

    default:
638
        QProxyStyle::drawPrimitive(element, option, painter, widget);
con's avatar
con committed
639 640 641 642 643 644 645 646
        break;
    }
}

void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option,
                                 QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
647
        return QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
648 649 650 651 652

    switch (element) {
    case CE_MenuBarItem:
        painter->save();
        if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
653
            QColor highlightOutline = Utils::StyleHelper::borderColor().lighter(120);
con's avatar
con committed
654 655
            bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
            bool dis = !(mbi->state & State_Enabled);
656
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
con's avatar
con committed
657 658 659 660 661 662 663 664 665 666
            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|
667
                QColor baseColor = Utils::StyleHelper::baseColor();
con's avatar
con committed
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 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
                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)) {
                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 724 725
                }

                customPal.setBrush(QPalette::All, QPalette::ButtonText, QColor(0, 0, 0, 70));

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
726 727
                QString text = option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, editRect.width());
                drawItemText(painter, editRect.translated(0, 1),
con's avatar
con committed
728 729
                             visualAlignment(option->direction, Qt::AlignLeft | Qt::AlignVCenter),
                             customPal, cb->state & State_Enabled, text, QPalette::ButtonText);
730
                customPal.setBrush(QPalette::All, QPalette::ButtonText, Utils::StyleHelper::panelTextColor());
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
731
                drawItemText(painter, editRect,
con's avatar
con committed
732 733 734
                             visualAlignment(option->direction, Qt::AlignLeft | Qt::AlignVCenter),
                             customPal, cb->state & State_Enabled, text, QPalette::ButtonText);
            } else {
735
                QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
            }
        }
        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: {
774
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
con's avatar
con committed
775
            painter->save();
776
            painter->setPen(Utils::StyleHelper::borderColor());
con's avatar
con committed
777 778 779 780 781 782 783 784
            painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
            painter->restore();
        }
        break;

    case CE_ToolBar:
        {
            QString key;
785 786
            QColor keyColor = Utils::StyleHelper::baseColor(lightColored(widget));
            key.sprintf("mh_toolbar %d %d %d", option->rect.width(), option->rect.height(), keyColor.rgb());;
con's avatar
con committed
787 788 789 790

            QPixmap pixmap;
            QPainter *p = painter;
            QRect rect = option->rect;
791
            bool horizontal = option->state & State_Horizontal;
792
            if (Utils::StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) {
con's avatar
con committed
793 794 795 796 797
                pixmap = QPixmap(option->rect.size());
                p = new QPainter(&pixmap);
                rect = QRect(0, 0, option->rect.width(), option->rect.height());
            }

798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
            if (!Utils::StyleHelper::usePixmapCache() || !QPixmapCache::find(key, pixmap)) {
                // 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(p, gradientSpan, rect, drawLightColored);
                else
                    Utils::StyleHelper::verticalGradient(p, gradientSpan, rect, drawLightColored);
            }

            if (Utils::StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) {
                delete p;
                QPixmapCache::insert(key, pixmap);
            }
            if (Utils::StyleHelper::usePixmapCache()) {
                painter->drawPixmap(rect.topLeft(), pixmap);
con's avatar
con committed
819 820
            }

821
            painter->setPen(Utils::StyleHelper::borderColor());
con's avatar
con committed
822 823

            if (horizontal) {
824 825 826
                // 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
827
                QColor lighter(Utils::StyleHelper::sidebarHighlight());
828
                if (widget && widget->property("topBorder").toBool()) {
829 830 831
                    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
832
                } else {
833 834 835
                    painter->drawLine(rect.bottomLeft(), rect.bottomRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft(), rect.topRight());
con's avatar
con committed
836 837
                }
            } else {
838 839
                painter->drawLine(rect.topLeft(), rect.bottomLeft());
                painter->drawLine(rect.topRight(), rect.bottomRight());
con's avatar
con committed
840 841 842 843
            }
        }
        break;
    default:
844
        QProxyStyle::drawControl(element, option, painter, widget);
con's avatar
con committed
845 846 847 848 849 850 851 852
        break;
    }
}

void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                        QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
853
         return     QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870

    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;
871 872 873 874 875 876
            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
877 878 879 880

            QStyleOption tool(0);
            tool.palette = toolbutton->palette;
            if (toolbutton->subControls & SC_ToolButton) {
881 882 883
                tool.rect = button;
                tool.state = bflags;
                drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
con's avatar
con committed
884 885 886 887 888 889 890 891 892 893
            }

            if (toolbutton->state & State_HasFocus) {
                QStyleOptionFocusRect fr;
                fr.QStyleOption::operator=(*toolbutton);
                fr.rect.adjust(3, 3, -3, -3);
                if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
                    fr.rect.adjust(0, 0, -pixelMetric(QStyle::PM_MenuButtonIndicator,
                                                      toolbutton, widget), 0);
                QPen oldPen = painter->pen();
894
                QColor focusColor = Utils::StyleHelper::panelTextColor();
con's avatar
con committed
895 896 897 898 899 900 901 902 903 904
                focusColor.setAlpha(120);
                QPen outline(focusColor, 1);
                outline.setStyle(Qt::DotLine);
                painter->setPen(outline);
                QRect r = option->rect.adjusted(2, 2, -2, -2);
                painter->drawRect(r);
                painter->setPen(oldPen);
            }

            QStyleOptionToolButton label = *toolbutton;
905 906

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

con's avatar
con committed
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
            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);
            } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
932
                int arrowSize = 6;
con's avatar
con committed
933 934 935
                QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1);
                QStyleOptionToolButton newBtn = *toolbutton;
                newBtn.palette = panelPalette(option->palette);
936 937
                newBtn.rect = QRect(ir.right() - arrowSize - 1,
                                    ir.height() - arrowSize - 2, arrowSize, arrowSize);
938
                drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
con's avatar
con committed
939 940 941 942 943
            }
        }
        break;

    case CC_ComboBox:
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
944
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
con's avatar
con committed
945
            painter->save();
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
946 947
            bool isEmpty = cb->currentText.isEmpty() && cb->currentIcon.isNull();
            bool reverse = option->direction == Qt::RightToLeft;
con's avatar
con committed
948 949

            // Draw tool button
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
950
            QLinearGradient grad(option->rect.topRight(), option->rect.bottomRight());
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
951 952 953 954
            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));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
955 956
            painter->setPen(QPen(grad, 0));
            painter->drawLine(rect.topRight(), rect.bottomRight());
957
            grad.setColorAt(0, QColor(0, 0, 0, 30));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
958 959 960
            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));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
961
            painter->setPen(QPen(grad, 0));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
962 963 964 965
            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
966
            QStyleOption toolbutton = *option;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
967 968
            if (isEmpty)
                toolbutton.state &= ~(State_Enabled | State_Sunken);
969 970
            painter->save();
            painter->setClipRect(toolbutton.rect.adjusted(0, 0, -2, 0));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
971
            drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget);
972
            painter->restore();
con's avatar
con committed
973
            // Draw arrow
974
            int menuButtonWidth = 12;
con's avatar
con committed
975 976
            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
977
            QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9);
con's avatar
con committed
978
            if (option->state & State_On)
979 980
                arrowRect.translate(QProxyStyle::pixelMetric(PM_ButtonShiftHorizontal, option, widget),
                                    QProxyStyle::pixelMetric(PM_ButtonShiftVertical, option, widget));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
981

con's avatar
con committed
982 983
            QStyleOption arrowOpt = *option;
            arrowOpt.rect = arrowRect;
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
984 985 986
            if (isEmpty)
                arrowOpt.state &= ~(State_Enabled | State_Sunken);

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
987 988 989 990 991 992 993 994
            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);
            }
con's avatar
con committed
995 996 997 998
            painter->restore();
        }
        break;
    default:
999
        QProxyStyle::drawComplexControl(control, option, painter, widget);
con's avatar
con committed
1000 1001 1002
        break;
    }
}