/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** 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. ** ** GNU Lesser General Public License Usage ** ** 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. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "manhattanstyle.h" #include "styleanimator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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) { if (!widget) return false; // Do not style dialogs or explicitly ignored widgets if (qobject_cast(widget->window())) return false; if (qobject_cast(widget)) return true; if (qobject_cast(widget)) return styleEnabled(widget); const QWidget *p = widget; while (p) { if (qobject_cast(p) || qobject_cast(p) || qobject_cast(p) || p->property("panelwidget").toBool()) return styleEnabled(widget); p = p->parentWidget(); } return false; } // 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(widget->window())) return false; const QWidget *p = widget; while (p) { if (p->property("lightColored").toBool()) return true; p = p->parentWidget(); } return false; } class ManhattanStylePrivate { public: explicit ManhattanStylePrivate(); void init(); public: const QImage lineeditImage; const QImage lineeditImage_disabled; const QPixmap extButtonPixmap; const QPixmap closeButtonPixmap; StyleAnimator animator; }; ManhattanStylePrivate::ManhattanStylePrivate() : 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")) { } ManhattanStyle::ManhattanStyle(const QString &baseStyleName) : QProxyStyle(QStyleFactory::create(baseStyleName)), d(new ManhattanStylePrivate()) { } ManhattanStyle::~ManhattanStyle() { delete d; d = 0; } QPixmap ManhattanStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const { return QProxyStyle::generatedIconPixmap(iconMode, pixmap, opt); } QSize ManhattanStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const { QSize newSize = QProxyStyle::sizeFromContents(type, option, size, widget); if (type == CT_Splitter && widget && widget->property("minisplitter").toBool()) return QSize(1, 1); else if (type == CT_ComboBox && panelWidget(widget)) newSize += QSize(14, 0); return newSize; } QRect ManhattanStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::subElementRect(element, option, widget); } QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const { return QProxyStyle::subControlRect(control, option, subControl, widget); } QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const { return QProxyStyle::hitTestComplexControl(control, option, pos, widget); } int ManhattanStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { int retval = 0; retval = QProxyStyle::pixelMetric(metric, option, widget); 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_DockWidgetHandleExtent: case PM_DockWidgetSeparatorExtent: return 1; 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(widget) && panelWidget(widget)) return 1; break; default: break; } return retval; } QPalette ManhattanStyle::standardPalette() const { return QProxyStyle::standardPalette(); } void ManhattanStyle::polish(QApplication *app) { return QProxyStyle::polish(app); } void ManhattanStyle::unpolish(QApplication *app) { return QProxyStyle::unpolish(app); } QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false) { QColor color = Utils::StyleHelper::panelTextColor(lightColored); 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) { QProxyStyle::polish(widget); // OxygenStyle forces a rounded widget mask on toolbars and dock widgets if (baseStyle()->inherits("OxygenStyle")) { if (qobject_cast(widget) || qobject_cast(widget)) { widget->removeEventFilter(baseStyle()); widget->setContentsMargins(0, 0, 0, 0); } } if (panelWidget(widget)) { // Oxygen and possibly other styles override this if (qobject_cast(widget)) widget->setContentsMargins(0, 0, 0, 0); widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, true); if (qobject_cast(widget)) { widget->setAttribute(Qt::WA_Hover); widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2); } else if (qobject_cast(widget)) { widget->setAttribute(Qt::WA_Hover); widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2); } else if (qobject_cast(widget)) widget->setPalette(panelPalette(widget->palette())); else if (widget->property("panelwidget_singlerow").toBool()) widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight()); else if (qobject_cast(widget)) widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight() + 2); else if (qobject_cast(widget)) { widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2); widget->setAttribute(Qt::WA_Hover); } } } void ManhattanStyle::unpolish(QWidget *widget) { QProxyStyle::unpolish(widget); if (panelWidget(widget)) { widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, false); if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover, false); } } void ManhattanStyle::polish(QPalette &pal) { QProxyStyle::polish(pal); } QIcon ManhattanStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { QIcon icon; switch (standardIcon) { case QStyle::SP_TitleBarCloseButton: case QStyle::SP_ToolBarHorizontalExtensionButton: return QIcon(standardPixmap(standardIcon, option, widget)); default: icon = baseStyle()->standardIcon(standardIcon, option, widget); } return icon; } QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const { if (widget && !panelWidget(widget)) return QProxyStyle::standardPixmap(standardPixmap, opt, widget); QPixmap pixmap; switch (standardPixmap) { case QStyle::SP_ToolBarHorizontalExtensionButton: pixmap = d->extButtonPixmap; break; case QStyle::SP_TitleBarCloseButton: pixmap = d->closeButtonPixmap; break; default: pixmap = QProxyStyle::standardPixmap(standardPixmap, opt, widget); break; } return pixmap; } int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { int ret = QProxyStyle::styleHint(hint, option, widget, returnData); switch (hint) { // Make project explorer alternate rows all the way case QStyle::SH_ItemView_PaintAlternatingRowColorsForEmptyArea: if (widget && widget->property("AlternateEmpty").toBool()) ret = true; break; case QStyle::SH_EtchDisabledText: if (panelWidget(widget)) ret = false; break; case QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren: ret = true; break; default: break; } return ret; } void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { if (!panelWidget(widget)) return QProxyStyle::drawPrimitive(element, option, painter, widget); 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 (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); if (oldState & State_MouseOver) t->setDuration(150); else t->setDuration(75); t->setStartTime(QTime::currentTime()); } } switch (element) { case PE_IndicatorDockWidgetResizeHandle: painter->fillRect(option->rect, Utils::StyleHelper::borderColor()); break; case PE_FrameDockWidget: QCommonStyle::drawPrimitive(element, option, painter, widget); break; case PE_PanelLineEdit: { painter->save(); // Fill the line edit background QRect filledRect = option->rect.adjusted(1, 1, -1, -1); painter->setBrushOrigin(filledRect.topLeft()); painter->fillRect(filledRect, option->palette.base()); if (option->state & State_Enabled) Utils::StyleHelper::drawCornerImage(d->lineeditImage, painter, option->rect, 5, 5, 5, 5); else Utils::StyleHelper::drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 5, 5, 5, 5); if (option->state & State_HasFocus || option->state & State_MouseOver) { QColor hover = Utils::StyleHelper::baseColor(); 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) { QColor shade(0, 0, 0, 40); painter->fillRect(rect, shade); painter->drawLine(rect.topLeft() + QPoint(1, 0), rect.topRight() - QPoint(1, 0)); painter->drawLine(rect.topLeft(), rect.bottomLeft()); painter->drawLine(rect.topRight(), rect.bottomRight()); // painter->drawLine(rect.bottomLeft() + QPoint(1, 0), rect.bottomRight() - QPoint(1, 0)); QColor highlight(255, 255, 255, 30); painter->setPen(highlight); } else if (option->state & State_Enabled && option->state & State_MouseOver) { QColor lighter(255, 255, 255, 37); painter->fillRect(rect, lighter); } 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); } } } break; case PE_PanelStatusBar: { painter->save(); QLinearGradient grad(option->rect.topLeft(), QPoint(rect.center().x(), rect.bottom())); QColor startColor = Utils::StyleHelper::shadowColor().darker(164); QColor endColor = Utils::StyleHelper::baseColor().darker(130); 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)); painter->setPen(Utils::StyleHelper::borderColor().darker(110)); painter->drawLine(rect.topLeft(), rect.topRight()); painter->restore(); } break; case PE_IndicatorToolBarSeparator: { QColor separatorColor = Utils::StyleHelper::borderColor(); 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); QColor dark = Utils::StyleHelper::borderColor(); dark.setAlphaF(0.4); QColor light = Utils::StyleHelper::baseColor(); 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; case PE_IndicatorArrowUp: case PE_IndicatorArrowDown: case PE_IndicatorArrowRight: case PE_IndicatorArrowLeft: { Utils::StyleHelper::drawArrow(element, painter, option); } break; default: QProxyStyle::drawPrimitive(element, option, painter, widget); break; } } void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { if (!panelWidget(widget)) return QProxyStyle::drawControl(element, option, painter, widget); switch (element) { 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(option)) { QStyleOptionTabV3 adjustedTab = *tab; if (tab->cornerWidgets == QStyleOptionTab::NoCornerWidgets && ( tab->position == QStyleOptionTab::Beginning || tab->position == QStyleOptionTab::OnlyOneTab)) { 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; case CE_MenuBarItem: painter->save(); if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) { QColor highlightOutline = Utils::StyleHelper::borderColor().lighter(120); bool act = mbi->state & State_Selected && mbi->state & State_Sunken; bool dis = !(mbi->state & State_Enabled); Utils::StyleHelper::menuGradient(painter, option->rect, option->rect); QStyleOptionMenuItem item = *mbi; item.rect = mbi->rect; QPalette pal = mbi->palette; pal.setBrush(QPalette::ButtonText, dis ? Qt::gray : Qt::black); item.palette = pal; QCommonStyle::drawControl(element, &item, painter, widget); QRect r = option->rect; if (act) { // Fill| QColor baseColor = Utils::StyleHelper::baseColor(); QLinearGradient grad(option->rect.topLeft(), option->rect.bottomLeft()); grad.setColorAt(0, baseColor.lighter(120)); grad.setColorAt(1, baseColor.lighter(130)); painter->fillRect(option->rect.adjusted(1, 1, -1, 0), grad); // Outline painter->setPen(QPen(highlightOutline, 0)); painter->drawLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom())); painter->drawLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom())); painter->drawLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())); highlightOutline.setAlpha(60); painter->setPen(QPen(highlightOutline, 0)); painter->drawPoint(r.topLeft()); painter->drawPoint(r.topRight()); QPalette pal = mbi->palette; uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; if (!styleHint(SH_UnderlineShortcut, mbi, widget)) alignment |= Qt::TextHideMnemonic; pal.setBrush(QPalette::Text, dis ? Qt::gray : QColor(0, 0, 0, 60)); drawItemText(painter, item.rect.translated(0, 1), alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text); pal.setBrush(QPalette::Text, dis ? Qt::gray : Qt::white); drawItemText(painter, item.rect, alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text); } } painter->restore(); break; case CE_ComboBoxLabel: if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { if (panelWidget(widget)) { painter->save(); 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); // Reserve some space for the down-arrow editRect.adjust(0, 0, -13, 0); } QString text = option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, editRect.width()); if ((option->state & State_Enabled)) { painter->setPen(QColor(0, 0, 0, 70)); painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, cb->currentText); } else { painter->setOpacity(0.8); } painter->setPen(Utils::StyleHelper::panelTextColor()); painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, cb->currentText); painter->restore(); } else { QProxyStyle::drawControl(element, option, painter, widget); } } 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: { Utils::StyleHelper::menuGradient(painter, option->rect, option->rect); painter->save(); painter->setPen(Utils::StyleHelper::borderColor()); painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); painter->restore(); } break; case CE_ToolBar: { QRect rect = option->rect; bool horizontal = option->state & State_Horizontal; 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); painter->setPen(Utils::StyleHelper::borderColor()); if (horizontal) { // Note: This is a hack to determine if the // toolbar should draw the top or bottom outline // (needed for the find toolbar for instance) QColor lighter(Utils::StyleHelper::sidebarHighlight()); if (widget && widget->property("topBorder").toBool()) { painter->drawLine(rect.topLeft(), rect.topRight()); painter->setPen(lighter); painter->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1)); } else { painter->drawLine(rect.bottomLeft(), rect.bottomRight()); painter->setPen(lighter); painter->drawLine(rect.topLeft(), rect.topRight()); } } else { painter->drawLine(rect.topLeft(), rect.bottomLeft()); painter->drawLine(rect.topRight(), rect.bottomRight()); } } break; default: QProxyStyle::drawControl(element, option, painter, widget); break; } } void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { if (!panelWidget(widget)) return QProxyStyle::drawComplexControl(control, option, painter, widget); QRect rect = option->rect; switch (control) { case CC_ToolButton: if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(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; if (toolbutton->state & State_Sunken) { if (toolbutton->activeSubControls & SC_ToolButton) bflags |= State_Sunken; if (toolbutton->activeSubControls & SC_ToolButtonMenu) mflags |= State_Sunken; } QStyleOption tool(0); tool.palette = toolbutton->palette; if (toolbutton->subControls & SC_ToolButton) { tool.rect = button; tool.state = bflags; drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); } QStyleOptionToolButton label = *toolbutton; label.palette = panelPalette(option->palette, lightColored(widget)); int fw = pixelMetric(PM_DefaultFrameWidth, option, widget); label.rect = button.adjusted(fw, fw, -fw, -fw); 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) { int arrowSize = 6; QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1); QStyleOptionToolButton newBtn = *toolbutton; newBtn.palette = panelPalette(option->palette); newBtn.rect = QRect(ir.right() - arrowSize - 1, ir.height() - arrowSize - 2, arrowSize, arrowSize); drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); } } break; case CC_ComboBox: if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { painter->save(); bool isEmpty = cb->currentText.isEmpty() && cb->currentIcon.isNull(); bool reverse = option->direction == Qt::RightToLeft; bool drawborder = !(widget && widget->property("hideborder").toBool()); bool alignarrow = !(widget && widget->property("alignarrow").toBool()); // Draw tool button 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()); } QStyleOption toolbutton = *option; if (isEmpty) toolbutton.state &= ~(State_Enabled | State_Sunken); painter->save(); if (drawborder) painter->setClipRect(toolbutton.rect.adjusted(0, 0, -2, 0)); drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget); painter->restore(); // Draw arrow int menuButtonWidth = 12; int left = !reverse ? rect.right() - menuButtonWidth : rect.left(); int right = !reverse ? rect.right() : rect.left() + menuButtonWidth; QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9); if (!alignarrow) { int leftOffset = option->fontMetrics.width(cb->currentText) + 12; arrowRect.moveLeft(leftOffset); } if (option->state & State_On) arrowRect.translate(QProxyStyle::pixelMetric(PM_ButtonShiftHorizontal, option, widget), QProxyStyle::pixelMetric(PM_ButtonShiftVertical, option, widget)); QStyleOption arrowOpt = *option; arrowOpt.rect = arrowRect; if (isEmpty) arrowOpt.state &= ~(State_Enabled | State_Sunken); 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); } painter->restore(); } break; default: QProxyStyle::drawComplexControl(control, option, painter, widget); break; } }