/** ****************************************************************************** * * @file manhattanstyle.cpp * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. * @addtogroup GCSPlugins GCS Plugins * @{ * @addtogroup CorePlugin Core Plugin * @{ * @brief The Core GCS plugin *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "manhattanstyle.h" #include "styleanimator.h" #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 const QStyle::State State_Animating = QStyle::State(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 ((widget->window()->windowFlags() & Qt::WindowType_Mask) == Qt::Dialog) { 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 ((widget->window()->windowFlags() & Qt::WindowType_Mask) == Qt::Dialog) { 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::Constants::ICON_CLOSE)) {} 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") || baseStyle()->inherits("Oxygen::Style")) { 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_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_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 = Utils::StyleHelper::statusBarGradient(rect); painter->fillRect(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_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; bool drawIcon = !(widget && widget->property("hideicon").toBool()); if (!cb->currentIcon.isNull() && drawIcon) { 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); } QLatin1Char asterisk('*'); int elideWidth = editRect.width(); bool notElideAsterisk = widget && widget->property("notelideasterisk").toBool() && cb->currentText.endsWith(asterisk) && option->fontMetrics.width(cb->currentText) > elideWidth; QString text; if (notElideAsterisk) { elideWidth -= option->fontMetrics.width(asterisk); text = asterisk; } text.prepend(option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, elideWidth)); if ((option->state & State_Enabled)) { painter->setPen(QColor(0, 0, 0, 70)); painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text); } else { painter->setOpacity(0.8); } painter->setPen(Utils::StyleHelper::panelTextColor()); painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text); 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); } if (!drawLightColored) { painter->setPen(Utils::StyleHelper::borderColor()); } else { painter->setPen(QColor(0x888888)); } 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 (drawLightColored) { lighter = QColor(255, 255, 255, 180); } 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)) { bool reverse = option->direction == Qt::RightToLeft; bool drawborder = (widget && widget->property("showborder").toBool()); if (drawborder) { drawButtonSeparator(painter, rect, reverse); } 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); } else if (!Utils::HostOsInfo::isMacHost() && (mflags & State_MouseOver)) { QColor shade(255, 255, 255, 50); painter->fillRect(tool.rect.adjusted(0, -1, 1, 1), shade); } } tool.rect = tool.rect.adjusted(2, 2, -2, -2); drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); } else if (toolbutton->features & QStyleOptionToolButton::HasMenu && !widget->property("noArrow").toBool()) { 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()); if (drawborder) { drawButtonSeparator(painter, rect, reverse); } 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 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)); } } 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; } } void ManhattanStyle::drawButtonSeparator(QPainter *painter, const QRect &rect, bool reverse) const { QLinearGradient grad(rect.topRight(), rect.bottomRight()); grad.setColorAt(0, QColor(255, 255, 255, 20)); grad.setColorAt(0.4, QColor(255, 255, 255, 60)); grad.setColorAt(0.7, QColor(255, 255, 255, 50)); grad.setColorAt(1, QColor(255, 255, 255, 40)); painter->setPen(QPen(grad, 0)); painter->drawLine(rect.topRight(), rect.bottomRight()); grad.setColorAt(0, QColor(0, 0, 0, 30)); grad.setColorAt(0.4, QColor(0, 0, 0, 70)); grad.setColorAt(0.7, QColor(0, 0, 0, 70)); grad.setColorAt(1, QColor(0, 0, 0, 40)); painter->setPen(QPen(grad, 0)); if (!reverse) { painter->drawLine(rect.topRight() - QPoint(1, 0), rect.bottomRight() - QPoint(1, 0)); } else { painter->drawLine(rect.topLeft(), rect.bottomLeft()); } }