diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 10:18:55 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 10:18:55 +0100 |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/gui/embedded/qdecorationdefault_qws.cpp |
Long live Qt 4.5!
Diffstat (limited to 'src/gui/embedded/qdecorationdefault_qws.cpp')
-rw-r--r-- | src/gui/embedded/qdecorationdefault_qws.cpp | 803 |
1 files changed, 803 insertions, 0 deletions
diff --git a/src/gui/embedded/qdecorationdefault_qws.cpp b/src/gui/embedded/qdecorationdefault_qws.cpp new file mode 100644 index 0000000000..6e5314d7f2 --- /dev/null +++ b/src/gui/embedded/qdecorationdefault_qws.cpp @@ -0,0 +1,803 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qapplication.h> +#include <qwidget.h> +#include <qpainter.h> +#include <qpaintengine.h> +#include <qdrawutil.h> +#include "qdecorationdefault_qws.h" + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_QWS_DECORATION_DEFAULT) || defined(QT_PLUGIN) + +QPixmap *QDecorationDefault::staticHelpPixmap = 0; +QPixmap *QDecorationDefault::staticMenuPixmap = 0; +QPixmap *QDecorationDefault::staticClosePixmap = 0; +QPixmap *QDecorationDefault::staticMinimizePixmap = 0; +QPixmap *QDecorationDefault::staticMaximizePixmap = 0; +QPixmap *QDecorationDefault::staticNormalizePixmap = 0; + +#ifndef QT_NO_IMAGEFORMAT_XPM + +/* XPM */ +static const char * const default_menu_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 11 1", +/* colors */ +" c #000000", +". c #336600", +"X c #666600", +"o c #99CC00", +"O c #999933", +"+ c #333300", +"@ c #669900", +"# c #999900", +"$ c #336633", +"% c #666633", +"& c #99CC33", +/* pixels */ +"oooooooooooooooo", +"oooooooooooooooo", +"ooooo#.++X#ooooo", +"ooooX Xoooo", +"oooX XO#% X&oo", +"oo# Ooo&@O Ooo", +"oo. Xoo#+ @X Xoo", +"oo+ OoO+ +O# +oo", +"oo+ #O+ +## +oo", +"oo. %@ ++ +. Xoo", +"oo# O@OO+ #oo", +"oooX X##$ Ooo", +"ooooX Xoo", +"oooo&OX++X#OXooo", +"oooooooooooooooo", +"oooooooooooooooo" +}; + +static const char * const default_help_xpm[] = { +"16 16 3 1", +" s None c None", +". c #ffffff", +"X c #707070", +" ", +" ", +" ...... ", +" ..XXXXXX ", +" .XX .XX ", +" .XX .XX ", +" ..XX ", +" ..XX ", +" ..XX ", +" .XX ", +" .XX ", +" .. ", +" .XX ", +" .XX ", +" ", +" "}; + +static const char * const default_close_xpm[] = { +"16 16 3 1", +" s None c None", +". c #ffffff", +"X c #707070", +" ", +" ", +" .X .X ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .XX.XX ", +" .XXX ", +" .XXX ", +" .XX.XX ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .X .X ", +" ", +" "}; + +static const char * const default_maximize_xpm[] = { +"16 16 3 1", +" s None c None", +". c #ffffff", +"X c #707070", +" ", +" ", +" ........... ", +" .XXXXXXXXXX ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X........X ", +" .XXXXXXXXXX ", +" ", +" ", +" "}; + +static const char * const default_minimize_xpm[] = { +"16 16 3 1", +" s None c None", +". c #ffffff", +"X c #707070", +" ", +" ", +" ", +" ", +" ", +" ", +" ... ", +" . X ", +" .XX ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; + +static const char * const default_normalize_xpm[] = { +"16 16 3 1", +" s None c None", +". c #ffffff", +"X c #707070", +" ", +" ", +" ........ ", +" .XXXXXXXX ", +" .X .X ", +" .X .X ", +" ....X... .X ", +" .XXXXXXXX .X ", +" .X .XXXX ", +" .X .X ", +" .X .X ", +" .X......X ", +" .XXXXXXXX ", +" ", +" ", +" "}; + +#endif // QT_NO_IMAGEFORMAT_XPM + +/*! + \class QDecorationDefault + \since 4.4 + \ingroup qws + \brief The QDecorationDefault class is a base class providing default window decorations. + + See the documentation for class QDecoration for a detailed + description. This subclass of QDecoration provides standard + icons for the decoration regions. + + Note that this class is non-portable and only available in + \l{Qt for Embedded Linux}. + */ + +/*! + Default constructor. + */ +QDecorationDefault::QDecorationDefault() + : QDecoration() +{ + menu_width = 20; + help_width = 20; + close_width = 20; + minimize_width = 20; + maximize_width = 20; + normalize_width = 20; +} + +/*! + The constructor deletes the static pixmaps. + */ +QDecorationDefault::~QDecorationDefault() +{ + delete staticMenuPixmap; + delete staticClosePixmap; + delete staticMinimizePixmap; + delete staticMaximizePixmap; + delete staticNormalizePixmap; + + // This makes it safe to delete and then create a QDecorationDefault + staticMenuPixmap = 0; + staticClosePixmap = 0; + staticMinimizePixmap = 0; + staticMaximizePixmap = 0; + staticNormalizePixmap = 0; +} + +/*! + \fn const char **QDecorationDefault::xpmForRegion(int region) + + Returns a pointer to the X pixmap for the icon specified by + \a region. An X pixmap is an ASCII-text-based image. The value + of \a region must be one of a subset of the values of enum + DecorationRegion. The supported values are \e Help, \e Menu, + \e Close, \e Minimize, \e Maximize, and \e Normalize. Other + values of \a region cause zero to be returned. + + \sa QDecoration::DecorationRegion + */ +const char **QDecorationDefault::xpmForRegion(int reg) +{ +#ifdef QT_NO_IMAGEFORMAT_XPM + Q_UNUSED(reg); +#else + switch(reg) + { + case Help: + return (const char **)default_help_xpm; + case Menu: + return (const char **)default_menu_xpm; + case Close: + return (const char **)default_close_xpm; + case Minimize: + return (const char **)default_minimize_xpm; + case Maximize: + return (const char **)default_maximize_xpm; + case Normalize: + return (const char **)default_normalize_xpm; + } +#endif + return 0; +} + +/*! + \fn QPixmap QDecorationDefault::pixmapFor(const QWidget *widget, + int decorationRegion, int &xoff, int &yoff) + + Returns a pointer to the QPixmap for the widget specified by \a widget and + \a decorationRegion. The returned QPixmap is constructed from the default + X pixmap obtained from xpmForRegion(). + + \a xoff and \a yoff specify the offset for the pixmap. + + The value of \a decorationRegion must be one of a subset of the values + of enum DecorationRegion. The supported values are \e Help, + \e Menu, \e Close, \e Minimize, \e Maximize, and \e Normalize. + Other values of \a decorationRegion return 0. + + \sa QDecoration::DecorationRegion +*/ +QPixmap QDecorationDefault::pixmapFor(const QWidget *widget, + int decorationRegion, + int &xoff, + int &/*yoff*/) +{ +#ifdef QT_NO_IMAGEFORMAT_XPM + Q_UNUSED(widget); + Q_UNUSED(decorationRegion); + Q_UNUSED(xoff); + return QPixmap(); +#else + static const char **staticHelpPixmapXPM = 0; + static const char **staticMenuPixmapXPM = 0; + static const char **staticClosePixmapXPM = 0; + static const char **staticMinimizePixmapXPM = 0; + static const char **staticMaximizePixmapXPM = 0; + static const char **staticNormalizePixmapXPM = 0; + const char **xpm; + + // Why don't we just use/extend the enum type... + + if (staticHelpPixmapXPM != (xpm = xpmForRegion(Help)) || !staticHelpPixmap) { + staticHelpPixmapXPM = xpm; + staticHelpPixmap = new QPixmap(xpm); + } + if (staticMenuPixmapXPM != (xpm = xpmForRegion(Menu)) || !staticMenuPixmap) { + staticMenuPixmapXPM = xpm; + staticMenuPixmap = new QPixmap(xpm); + } + if (staticClosePixmapXPM != (xpm = xpmForRegion(Close)) || !staticClosePixmap) { + staticClosePixmapXPM = xpm; + staticClosePixmap = new QPixmap(xpm); + } + if (staticMinimizePixmapXPM != (xpm = xpmForRegion(Minimize)) || !staticMinimizePixmap) { + staticMinimizePixmapXPM = xpm; + staticMinimizePixmap = new QPixmap(xpm); + } + if (staticMaximizePixmapXPM != (xpm = xpmForRegion(Maximize)) || !staticMaximizePixmap) { + staticMaximizePixmapXPM = xpm; + staticMaximizePixmap = new QPixmap(xpm); + } + if (staticNormalizePixmapXPM != (xpm = xpmForRegion(Normalize)) || !staticNormalizePixmap) { + staticNormalizePixmapXPM = xpm; + staticNormalizePixmap = new QPixmap(xpm); + } + + const QPixmap *pm = 0; + + switch (decorationRegion) { + case Help: + pm = staticHelpPixmap; + break; + case Menu: + if (!widget->windowIcon().isNull()) + return widget->windowIcon().pixmap(16,16); //##### QIcon::pixmap() needs a size !!!!!!" + if (!pm) { + xoff = 1; + pm = staticMenuPixmap; + } + break; + case Close: + pm = staticClosePixmap; + break; + case Maximize: + pm = staticMaximizePixmap; + break; + case Normalize: + pm = staticNormalizePixmap; + break; + case Minimize: + pm = staticMinimizePixmap; + break; + default: + break; + } + return *pm; +#endif +} + +/*! + \fn int QDecorationDefault::titleBarHeight(const QWidget *widget) + + Returns the title bar height in pixels for the given \a widget. It is the + greater of 20, or the sum of the application font's line spacing value + plus a border width fudge factor. +*/ +int QDecorationDefault::titleBarHeight(const QWidget *) +{ + return qMax(20, QApplication::fontMetrics().lineSpacing() + BORDER_WIDTH); +} + +/*! + Returns the region specified by \a decorationRegion for the + top-level \a widget. \a rect specifies the rectangle the decoration + wraps. The value of \a decorationRegion is a combination of the + bitmask values of enum DecorationRegion. + */ +QRegion QDecorationDefault::region(const QWidget *widget, + const QRect &rect, + int decorationRegion) +{ + 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; + int state = widget->windowState(); + bool isMinimized = state & Qt::WindowMinimized; + bool isMaximized = state & Qt::WindowMaximized; + + int titleHeight = hasTitle ? titleBarHeight(widget) : 0; + int bw = hasBorder ? BORDER_WIDTH : 0; + int bbw = hasBorder ? BOTTOM_BORDER_WIDTH : 0; + + QRegion region; + switch (decorationRegion) { + case All: { + QRect r(rect.left() - bw, + rect.top() - titleHeight - bw, + rect.width() + 2 * bw, + rect.height() + titleHeight + bw + bbw); + region = r; + region -= rect; + } + break; + + case Title: { + QRect r(rect.left() + + (hasSysMenu ? menu_width : 0), + rect.top() - titleHeight, + rect.width() + - (hasSysMenu ? menu_width : 0) + - close_width + - (hasMaximize ? maximize_width : 0) + - (hasMinimize ? minimize_width : 0) + - (hasContextHelp ? help_width : 0), + + titleHeight); + if (r.width() > 0) + region = r; + } + break; + + case Top: { + QRect r(rect.left() + CORNER_GRAB, + rect.top() - titleHeight - bw, + rect.width() - 2 * CORNER_GRAB, + bw); + region = r; + } + break; + + case Left: { + QRect r(rect.left() - bw, + rect.top() - titleHeight + CORNER_GRAB, + bw, + rect.height() + titleHeight - 2 * CORNER_GRAB); + region = r; + } + break; + + case Right: { + QRect r(rect.right() + 1, + rect.top() - titleHeight + CORNER_GRAB, + bw, + rect.height() + titleHeight - 2 * CORNER_GRAB); + region = r; + } + break; + + case Bottom: { + QRect r(rect.left() + CORNER_GRAB, + rect.bottom() + 1, + rect.width() - 2 * CORNER_GRAB, + bw); + region = r; + } + break; + + case TopLeft: { + QRect r1(rect.left() - bw, + rect.top() - bw - titleHeight, + CORNER_GRAB + bw, + bw); + + QRect r2(rect.left() - bw, + rect.top() - bw - titleHeight, + bw, + CORNER_GRAB + bw); + + region = QRegion(r1) + r2; + } + break; + + case TopRight: { + QRect r1(rect.right() - CORNER_GRAB, + rect.top() - bw - titleHeight, + CORNER_GRAB + bw, + bw); + + QRect r2(rect.right() + 1, + rect.top() - bw - titleHeight, + bw, + CORNER_GRAB + bw); + + region = QRegion(r1) + r2; + } + break; + + case BottomLeft: { + QRect r1(rect.left() - bw, + rect.bottom() + 1, + CORNER_GRAB + bw, + bw); + + QRect r2(rect.left() - bw, + rect.bottom() - CORNER_GRAB, + bw, + CORNER_GRAB + bw); + region = QRegion(r1) + r2; + } + break; + + case BottomRight: { + QRect r1(rect.right() - CORNER_GRAB, + rect.bottom() + 1, + CORNER_GRAB + bw, + bw); + + QRect r2(rect.right() + 1, + rect.bottom() - CORNER_GRAB, + bw, + CORNER_GRAB + bw); + region = QRegion(r1) + r2; + } + break; + + case Menu: { + if (hasSysMenu) { + region = QRect(rect.left(), rect.top() - titleHeight, + menu_width, titleHeight); + } + } + break; + + case Help: { + if (hasContextHelp) { + QRect r(rect.right() + - close_width + - (hasMaximize ? maximize_width : 0) + - (hasMinimize ? minimize_width : 0) + - help_width + 1, rect.top() - titleHeight, + help_width, titleHeight); + if (r.left() > rect.left() + titleHeight) + region = r; + } + } + break; + + + case Minimize: { + if (hasMinimize && !isMinimized) { + QRect r(rect.right() - close_width + - (hasMaximize ? maximize_width : 0) + - minimize_width + 1, rect.top() - titleHeight, + minimize_width, titleHeight); + if (r.left() > rect.left() + titleHeight) + region = r; + } + } + break; + + case Maximize: { + if (hasMaximize && !isMaximized) { + QRect r(rect.right() - close_width - maximize_width + 1, + rect.top() - titleHeight, maximize_width, titleHeight); + if (r.left() > rect.left() + titleHeight) + region = r; + } + } + break; + + case Normalize: { + if (hasMinimize && isMinimized) { + QRect r(rect.right() - close_width + - (hasMaximize ? maximize_width : 0) + - minimize_width + 1, rect.top() - titleHeight, + minimize_width, titleHeight); + if (r.left() > rect.left() + titleHeight) + region = r; + } else if (hasMaximize && isMaximized) { + QRect r(rect.right() - close_width - maximize_width + 1, + rect.top() - titleHeight, maximize_width, titleHeight); + if (r.left() > rect.left() + titleHeight) + region = r; + } + } + break; + + case Close: { + QRect r(rect.right() - close_width + 1, rect.top() - titleHeight, + close_width, titleHeight); + if (r.left() > rect.left() + titleHeight) + region = r; + } + break; + + default: { + int i = 1; + while (i) { + if (i & decorationRegion) + region += this->region(widget, rect, i); + i <<= 1; + } + } + break; + } + + return region; +} + +/*! + Paints the border and title decoration for the top-level \a widget + using the \a painter provided and the decoration \a state. The value + of \a decorationRegion is a combination of the bitmask values of + enum DecorationRegion. + + Note that Qt for Embedded Linux expects this function to return true if any of + the widget's decorations are repainted; otherwise it returns false. + */ +bool QDecorationDefault::paint(QPainter *painter, + const QWidget *widget, + int decorationRegion, + DecorationState state) +{ + if (decorationRegion == None) + return false; + + const QRect titleRect = QDecoration::region(widget, Title).boundingRect(); + const QPalette pal = QApplication::palette(); + int titleHeight = titleRect.height(); + int titleWidth = titleRect.width(); + QRegion oldClipRegion = painter->clipRegion(); + + + 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 == int(All)); + bool handled = false; + + bool porterDuff = painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff); + + if ((paintAll || decorationRegion & Borders) && state == Normal && hasBorder) { + if (hasTitle) { // reduce flicker + QRect rect(widget->rect()); + QRect r(rect.left(), rect.top() - titleHeight, + rect.width(), titleHeight); + painter->setClipRegion(oldClipRegion - r); + } + QRect br = QDecoration::region(widget).boundingRect(); + if (porterDuff) + painter->setCompositionMode(QPainter::CompositionMode_Source); + qDrawWinPanel(painter, br.x(), br.y(), br.width(), + br.height(), pal, false, + &pal.brush(QPalette::Window)); + if (porterDuff) + painter->setCompositionMode(QPainter::CompositionMode_SourceOver); + handled |= true; + } + + if ((paintAll || decorationRegion & Title && titleWidth > 0) && state == Normal && hasTitle) { + painter->setClipRegion(oldClipRegion); + QBrush titleBrush; + QPen titlePen; + + if (widget == qApp->activeWindow()) { + titleBrush = pal.brush(QPalette::Highlight); + titlePen = pal.color(QPalette::HighlightedText); + } else { + titleBrush = pal.brush(QPalette::Window); + titlePen = pal.color(QPalette::Text); + } + + if (porterDuff) + painter->setCompositionMode(QPainter::CompositionMode_Source); + qDrawShadePanel(painter, + titleRect.x(), titleRect.y(), titleRect.width(), titleRect.height(), + pal, true, 1, &titleBrush); + if (porterDuff) + painter->setCompositionMode(QPainter::CompositionMode_SourceOver); + + painter->setPen(titlePen); + painter->drawText(titleRect.x() + 4, titleRect.y(), + titleRect.width() - 8, titleRect.height(), + Qt::AlignVCenter, windowTitleFor(widget)); + handled |= true; + } + + if (state != Hover) { + painter->setClipRegion(oldClipRegion); + if ((paintAll || decorationRegion & Menu) && hasSysMenu) { + paintButton(painter, widget, Menu, state, pal); + handled |= true; + } + + if ((paintAll || decorationRegion & Help) && hasContextHelp) { + paintButton(painter, widget, Help, state, pal); + handled |= true; + } + + if ((paintAll || decorationRegion & Minimize) && hasMinimize) { + paintButton(painter, widget, Minimize, state, pal); + handled |= true; + } + + if ((paintAll || decorationRegion & Maximize) && hasMaximize) { + paintButton(painter, widget, + ((widget->windowState() & Qt::WindowMaximized)? Normalize : Maximize), + state, pal); + handled |= true; + } + + if (paintAll || decorationRegion & Close) { + paintButton(painter, widget, Close, state, pal); + handled |= true; + } + } + return handled; +} + +/*! + \fn void QDecorationDefault::paintButton(QPainter *painter, const + QWidget *widget, int buttonRegion, DecorationState state, + const QPalette &palette) + + Paints a region of the top-level \a widget. The region is + painted in the specified decoration \a state using the + \a painter and \a palette provided. The region to be painted is specified + by \a buttonRegion, which is a combination of the bitmask values of + DecorationRegion. If the value of \a buttonRegion is one of \e Help, + \e Menu, \e Close, \e Minimize, \e Maximize, and \e Normalize, the + button pixmap for that region is painted. + + \sa pixmapFor() + */ +void QDecorationDefault::paintButton(QPainter *painter, + const QWidget *widget, + int buttonRegion, + DecorationState state, + const QPalette &pal) +{ + int xoff = 2; + int yoff = 2; + + const QPixmap pm = pixmapFor(widget, buttonRegion, xoff, yoff); + QRect brect(QDecoration::region(widget, buttonRegion).boundingRect()); + bool porterDuff = painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff); + + if (state & QDecoration::Pressed) { + if (porterDuff) + painter->setCompositionMode(QPainter::CompositionMode_Source); + qDrawWinPanel(painter, brect, pal, true, &pal.brush(QPalette::Window)); + if (porterDuff) + painter->setCompositionMode(QPainter::CompositionMode_SourceOver); + ++xoff; + ++yoff; + } else { + painter->fillRect(brect, pal.brush(QPalette::Window)); + } + + if (!pm.isNull()) + painter->drawPixmap(brect.x() + xoff, brect.y() + yoff, pm); +} + +extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); + +/*! + \internal + */ +QString QDecorationDefault::windowTitleFor(const QWidget *widget) const +{ + return qt_setWindowTitle_helperHelper(widget->windowTitle(), widget); +} + +#endif // QT_NO_QWS_DECORATION_DEFAULT + +QT_END_NAMESPACE |