1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-14 21:23:52 +01:00
LibrePilot/ground/openpilotgcs/src/plugins/coreplugin/manhattanstyle.cpp

1095 lines
44 KiB
C++
Raw Normal View History

/**
******************************************************************************
*
* @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 <QtCore/QLibrary>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
#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>
#include <QtGui/QAbstractItemView>
// 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)
{
const QWidget *p = widget;
while (p) {
if (qobject_cast<const QToolBar *>(p) && styleEnabled(p))
return true;
else if (qobject_cast<const QStatusBar *>(p) && styleEnabled(p))
return true;
else if (qobject_cast<const QMenuBar *>(p) && styleEnabled(p))
return true;
else if (p->property("panelwidget").toBool())
return true;
p = p->parentWidget();
}
return false;
}
class ManhattanStylePrivate
{
public:
ManhattanStylePrivate(const QString &baseStyleName)
{
style = QStyleFactory::create(baseStyleName);
QTC_ASSERT(style, /**/);
lineeditImage = QImage(":/core/images/inputfield.png");
lineeditImage_disabled = QImage(":/core/images/inputfield_disabled.png");
}
~ManhattanStylePrivate()
{
delete style;
style = 0;
}
void init();
public:
QStyle *style;
QImage lineeditImage;
QImage lineeditImage_disabled;
StyleAnimator animator;
};
ManhattanStyle::ManhattanStyle(const QString &baseStyleName)
: QWindowsStyle(), d(new ManhattanStylePrivate(baseStyleName))
{
}
ManhattanStyle::~ManhattanStyle()
{
delete d;
d = 0;
}
QStyle *ManhattanStyle::systemStyle() const
{
return d->style;
}
// 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));
if (left > 0) //top-left
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
{
QPixmap result;
result = d->style->generatedIconPixmap(iconMode, pixmap, opt);
return result;
}
int ManhattanStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
QSizePolicy::ControlType control2,
Qt::Orientation orientation,
const QStyleOption * option ,
const QWidget * widget ) const
{
return d->style->layoutSpacing(control1, control2, orientation, option, widget);
}
QSize ManhattanStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
const QSize &size, const QWidget *widget) const
{
QSize newSize = d->style->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
{
QRect rect;
rect = d->style->subElementRect(element, option, widget);
return rect;
}
QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
SubControl subControl, const QWidget *widget) const
{
QRect rect;
#ifndef Q_WS_MACX
// Not using OSX, size combo dropdown to fit contents
if(control == CC_ComboBox && subControl == SC_ComboBoxListBoxPopup)
{
const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option);
const QComboBox* combo = qobject_cast<const QComboBox*>(widget);
QRect comboRect = cb->rect;
int newWidth = combo->view()->sizeHintForColumn(0);
if(newWidth > comboRect.width())
{
// Set new rectangle, only width matters, list height is set by
// combination of number of combo box items and setMaxVisibleItems
rect.setRect(comboRect.x(), comboRect.y(), newWidth, comboRect.height());
rect = visualRect(cb->direction, cb->rect, rect);
}
else
{
rect = d->style->subControlRect(control, option, subControl, widget);
}
}
else
{
rect = d->style->subControlRect(control, option, subControl, widget);
}
#else
// Using OSX, use default style behaviour as this already sizes the
// combo dropdown to fit
rect = d->style->subControlRect(control, option, subControl, widget);
#endif
return rect;
}
QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
const QPoint &pos, const QWidget *widget) const
{
SubControl result = QStyle::SC_None;
result = d->style->hitTestComplexControl(control, option, pos, widget);
return result;
}
int ManhattanStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
int retval = 0;
retval = d->style->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_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
{
QPalette result;
result = d->style->standardPalette();
return result;
}
void ManhattanStyle::polish(QApplication *app)
{
d->style->polish(app);
}
void ManhattanStyle::unpolish(QApplication *app)
{
d->style->unpolish(app);
}
QPalette panelPalette(const QPalette &oldPalette)
{
QColor color = Utils::StyleHelper::panelTextColor();
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)
{
d->style->polish(widget);
// OxygenStyle forces a rounded widget mask on toolbars
if (d->style->inherits("OxygenStyle")) {
if (qobject_cast<QToolBar*>(widget))
widget->removeEventFilter(d->style);
}
if (panelWidget(widget)) {
widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
if (qobject_cast<QToolButton*>(widget)) {
widget->setAttribute(Qt::WA_Hover);
widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
}
else if (qobject_cast<QLineEdit*>(widget)) {
widget->setAttribute(Qt::WA_Hover);
widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
}
else if (qobject_cast<QLabel*>(widget))
widget->setPalette(panelPalette(widget->palette()));
else if (qobject_cast<QToolBar*>(widget) || widget->property("panelwidget_singlerow").toBool())
widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight());
else if (qobject_cast<QStatusBar*>(widget))
widget->setFixedHeight(Utils::StyleHelper::navigationWidgetHeight() + 2);
else if (qobject_cast<QComboBox*>(widget)) {
widget->setMaximumHeight(Utils::StyleHelper::navigationWidgetHeight() - 2);
widget->setAttribute(Qt::WA_Hover);
}
}
}
void ManhattanStyle::unpolish(QWidget *widget)
{
d->style->unpolish(widget);
if (panelWidget(widget)) {
widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
if (qobject_cast<QTabBar*>(widget))
widget->setAttribute(Qt::WA_Hover, false);
else if (qobject_cast<QToolBar*>(widget))
widget->setAttribute(Qt::WA_Hover, false);
else if (qobject_cast<QComboBox*>(widget))
widget->setAttribute(Qt::WA_Hover, false);
}
}
void ManhattanStyle::polish(QPalette &pal)
{
d->style->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 = d->style->standardIcon(standardIcon, option, widget);
}
return icon;
}
QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
const QWidget *widget) const
{
if (widget && !panelWidget(widget))
return d->style->standardPixmap(standardPixmap, opt, widget);
QPixmap pixmap;
switch (standardPixmap) {
case QStyle::SP_ToolBarHorizontalExtensionButton: {
static const QPixmap extButton(":/core/images/extension.png");
pixmap = extButton;
}
break;
case QStyle::SP_TitleBarCloseButton: {
static const QPixmap closeButton(":/core/images/closebutton.png");
pixmap = closeButton;
}
break;
default:
pixmap = d->style->standardPixmap(standardPixmap, opt, widget);
}
return pixmap;
}
int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
QStyleHintReturn *returnData) const
{
int ret = d->style->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;
default:
break;
}
return ret;
}
void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
{
if (!panelWidget(widget))
return d->style->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<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);
if (oldState & State_MouseOver)
t->setDuration(150);
else
t->setDuration(75);
t->setStartTime(QTime::currentTime());
}
}
switch (element) {
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)
drawCornerImage(d->lineeditImage, painter, option->rect, 2, 2, 2, 2);
else
drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 2, 2, 2, 2);
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);
}
}
}
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:
{
// From windowsstyle but modified to enable AA
if (option->rect.width() <= 1 || option->rect.height() <= 1)
break;
QRect r = option->rect;
int size = qMin(r.height(), r.width());
QPixmap pixmap;
QString pixmapName;
QTextStream(&pixmapName) << "$qt_ia" << "-" << metaObject()->className() <<
"-" << uint(option->state) << "-" << element << "-" << size <<
"-" << option->palette.cacheKey();
// pixmapName.sprintf("%s-%s-%d-%d-%d-%lld",
// "$qt_ia", metaObject()->className(),
// uint(option->state), element,
// size, option->palette.cacheKey());
if (!QPixmapCache::find(pixmapName, pixmap)) {
int border = size/5;
int sqsize = 2*(size/2);
QImage image(sqsize, sqsize, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter imagePainter(&image);
imagePainter.setRenderHint(QPainter::Antialiasing, true);
imagePainter.translate(0.5, 0.5);
QPolygon a;
switch (element) {
case PE_IndicatorArrowUp:
a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize - border, sqsize/2);
break;
case PE_IndicatorArrowDown:
a.setPoints(3, border, sqsize/2, sqsize/2, sqsize - border, sqsize - border, sqsize/2);
break;
case PE_IndicatorArrowRight:
a.setPoints(3, sqsize - border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border);
break;
case PE_IndicatorArrowLeft:
a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border);
break;
default:
break;
}
int bsx = 0;
int bsy = 0;
if (option->state & State_Sunken) {
bsx = pixelMetric(PM_ButtonShiftHorizontal);
bsy = pixelMetric(PM_ButtonShiftVertical);
}
QRect bounds = a.boundingRect();
int sx = sqsize / 2 - bounds.center().x() - 1;
int sy = sqsize / 2 - bounds.center().y() - 1;
imagePainter.translate(sx + bsx, sy + bsy);
if (!(option->state & State_Enabled)) {
QColor foreGround(150, 150, 150, 150);
imagePainter.setBrush(option->palette.mid().color());
imagePainter.setPen(option->palette.mid().color());
} else {
QColor shadow(0, 0, 0, 100);
imagePainter.translate(0, 1);
imagePainter.setPen(shadow);
imagePainter.setBrush(shadow);
QColor foreGround(255, 255, 255, 210);
imagePainter.drawPolygon(a);
imagePainter.translate(0, -1);
imagePainter.setPen(foreGround);
imagePainter.setBrush(foreGround);
}
imagePainter.drawPolygon(a);
imagePainter.end();
pixmap = QPixmap::fromImage(image);
QPixmapCache::insert(pixmapName, pixmap);
}
int xOffset = r.x() + (r.width() - size)/2;
int yOffset = r.y() + (r.height() - size)/2;
painter->drawPixmap(xOffset, yOffset, pixmap);
}
break;
default:
d->style->drawPrimitive(element, option, painter, widget);
break;
}
}
void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
{
if (!panelWidget(widget))
return d->style->drawControl(element, option, painter, widget);
switch (element) {
case CE_MenuBarItem:
painter->save();
if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(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<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);
// Reserve some space for the down-arrow
editRect.adjust(0, 0, -13, 0);
}
customPal.setBrush(QPalette::All, QPalette::ButtonText, QColor(0, 0, 0, 70));
QString text = option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, editRect.width());
drawItemText(painter, editRect.translated(0, 1),
visualAlignment(option->direction, Qt::AlignLeft | Qt::AlignVCenter),
customPal, cb->state & State_Enabled, text, QPalette::ButtonText);
customPal.setBrush(QPalette::All, QPalette::ButtonText, Utils::StyleHelper::panelTextColor());
drawItemText(painter, editRect,
visualAlignment(option->direction, Qt::AlignLeft | Qt::AlignVCenter),
customPal, cb->state & State_Enabled, text, QPalette::ButtonText);
} else {
d->style->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:
{
QString key;
key.sprintf("mh_toolbar %d %d %d", option->rect.width(), option->rect.height(), Utils::StyleHelper::baseColor().rgb());;
QPixmap pixmap;
QPainter *p = painter;
QRect rect = option->rect;
if (Utils::StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) {
pixmap = QPixmap(option->rect.size());
p = new QPainter(&pixmap);
rect = QRect(0, 0, option->rect.width(), option->rect.height());
}
bool horizontal = option->state & State_Horizontal;
// 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());
}
if (horizontal)
Utils::StyleHelper::horizontalGradient(p, gradientSpan, rect);
else
Utils::StyleHelper::verticalGradient(p, gradientSpan, rect);
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(255, 255, 255, 40);
if (widget && widget->property("topBorder").toBool()) {
p->drawLine(rect.topLeft(), rect.topRight());
p->setPen(lighter);
p->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1));
} else {
p->drawLine(rect.bottomLeft(), rect.bottomRight());
p->setPen(lighter);
p->drawLine(rect.topLeft(), rect.topRight());
}
} else {
p->drawLine(rect.topLeft(), rect.bottomLeft());
p->drawLine(rect.topRight(), rect.bottomRight());
}
if (Utils::StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) {
painter->drawPixmap(rect.topLeft(), pixmap);
p->end();
delete p;
QPixmapCache::insert(key, pixmap);
}
}
break;
default:
d->style->drawControl(element, option, painter, widget);
break;
}
}
void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
QPainter *painter, const QWidget *widget) const
{
if (!panelWidget(widget))
return d->style->drawComplexControl(control, option, painter, widget);
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;
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);
}
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();
QColor focusColor = Utils::StyleHelper::panelTextColor();
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;
label.palette = panelPalette(option->palette);
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<const QStyleOptionComboBox *>(option)) {
painter->save();
bool isEmpty = cb->currentText.isEmpty() && cb->currentIcon.isNull();
bool reverse = option->direction == Qt::RightToLeft;
// Draw tool button
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();
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 (option->state & State_On)
arrowRect.translate(d->style->pixelMetric(PM_ButtonShiftHorizontal, option, widget),
d->style->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:
d->style->drawComplexControl(control, option, painter, widget);
break;
}
}
// Mac style reimplements this to control the
// focus widget among other things
bool ManhattanStyle::event(QEvent *e)
{
Q_ASSERT(d->style);
return d->style->event(e);
}