blob: 61f11f67e2ff9bcdd382e5aef6cd3330e4fe8581 [file] [log] [blame]
/****************************************************************************
**
** 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