/**************************************************************************** ** ** Copyright (C) 2007-2007 Trolltech ASA. All rights reserved. ** ** This file is part of the DotNetStyle project on Trolltech Labs. ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of ** this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** http://www.trolltech.com/products/qt/opensource.html ** ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http://www.trolltech.com/products/qt/licensing.html or contact the ** sales department at sales@trolltech.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifdef USE_DOTNET_STYLE #include "dotnetstyle.h" #include #include #include #include #include #include #include #include #include #include #include #include #include typedef bool (WINAPI *PtrIsAppThemed)(); typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); static PtrIsAppThemed pIsAppThemed = 0; static PtrGetCurrentThemeName pGetCurrentThemeName = 0; static const int windowsItemFrame = 2; // menu item frame width static const int windowsSepHeight = 9; // separator item height static const int windowsItemHMargin = 3; // menu item hor text margin static const int windowsItemVMargin = 2; // menu item ver text margin static const int windowsArrowHMargin = 6; // arrow horizontal margin static const int windowsRightBorder = 15; // right border on windows class DotNetStylePrivate { public: DotNetStylePrivate() { QLibrary themeLib("uxtheme"); themeLib.load(); if (themeLib.isLoaded()) { //resolve uxtheme functions pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); pGetCurrentThemeName = (PtrGetCurrentThemeName)themeLib.resolve("GetCurrentThemeName"); } } ~DotNetStylePrivate() {} enum InternalPalette { Blue, Silver, Olive, System, Classic }; void init(); QColor gradientDarkColor(const QStyleOption *option) const; QColor gradientLightColor(const QStyleOption *option) const; QColor highlightOutlineColor(const QStyleOption *option, bool act) const; QColor shadowColor(const QStyleOption *option) const; QBrush highlightBrush(const QStyleOption *option, bool act) const; QBrush highlightMenuCheckBrush(const QStyleOption *option, bool act) const; QLinearGradient toolbarGradient(const QStyleOption *option, QRect rect, Qt::Orientation orientation) const; QLinearGradient menuGradient(const QStyleOption *option, QRect rect, Qt::Orientation orientation) const; void updatePalette(); QColor menuSeparatorColor; QColor menuBackgroundColor; QColor menuFrameColor; InternalPalette internalPalette; //internal color theme DotNetStyle::ColorTheme theme; //external color theme QPalette currentPal; //used to detect system palette changes }; inline QColor DotNetStylePrivate::gradientDarkColor(const QStyleOption *option) const { QColor color = option->palette.background().color(); switch (internalPalette) { case Olive: color = QColor(217, 217, 167); break; case Blue: color = QColor(158, 190, 245); break; case Silver: color = QColor(216, 216, 229); break; default: break; } return color; } inline QColor DotNetStylePrivate::gradientLightColor(const QStyleOption *option) const { QColor color = option->palette.background().color().lighter(106); switch (internalPalette) { case Olive: color = QColor(241, 240, 227); break; case Blue: color = QColor(196, 217, 249); break; case Silver: color = QColor(242, 242, 247); break; case Classic: color = option->palette.light().color().lighter(106); default: break; } return color; } inline QColor DotNetStylePrivate::shadowColor(const QStyleOption *option) const { QColor color; switch (internalPalette) { case Blue: color = QColor(59, 97, 156); break; case Silver: color = QColor(124, 124, 148); break; case Olive: color = QColor(96, 128, 88); break; case Classic: color = option->palette.background().color(); break; default: color = option->palette.dark().color(); break; } return color; } inline QColor DotNetStylePrivate::highlightOutlineColor(const QStyleOption *option, bool act = false) const { QColor color; switch (internalPalette) { case Blue: color = QColor(0, 0, 128); break; case Silver: color = QColor(75, 75, 111); break; case Olive: color = QColor(63, 93, 56); break; default: if (act) return option->palette.highlight().color().darker(110); else return option->palette.highlight().color().lighter(110); break; } return color; } QBrush DotNetStylePrivate::highlightBrush(const QStyleOption *option, bool act) const { QBrush brush; QColor highlight; switch (internalPalette) { case Silver: case Olive: case Blue: if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { brush = QColor(255, 238, 194); } else { QLinearGradient gradient(option->rect.topLeft(), option->rect.bottomLeft()); if (act) { gradient.setColorAt(0, QColor(254, 149, 82)); gradient.setColorAt(1, QColor(255, 211, 142)); } else { gradient.setColorAt(0, QColor(255, 252, 200)); gradient.setColorAt(1, QColor(255, 208, 145)); } brush = gradient; } break; default: highlight = option->palette.highlight().color().lighter(120); if (act) highlight.setHsv(highlight.hue(), 70, 220); else highlight.setHsv(highlight.hue(), 40, 230); brush = QBrush(highlight); break; } return brush; } QBrush DotNetStylePrivate::highlightMenuCheckBrush(const QStyleOption *option, bool act) const { QBrush brush; QColor highlight; switch (internalPalette) { case Silver: case Olive: case Blue: if (act) brush = QColor(254, 128, 62); else brush = QColor(255, 192, 111); break; default: highlight = option->palette.highlight().color().lighter(120); if (act) highlight.setHsv(highlight.hue(), 120, 180); else { highlight.setHsv(highlight.hue(), 30, 230); } highlight.setAlpha(170); brush = highlight; break; } return brush; } QLinearGradient DotNetStylePrivate::toolbarGradient(const QStyleOption *option, QRect rect, Qt::Orientation orientation= Qt::Vertical) const { QLinearGradient gradient(rect.topLeft(), orientation == Qt::Vertical ? rect.topRight() : rect.bottomLeft()); QColor start, stop; switch (internalPalette) { case Blue: start = QColor(220, 235, 254); stop = QColor(129, 169, 226); gradient.setColorAt(0.3, start); break; case Silver: start = QColor(242, 242, 249); stop = QColor(153, 151, 181); gradient.setColorAt(0.3, start); break; case Olive: start = QColor(241, 245, 217); stop = QColor(183, 198, 145); gradient.setColorAt(0.0, start); break; default: start = option->palette.light().color(); if (internalPalette == Classic) start = start.lighter(130); start.setAlpha(180); stop = option->palette.button().color(); stop.setHsv(stop.hue(), qMin(stop.saturation()*2, 255), (stop.value()*2)/3); stop.setAlpha(128); if (internalPalette == Classic) stop.setAlpha(0); gradient.setColorAt(0.3, start); break; } gradient.setColorAt(1, stop); return gradient; } QLinearGradient DotNetStylePrivate::menuGradient(const QStyleOption *option, QRect rect, Qt::Orientation orientation = Qt::Horizontal) const { QColor start, stop; QLinearGradient grad; if (orientation == Qt::Vertical) { grad.setStart(rect.left(), rect.top()); grad.setFinalStop(rect.left(), rect.bottom()); } else { grad.setStart(QPoint(rect.left(), 0)); grad.setFinalStop(QPoint(rect.left() + 24, 0)); } switch (internalPalette) { case Blue: start = QColor(220, 235, 254); stop = QColor(129, 169, 226); grad.setColorAt(0.3, start); break; case Olive: start = QColor(246, 248, 224); stop = QColor(186, 201, 148); grad.setColorAt(0.0, start); break; case Silver: start = QColor(215, 215, 226); stop = QColor(138, 137, 166); grad.setColorAt(0.4, start); break; default: start = option->palette.brush(QPalette::Active, QPalette::Base).color(); stop = gradientDarkColor(option); stop.setHsv(stop.hue(), qMin((int)(stop.saturation()*1.2), 255), (5*stop.value()/7)); if (internalPalette == Classic) stop.setAlpha(120); grad.setColorAt(0, start); break; } grad.setColorAt(1, stop); return grad; } /*! \class DotNetStyle qtdotnetstyle.h \brief The DotNetStyle class provides an alternative, modern look for Qt applications on Windows. The GUI look is very similar to the style introduced in Visual Studio 2005, Office 2003 as well as in .NET Windows Forms (when the RenderMode is set to "Professional" instead of "System"). It gives applications a modern gradient appearance for tool bars and menus while retaining the native look and feel for other widgets. The style supports different color themes, which may be specified in the constructor. The default is \c Standard color theme. This is the textedit example running with the Standard style: \img dotnetstyle.png This is the textedit example running with the Office style: \img dotnetstyle2.png \sa QStyle, QWindowsVistaStyle, QWindowsXPStyle */ /*! \enum DotNetStyle::ColorTheme This enum describes the different color schemes supported by the style. \value Standard Use gradients based on the operating system palette. \value Office Use Microsoft Office 2003 style gradients. */ /*! Constructs a DotNetStyle object which uses the default color theme (\c Office). */ DotNetStyle::DotNetStyle() : QWindowsVistaStyle(), d(new DotNetStylePrivate()) { d->theme = Office; } /*! Constructs a DotNetStyle object which uses the color theme \a colortheme. */ DotNetStyle::DotNetStyle(ColorTheme colortheme) : QWindowsVistaStyle(), d(new DotNetStylePrivate()) { d->theme = colortheme; } /*! Destroys the DotNetStyle object. */ DotNetStyle::~DotNetStyle() { delete d; } /*! \reimp */ void DotNetStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { QColor gradientDark = d->gradientDarkColor(option); QColor gradientLight = d->gradientLightColor(option); QColor shadow = d->shadowColor(option); QRect rect = option->rect; switch (element) { case PE_IndicatorDockWidgetResizeHandle: break; case PE_PanelLineEdit: if (widget && qobject_cast(widget->parentWidget())) { QRect rect = option->rect.adjusted(2, 1, -2, -2); painter->save(); bool active = option->state & State_Active && ((option->state & State_MouseOver) || (option->state & State_HasFocus)); QBrush editBrush = option->palette.brush(QPalette::Base); painter->setPen(QPen(editBrush.color())); painter->fillRect(rect, editBrush); QRect re = option->rect ; if (active) { painter->setPen(d->highlightOutlineColor(option)); painter->drawRect(rect); } painter->restore(); } else { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::drawPrimitive(element, option, painter, widget); else QWindowsXPStyle::drawPrimitive(element, option, painter, widget); } case PE_PanelButtonTool: { QStyleOption opt2 = *option; if (widget) if(QDockWidget *dw = qobject_cast(widget->parentWidget())) { if (!dw->isFloating()) opt2.palette.setBrush(QPalette::Button, Qt::transparent); } if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::drawPrimitive(element, &opt2, painter, widget); else QWindowsXPStyle::drawPrimitive(element, &opt2, painter, widget); } break; case PE_FrameMenu: { QPen pen = painter->pen(); QBrush brush = painter->brush(); if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(option)) { Qt::Orientation orientation =(toolbar->toolBarArea == Qt::RightToolBarArea || toolbar->toolBarArea == Qt::LeftToolBarArea) ? Qt::Vertical : Qt::Horizontal; painter->setBrush(d->toolbarGradient(toolbar, toolbar->rect, orientation)); } else { painter->setBrush(d->menuBackgroundColor); } painter->setPen(d->menuFrameColor); painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); painter->setPen(pen); painter->setBrush(brush); } break; case PE_Widget: if (const QMainWindow *mw = qobject_cast(widget)) { if (d->currentPal != qApp->palette()) //workaround for style polish on theme color change { d->currentPal = qApp->palette(); d->updatePalette(); } painter->save(); QPoint begin = widget->geometry().topRight(); QPoint end = widget->geometry().topLeft() + QPoint(0, widget->geometry().height()/2); begin = widget->mapFromGlobal(begin); end = widget->mapFromGlobal(end); QLinearGradient menubargradient(begin, end); menubargradient.setColorAt(0, gradientLight); if (d->internalPalette == DotNetStylePrivate::System) menubargradient.setColorAt(0.3, gradientDark); else menubargradient.setColorAt(0.8, gradientDark); menubargradient.setColorAt(1, gradientDark); QRect windowRect = option->rect; if (QStatusBar *statusBar = mw->findChild()) { windowRect.adjust(0, 0, 0, -statusBar->height()); painter->setPen(option->palette.background().color().lighter(106)); painter->drawLine(windowRect.bottomLeft() + QPoint(0, 1), windowRect.bottomRight() + QPoint(0, 1)); } painter->fillRect(windowRect, menubargradient); painter->restore(); } break; case PE_IndicatorToolBarSeparator: { QRect rect = option->rect; shadow.setAlpha(180); painter->setPen(shadow); const int margin = 3; 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); painter->setPen(QPen(option->palette.background().color().light(110))); painter->drawLine(rect.bottomLeft().x() + offset + 1, rect.bottomLeft().y() - margin, rect.topLeft().x() + offset + 1, rect.topLeft().y() + margin); } else { //Draw vertical separator const int offset = rect.height()/2; painter->setPen(QPen(option->palette.background().color().dark(110))); painter->drawLine(rect.topLeft().x() + margin , rect.topLeft().y() + offset, rect.topRight().x() - margin, rect.topRight().y() + offset); painter->setPen(QPen(option->palette.background().color().light(110))); painter->drawLine(rect.topLeft().x() + margin , rect.topLeft().y() + offset + 1, rect.topRight().x() - margin, rect.topRight().y() + offset + 1); } } break; case PE_IndicatorToolBarHandle: painter->save(); { QColor gripColor = shadow; if (d->internalPalette != DotNetStylePrivate::System) gripColor = shadow.darker(120); if (option->state & State_Horizontal) { for (int i = rect.height()/5; i <= 4*(rect.height()/5) ; i+=4) { int y = rect.topLeft().y() + i + 1; int x1 = rect.topLeft().x() + 3; painter->fillRect(x1 + 1, y, 2, 2, Qt::white); painter->fillRect(x1, y - 1, 2, 2, gripColor); } } else { //vertical toolbar for (int i = rect.width()/5; i <= 4*(rect.width()/5) ; i+=4) { int x = rect.topLeft().x() + i + 1; int y1 = rect.topLeft().y() + 3; painter->fillRect(x , y1 + 1, 2, 2, Qt::white); painter->fillRect(x - 1, y1, 2, 2, gripColor); } } } painter->restore(); break; case PE_PanelMenuBar: break; default: if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::drawPrimitive(element, option, painter, widget); else QWindowsXPStyle::drawPrimitive(element, option, painter, widget); break; } } /*! \reimp */ void DotNetStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { QColor gradientDark = d->gradientDarkColor(option); QColor gradientLight = d->gradientLightColor(option); QColor shadow = d->shadowColor(option); QRect rect = option->rect; switch (element) { #ifndef QT_NO_MENU case CE_MenuItem: painter->save(); if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { int x, y, w, h; QStyleOptionMenuItem mbiCopy = *menuitem; painter->fillRect(rect, d->menuBackgroundColor); painter->fillRect(QRect(0, rect.top(), 25, rect.bottom()), d->menuGradient(option, rect)); menuitem->rect.getRect(&x, &y, &w, &h); int tab = menuitem->tabWidth; bool dis = !(menuitem->state & State_Enabled); bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable ? menuitem->checked : false; bool act = menuitem->state & State_Selected; // windows always has a check column, regardless whether we have an icon or not int checkcol = qMax(menuitem->maxIconWidth, 20); if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { int yoff = y-1 + h / 2; painter->setPen(d->menuSeparatorColor); painter->drawLine(x + 32, yoff, x + w + 6, yoff); painter->restore(); return; } QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height())); vCheckRect.adjust(2, 0, 0, 0); if (act) { painter->setPen(d->highlightOutlineColor(option)); painter->setBrush(d->highlightBrush(option, false)); painter->drawRect(option->rect.adjusted(0, 0, -2, -2)); } if (!menuitem->icon.isNull()) { QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; if (act && !dis) mode = QIcon::Active; QPixmap pixmap; if (checked) pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize), mode, QIcon::On); else pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize), mode); int pixw = pixmap.width(); int pixh = pixmap.height(); QRect pmr(0, 0, pixw, pixh); pmr.moveCenter(vCheckRect.center()); painter->setPen(menuitem->palette.text().color()); painter->drawPixmap(pmr.topLeft(), pixmap); } else if (checked) { painter->save(); painter->setPen(d->highlightOutlineColor(option, act)); painter->setBrush(d->highlightMenuCheckBrush(option, act)); painter->drawRect(vCheckRect.adjusted(-1, 1, 0, -3)); painter->restore(); QStyleOptionMenuItem newMi = *menuitem; newMi.state = State_None; if (!dis) newMi.state |= State_Enabled; if (act) newMi.state |= State_On; newMi.rect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x() + windowsItemFrame, menuitem->rect.y() + windowsItemFrame, checkcol - 2 * windowsItemFrame, menuitem->rect.height() - 2*windowsItemFrame)); drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, painter, widget); } painter->setPen(menuitem->palette.buttonText().color()); QColor discol; if (dis) { discol = menuitem->palette.text().color(); painter->setPen(discol); } int xm = windowsItemFrame + checkcol + windowsItemHMargin; int xpos = menuitem->rect.x() + xm; QRect textRect(xpos + 5, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect); QString s = menuitem->text; if (!s.isEmpty()) { // draw text painter->save(); int t = s.indexOf(QLatin1Char('\t')); int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) text_flags |= Qt::TextHideMnemonic; text_flags |= Qt::AlignLeft; if (t >= 0) { QRect vShortcutRect = visualRect(option->direction, menuitem->rect, QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); if (dis && !act) { painter->setPen(discol); } painter->drawText(vShortcutRect, text_flags, s.mid(t + 1)); s = s.left(t); } QFont font = menuitem->font; if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) font.setBold(true); painter->setFont(font); if (dis && !act) { painter->setPen(discol); } painter->drawText(vTextRect, text_flags, s.left(t)); painter->restore(); } if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow int dim = (h - 2 * windowsItemFrame) / 2; PrimitiveElement arrow; arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); QStyleOptionMenuItem newMI = *menuitem; newMI.rect = vSubMenuRect; newMI.state = dis ? State_None : State_Enabled; drawPrimitive(arrow, &newMI, painter, widget); } } painter->restore(); break; #endif // QT_NO_MENU case CE_MenuEmptyArea: { painter->fillRect(option->rect, option->palette.base()); QLinearGradient grad(QPoint(rect.left() , 0), QPoint(rect.left() + 23, 0)); grad.setColorAt(0, gradientLight.light(110)); grad.setColorAt(1, gradientDark); painter->fillRect(QRect(0, rect.top() + 2, 23, rect.bottom() - 3), grad); } break; case CE_MenuBarItem: if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) { QRect rect(QPoint(0, 0), widget->window()->size()); { if (widget->window()) drawPrimitive(PE_Widget, option, painter, widget); } if (option->state & (QStyle::State_Sunken | QStyle::State_Selected)) { QColor highlight = shadow; painter->setPen(d->menuFrameColor); if (option->state & QStyle::State_Sunken) { if (d->internalPalette == DotNetStylePrivate::System) painter->setBrush(Qt::white); else painter->setBrush(d->menuGradient(option, option->rect, Qt::Vertical)); painter->drawRect(option->rect.adjusted(0, 2, -1, 0)); //draw shadow behind: QColor shade = Qt::black; shade.setAlpha(50); painter->setBrush(shade); painter->setPen(Qt::transparent); QRect shadowRect(option->rect.topRight() + QPoint(0, 4), option->rect.bottomRight() + QPoint(1,0)); painter->drawRect(shadowRect); } else { painter->setPen(d->highlightOutlineColor(option)); painter->setBrush(d->highlightBrush(option, false)); painter->drawRect(option->rect.adjusted(0, 2, -2, -2)); } } QStyleOptionMenuItem mbiCopy = *mbi; QPalette pal = mbi->palette; pal.setBrush(QPalette::All, QPalette::ButtonText, mbi->palette.text()); mbiCopy.palette = pal; QCommonStyle::drawControl(element, &mbiCopy, painter, widget); } break; case CE_MenuBarEmptyArea: if (widget->window()) drawPrimitive(PE_Widget, option, painter, widget); break; case CE_DockWidgetTitle: if (const QDockWidget *dockWidget = qobject_cast(widget)) { painter->save(); if (d->internalPalette == DotNetStylePrivate::System) { painter->setBrush(option->palette.dark().color().light(130)); painter->setPen(option->palette.dark().color()); } else if (d->internalPalette == DotNetStylePrivate::Classic) { painter->setBrush(option->palette.background().color().dark(108)); painter->setPen(option->palette.dark().color()); } else { painter->setBrush(d->toolbarGradient(option, option->rect, Qt::Horizontal)); QColor color = d->gradientDarkColor(option).darker(120); painter->setPen(color); } painter->drawRect(rect.adjusted(0, 2, -1, -3)); if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) { QRect titleRect = option->rect.adjusted(6, 2, 0, 0); int buttonMargin = 4; int mw = pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); if (dwOpt->closable) { QPixmap pm = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).pixmap(10, 10); titleRect.adjust(0, 0, -pm.size().width() - mw - buttonMargin, 0); } if (dwOpt->floatable) { QPixmap pm = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).pixmap(10, 10); titleRect.adjust(0, 0, -pm.size().width() - mw - buttonMargin, 0); } titleRect = visualRect(option->direction, option->rect, titleRect); if (!dwOpt->title.isEmpty()) { QString titleText = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); drawItemText(painter, titleRect, Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette, dwOpt->state & State_Enabled, titleText, QPalette::WindowText); } painter->restore(); } break; } case CE_ToolBar: if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(option)) { painter->save(); rect.adjust(1, 0, 0, 0); if (const QToolBar *tb = qobject_cast(widget)) { if (option->direction == Qt::LeftToRight) rect.setRight(tb->childrenRect().right() + 2); else rect.setLeft(tb->childrenRect().left() - 2); } Qt::Orientation gradientOrientation =(toolbar->toolBarArea == Qt::RightToolBarArea || toolbar->toolBarArea == Qt::LeftToolBarArea) ? Qt::Vertical : Qt::Horizontal; QLinearGradient gradient = d->toolbarGradient(toolbar, rect, gradientOrientation); painter->setBrush(gradient); painter->setPen(Qt::NoPen); bool roundEdges = true; if (widget && widget->parentWidget()) { if (const QToolBar *tb = qobject_cast(widget)) { if (!(tb->childrenRect().width() + 32 < widget->parentWidget()->geometry().width())) { roundEdges = false; rect.adjust(-1, 0, 0, 0); } } } if (roundEdges) { rect = rect.adjusted(1, 1, -1, 0); QRegion region = rect; region -= QRect(rect.left(), rect.bottom(), 2, 1); region -= QRect(rect.right() - 1, rect.bottom(), 2, 1); region -= QRect(rect.left(), rect.bottom() - 1, 1, 1); region -= QRect(rect.right(), rect.bottom() - 1, 1, 1); region -= QRect(rect.left(), rect.top(), 2, 1); region -= QRect(rect.right() - 1, rect.top(), 2, 1); region -= QRect(rect.left(), rect.top() + 1, 1, 1); region -= QRect(rect.right(), rect.top() + 1, 1, 1); painter->setClipRegion(region); painter->fillRect(rect, gradient); painter->setPen(QPen(shadow, 0)); painter->drawLine(rect.bottomLeft() + QPoint(3,0), rect.bottomRight() - QPoint(2,0)); painter->drawPoint(rect.bottomRight() - QPoint(1, 1)); QColor alphashadow = shadow; alphashadow.setAlpha(128); painter->setPen(QPen(alphashadow, 0)); painter->drawLine(rect.topRight() + QPoint(0, 2), rect.bottomRight() - QPoint(0, 2)); } else { painter->fillRect(rect, gradient); } painter->restore(); } break; default: if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::drawControl(element, option, painter, widget); else QWindowsXPStyle::drawControl(element, option, painter, widget); break; } } /*! \reimp */ void DotNetStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { switch (control) { case CC_ComboBox: if (widget && qobject_cast(widget->parentWidget())) { QColor highlightedOutlineColor = d->highlightOutlineColor(option); if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { bool active = cmb->state & State_Active && ((cmb->state & State_MouseOver) || (cmb->state & State_On) || (cmb->state & State_HasFocus)); QRect editRect = QWindowsStyle::subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget).adjusted(0, 0, 3, 1); QRect rect = option->rect.adjusted(1, 1, -3, -2); editRect.setLeft(rect.left()); if (cmb->subControls & SC_ComboBoxEditField) { painter->save(); QBrush editBrush = cmb->palette.brush(QPalette::Base); painter->setPen(QPen(editBrush.color())); painter->drawRect(rect); painter->fillRect(editRect, editBrush); if (active) { QColor highlight = highlightedOutlineColor; painter->setPen(highlight); painter->drawRect(rect); } painter->restore(); } if (cmb->subControls & SC_ComboBoxArrow) { State flags = State_None; QRect ar = QWindowsStyle::subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget).adjusted(1, 0, -1, 0); if (active) { painter->save(); painter->fillRect(ar, d->highlightBrush(option, cmb->state & State_Sunken)); painter->setPen(highlightedOutlineColor); painter->drawLine(ar.topLeft(), ar.bottomLeft()); painter->restore(); } ar.adjust(5, 5, -2, -2); if (option->state & State_Enabled) flags |= State_Enabled; QStyleOption arrowOpt(0); arrowOpt.rect = ar; arrowOpt.palette = cmb->palette; arrowOpt.state = flags; QWindowsStyle::drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); } } } else { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::drawComplexControl(control, option, painter, widget); else QWindowsXPStyle::drawComplexControl(control, option, painter, widget); } break; case CC_ToolButton: if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(option)) { QRect button; button = subControlRect(control, toolbutton, SC_ToolButton, widget); if ((widget && qobject_cast(widget->parentWidget())) && ((toolbutton->state & State_MouseOver && toolbutton->state & State_Enabled) || toolbutton->state & State_On)) { QLinearGradient menubargradient2(button.topLeft(), button.bottomLeft()); bool act = (toolbutton->state & State_Sunken) || (toolbutton->state & State_On); painter->setPen(d->highlightOutlineColor(option, act)); painter->setBrush(d->highlightBrush(option, act)); painter->drawRect(button.adjusted(0, 0, -2, -1)); QStyleOptionComplex comp; comp.init(widget); comp.rect = button; QStyleOptionToolButton label = *toolbutton; int fw = pixelMetric(PM_DefaultFrameWidth, option, widget); label.rect = button.adjusted(fw, fw, -fw, -fw); label.features &= ~QStyleOptionToolButton::Arrow; drawControl(CE_ToolButtonLabel, &label, painter, widget); if (toolbutton->subControls & SC_ToolButtonMenu) { QStyleOption tool = *toolbutton; tool.rect = QWindowsStyle::subControlRect(control, toolbutton, SC_ToolButtonMenu, widget); painter->setPen(d->highlightOutlineColor(option, act)); painter->setBrush(d->highlightBrush(option, toolbutton->activeSubControls & SC_ToolButtonMenu)); painter->drawRect(tool.rect.adjusted(-2, 0, -1, -1)); tool.rect.adjust(2, 3, -2, -2); drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); } } else if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::drawComplexControl(control, option, painter, widget); else QWindowsXPStyle::drawComplexControl(control, option, painter, widget); } break; default: if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::drawComplexControl(control, option, painter, widget); else QWindowsXPStyle::drawComplexControl(control, option, painter, widget); break; } } /*! \reimp */ QSize DotNetStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const { QSize newSize; if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) newSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget); else newSize = QWindowsXPStyle::sizeFromContents(type, option, size, widget); switch (type) { case CT_LineEdit: if (widget && qobject_cast(widget->parentWidget())) { newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); newSize += QSize(0, 2); } break; case CT_ComboBox: if (widget && qobject_cast(widget->parentWidget())) { newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); newSize += QSize(0, 2); } break; case CT_MenuBarItem: newSize += QSize(0, 1); break; case CT_MenuItem: if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); if (menuitem->menuItemType == QStyleOptionMenuItem::Separator){ newSize.setHeight(2); } else { newSize.rwidth() += 10; //ensure menu items have uniform height if (newSize.height() < 22) newSize.setHeight(22); } } break; case CT_Menu: //work around for a menu frame issue (same as xp style) newSize = size; newSize -= QSize(1,2); break; default: break; } return newSize; } /*! \reimp */ QRect DotNetStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { QRect rect; if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) rect = QWindowsVistaStyle::subElementRect(element, option, widget); else rect = QWindowsXPStyle::subElementRect(element, option, widget); if (element == SE_DockWidgetCloseButton || element == SE_DockWidgetFloatButton) rect.translate(0, 1); return rect; } /*! \reimp */ QRect DotNetStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const { QRect rect; if (control == CC_ComboBox && widget && qobject_cast(widget->parentWidget())) rect = QWindowsStyle::subControlRect(control, option, subControl, widget); else if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) rect = QWindowsVistaStyle::subControlRect(control, option, subControl, widget); else rect = QWindowsXPStyle::subControlRect(control, option, subControl, widget); return rect; } /*! \reimp */ QStyle::SubControl DotNetStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) return QWindowsVistaStyle::hitTestComplexControl(control, option, pos, widget); else return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget); } /*! \reimp */ int DotNetStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { int retval = 0; if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) retval = QWindowsVistaStyle::pixelMetric(metric, option, widget); else retval = QWindowsXPStyle::pixelMetric(metric, option, widget); switch (metric) { case PM_ToolBarItemSpacing: retval = 2; break; case PM_ToolBarIconSize: retval = 16; break; case PM_MenuHMargin: retval = 1; break; case PM_MenuVMargin: retval = 1; break; case PM_MenuBarPanelWidth: retval = 0; break; case PM_MenuPanelWidth: retval = 1; break; case PM_DockWidgetTitleBarButtonMargin: retval = 6; break; case PM_DefaultFrameWidth: case PM_SpinBoxFrameWidth: if (widget && qobject_cast(widget->parentWidget())) retval = 2; break; case PM_ButtonShiftVertical: case PM_ButtonShiftHorizontal: if (widget && qobject_cast(widget->parentWidget())) retval = 0; break; default: break; } return retval; } /*! \reimp */ QPalette DotNetStyle::standardPalette() const { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) return QWindowsVistaStyle::standardPalette(); else return QWindowsXPStyle::standardPalette(); } void DotNetStylePrivate::updatePalette() { //Detect color palette const int maxlength = 256; WCHAR themeFileName[maxlength]; WCHAR themeColor[maxlength]; internalPalette = Classic; if (pIsAppThemed && pIsAppThemed() && pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { QString name = QString::fromUtf16((ushort *)themeFileName); QString color = QString::fromUtf16((ushort *)themeColor); if (theme == DotNetStyle::Standard) { if (name.endsWith("Luna.msstyles")) { if (color == "Metallic") internalPalette = Silver; else internalPalette = System; } } else { //Office style if (name.endsWith("Luna.msstyles")) { if (color == "HomeStead") internalPalette = Olive; else if (color == "Metallic") internalPalette = Silver; else internalPalette = Blue; } else if (name.endsWith("Aero.msstyles")) { internalPalette = Blue; } } } switch (internalPalette) { case Blue: menuSeparatorColor = QColor(106, 140, 203); menuBackgroundColor = QColor(246, 246, 246); menuFrameColor = QColor(0, 45, 150); break; case Silver: menuSeparatorColor = QColor(110, 109, 143); menuBackgroundColor = QColor(254, 250, 255); menuFrameColor = QColor(124, 124, 148); break; case Olive: menuSeparatorColor = QColor(96, 128, 88); menuBackgroundColor = QColor(244, 244, 238); menuFrameColor = QColor(117, 141, 94); break; default: menuFrameColor = currentPal.dark().color().lighter(108); menuSeparatorColor = currentPal.background().color().darker(110); menuBackgroundColor = currentPal.light().color(); menuBackgroundColor.setHsv( menuBackgroundColor.hue(), 3 * menuBackgroundColor.saturation()/8 , 250); break; } } /*! \reimp */ void DotNetStyle::polish(QApplication *app) { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::polish(app); else QWindowsXPStyle::polish(app); d->currentPal = app->palette(); d->updatePalette(); } /*! \reimp */ void DotNetStyle::unpolish(QApplication *app) { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::unpolish(app); else QWindowsXPStyle::unpolish(app); } /*! \reimp */ void DotNetStyle::polish(QWidget *widget) { if (qobject_cast(widget)) widget->setAttribute(Qt::WA_StyledBackground); else if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover); else if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover); if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::polish(widget); else QWindowsXPStyle::polish(widget); } /*! \reimp */ void DotNetStyle::unpolish(QWidget *widget) { if (qobject_cast(widget)) widget->setAttribute(Qt::WA_StyledBackground, false); else if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover, false); if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::unpolish(widget); else QWindowsXPStyle::unpolish(widget); } /*! \reimp */ void DotNetStyle::polish(QPalette &pal) { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) QWindowsVistaStyle::polish(pal); else QWindowsXPStyle::polish(pal); } /*! \reimp */ QPixmap DotNetStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const { if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) return QWindowsVistaStyle::standardPixmap(standardPixmap, opt, widget); else return QWindowsXPStyle::standardPixmap(standardPixmap, opt, widget); } /*! \reimp */ int DotNetStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { int ret = 0; if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) ret = QWindowsVistaStyle::styleHint(hint, option, widget, returnData); else ret = QWindowsXPStyle::styleHint(hint, option, widget, returnData); return ret; } #endif //USE_DOTNET_STYLE