/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the QtGui module of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.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 the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include <qapplication.h> | |
#include <qwidget.h> | |
#include <qpainter.h> | |
#include <qdrawutil.h> | |
#include "qdecorationstyled_qws.h" | |
#include "qstyle.h" | |
#include "qstyleoption.h" | |
#include "qpaintengine.h" | |
QT_BEGIN_NAMESPACE | |
#if !defined(QT_NO_QWS_DECORATION_STYLED) || defined(QT_PLUGIN) | |
QDecorationStyled::QDecorationStyled() | |
: QDecorationDefault() | |
{ | |
} | |
QDecorationStyled::~QDecorationStyled() | |
{ | |
} | |
int QDecorationStyled::titleBarHeight(const QWidget *widget) | |
{ | |
QStyleOptionTitleBar opt; | |
opt.subControls = QStyle::SC_TitleBarLabel | |
| QStyle::SC_TitleBarSysMenu | |
| QStyle::SC_TitleBarNormalButton | |
| QStyle::SC_TitleBarContextHelpButton | |
| QStyle::SC_TitleBarMinButton | |
| QStyle::SC_TitleBarMaxButton | |
| QStyle::SC_TitleBarCloseButton; | |
opt.titleBarFlags = widget->windowFlags(); | |
opt.direction = QApplication::layoutDirection(); | |
opt.text = windowTitleFor(widget); | |
opt.icon = widget->windowIcon(); | |
opt.rect = widget->rect(); | |
QStyle *style = QApplication::style(); | |
if (!style) | |
return 18; | |
return style->pixelMetric(QStyle::PM_TitleBarHeight, &opt, 0); | |
} | |
bool QDecorationStyled::paint(QPainter *painter, const QWidget *widget, int decorationRegion, | |
DecorationState state) | |
{ | |
if (decorationRegion == None) | |
return false; | |
bool isActive = (widget == qApp->activeWindow()); | |
QPalette pal = qApp->palette(); | |
//ideally, the difference between Active and Inactive should be enough, so we shouldn't need to test this | |
if (!isActive) { | |
//pal.setCurrentColorGroup(QPalette::Disabled); //Can't do this either, because of palette limitations | |
//copied from Q3TitleBar: | |
pal.setColor(QPalette::Inactive, QPalette::Highlight, | |
pal.color(QPalette::Inactive, QPalette::Dark)); | |
pal.setColor(QPalette::Inactive, QPalette::Base, | |
pal.color(QPalette::Inactive, QPalette::Dark)); | |
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, | |
pal.color(QPalette::Inactive, QPalette::Window)); | |
} | |
Qt::WindowFlags flags = widget->windowFlags(); | |
bool hasBorder = !widget->isMaximized(); | |
bool hasTitle = flags & Qt::WindowTitleHint; | |
bool hasSysMenu = flags & Qt::WindowSystemMenuHint; | |
bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint; | |
bool hasMinimize = flags & Qt::WindowMinimizeButtonHint; | |
bool hasMaximize = flags & Qt::WindowMaximizeButtonHint; | |
bool paintAll = (DecorationRegion(decorationRegion) == All); | |
bool handled = false; | |
QStyle *style = QApplication::style(); | |
// In the case of a borderless title bar, the title bar must be expanded one | |
// borderWidth to the left, right and up. | |
bool noTitleBorder = style->styleHint(QStyle::SH_TitleBar_NoBorder, 0, widget); | |
int borderWidth = style->pixelMetric(QStyle::PM_MDIFrameWidth, 0, 0); | |
int titleHeight = titleBarHeight(widget) + (noTitleBorder ? borderWidth : 0); | |
int titleExtra = noTitleBorder ? borderWidth : 0; | |
if ((paintAll || decorationRegion & Borders) && state == Normal && hasBorder) { | |
QRegion newClip = painter->clipRegion(); | |
if (hasTitle) { // reduce flicker | |
QRect rect(widget->rect()); | |
QRect r(rect.left() - titleExtra, rect.top() - titleHeight, | |
rect.width() + 2 * titleExtra, titleHeight); | |
newClip -= r; | |
} | |
if (!newClip.isEmpty()) { | |
QRect br = QDecoration::region(widget).boundingRect(); | |
painter->save(); | |
painter->setClipRegion(newClip); | |
QStyleOptionFrame opt; | |
opt.palette = pal; | |
opt.rect = br; | |
opt.lineWidth = borderWidth; | |
if (isActive) | |
opt.state |= QStyle::State_Active; | |
bool porterDuff = painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff); | |
if (porterDuff) | |
painter->setCompositionMode(QPainter::CompositionMode_Source); | |
painter->fillRect(br, pal.window()); | |
if (porterDuff) | |
painter->setCompositionMode(QPainter::CompositionMode_SourceOver); | |
style->drawPrimitive(QStyle::PE_FrameWindow, &opt, painter, 0); | |
painter->restore(); | |
decorationRegion &= (~Borders); | |
handled |= true; | |
} | |
} | |
if (hasTitle) { | |
painter->save(); | |
QStyleOptionTitleBar opt; | |
opt.subControls = (decorationRegion & Title | |
? QStyle::SC_TitleBarLabel : QStyle::SubControl(0)) | |
| (decorationRegion & Menu | |
? QStyle::SC_TitleBarSysMenu : QStyle::SubControl(0)) | |
| (decorationRegion & Help | |
? QStyle::SC_TitleBarContextHelpButton : QStyle::SubControl(0)) | |
| (decorationRegion & Minimize | |
? QStyle::SC_TitleBarMinButton : QStyle::SubControl(0)) | |
| (decorationRegion & Maximize | |
? QStyle::SC_TitleBarMaxButton : QStyle::SubControl(0)) | |
| (decorationRegion & (Minimize | Maximize) | |
? QStyle::SC_TitleBarNormalButton : QStyle::SubControl(0)) | |
| (decorationRegion & Close | |
? QStyle::SC_TitleBarCloseButton : QStyle::SubControl(0)); | |
opt.titleBarFlags = widget->windowFlags(); | |
opt.titleBarState = widget->windowState(); | |
if (isActive) | |
opt.titleBarState |= QStyle::State_Active; | |
opt.text = windowTitleFor(widget); | |
opt.icon = widget->windowIcon(); | |
opt.palette = pal; | |
opt.rect = QRect(widget->rect().x() - titleExtra, -titleHeight, | |
widget->rect().width() + 2 * titleExtra, titleHeight); | |
if (paintAll) { | |
painter->setClipRegion(opt.rect); | |
} else { | |
const QRect widgetRect = widget->rect(); | |
QRegion newClip = opt.rect; | |
if (!(decorationRegion & Menu) && hasSysMenu) | |
newClip -= region(widget, widgetRect, Menu); | |
if (!(decorationRegion & Title) && hasTitle) | |
newClip -= region(widget, widgetRect, Title); | |
if (!(decorationRegion & Help) && hasContextHelp) | |
newClip -= region(widget, widgetRect, Help); | |
if (!(decorationRegion & Minimize) && hasMinimize) | |
newClip -= region(widget, widgetRect, Minimize); | |
if (!(decorationRegion & Maximize) && hasMaximize) | |
newClip -= region(widget, widgetRect, Maximize); | |
if (!(decorationRegion & (Minimize | Maximize)) && (hasMaximize | hasMinimize)) | |
newClip -= region(widget, widgetRect, Normal); | |
if (!(decorationRegion & Close)) | |
newClip -= region(widget, widgetRect, Close); | |
painter->setClipRegion(newClip); | |
} | |
if (state == Pressed) | |
opt.activeSubControls = opt.subControls; | |
style->drawComplexControl(QStyle::CC_TitleBar, &opt, painter, 0); | |
painter->restore(); | |
decorationRegion &= ~(Title | Menu | Help | Normalize | Minimize | Maximize | Close); | |
handled |= true; | |
} | |
return handled; | |
} | |
QRegion QDecorationStyled::region(const QWidget *widget, const QRect &rect, int decorationRegion) | |
{ | |
QStyle *style = QApplication::style(); | |
// In the case of a borderless title bar, the title bar must be expanded one | |
// borderWidth to the left, right and up. | |
bool noTitleBorder = style->styleHint(QStyle::SH_TitleBar_NoBorder, 0, widget); | |
int borderWidth = style->pixelMetric(QStyle::PM_MDIFrameWidth, 0, 0); | |
int titleHeight = titleBarHeight(widget) + (noTitleBorder ? borderWidth : 0); | |
int titleExtra = noTitleBorder ? borderWidth : 0; | |
QRect inside = QRect(rect.x() - titleExtra, rect.top() - titleHeight, | |
rect.width() + 2 * titleExtra, titleHeight); | |
Qt::WindowFlags flags = widget->windowFlags(); | |
bool hasSysMenu = flags & Qt::WindowSystemMenuHint; | |
bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint; | |
bool hasMinimize = flags & Qt::WindowMinimizeButtonHint; | |
bool hasMaximize = flags & Qt::WindowMaximizeButtonHint; | |
QStyleOptionTitleBar opt; | |
opt.subControls = QStyle::SC_TitleBarLabel | |
| QStyle::SC_TitleBarSysMenu | |
| QStyle::SC_TitleBarNormalButton | |
| QStyle::SC_TitleBarMinButton | |
| QStyle::SC_TitleBarMaxButton | |
| QStyle::SC_TitleBarCloseButton; | |
opt.titleBarFlags = widget->windowFlags(); | |
opt.direction = QApplication::layoutDirection(); | |
opt.text = windowTitleFor(widget); | |
opt.icon = widget->windowIcon(); | |
opt.rect = inside; | |
QRegion region; | |
switch (decorationRegion) { | |
case Title: | |
region = style->subControlRect(QStyle::CC_TitleBar, &opt, | |
QStyle::SC_TitleBarLabel, 0); | |
break; | |
case Menu: | |
if (hasSysMenu) | |
region = style->subControlRect(QStyle::CC_TitleBar, &opt, | |
QStyle::SC_TitleBarSysMenu, 0); | |
break; | |
case Help: | |
if (hasContextHelp) | |
region = style->subControlRect(QStyle::CC_TitleBar, &opt, | |
QStyle::SC_TitleBarContextHelpButton, | |
0); | |
break; | |
case Normalize: | |
if (hasMaximize | hasMinimize) | |
region = style->subControlRect(QStyle::CC_TitleBar, &opt, | |
QStyle::SC_TitleBarNormalButton, | |
0); | |
break; | |
case Minimize: | |
if (hasMinimize) | |
region = style->subControlRect(QStyle::CC_TitleBar, &opt, | |
QStyle::SC_TitleBarMinButton, | |
0); | |
break; | |
case Maximize: | |
if (hasMaximize) | |
region = style->subControlRect(QStyle::CC_TitleBar, &opt, | |
QStyle::SC_TitleBarMaxButton, | |
0); | |
break; | |
case Close: | |
region = style->subControlRect(QStyle::CC_TitleBar, &opt, | |
QStyle::SC_TitleBarCloseButton, 0); | |
break; | |
default: | |
region = QDecorationDefault::region(widget, rect, decorationRegion); | |
} | |
opt.rect = QRect(rect.x() - titleExtra, rect.top() - titleHeight, | |
rect.width() + 2 * titleExtra, | |
rect.height() + titleHeight + titleExtra); | |
QStyleHintReturnMask mask; | |
style->styleHint(QStyle::SH_WindowFrame_Mask, &opt, 0, &mask); | |
return (mask.region.isEmpty() ? region : (region & mask.region)); | |
} | |
#endif // QT_NO_QWS_DECORATION_STYLED | |
QT_END_NAMESPACE |