blob: 31ffe21428a01ba003c8099ba94eff92945082b6 [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 "qworkspace.h"
#ifndef QT_NO_WORKSPACE
#include "qapplication.h"
#include "qbitmap.h"
#include "qcursor.h"
#include "qdesktopwidget.h"
#include "qevent.h"
#include "qhash.h"
#include "qicon.h"
#include "qimage.h"
#include "qlabel.h"
#include "qlayout.h"
#include "qmenubar.h"
#include "qmenu.h"
#include "qpainter.h"
#include "qpointer.h"
#include "qscrollbar.h"
#include "qstyle.h"
#include "qstyleoption.h"
#include "qelapsedtimer.h"
#include "qtooltip.h"
#include "qdebug.h"
#include <private/qwidget_p.h>
#include <private/qwidgetresizehandler_p.h>
#include <private/qlayoutengine_p.h>
QT_BEGIN_NAMESPACE
class QWorkspaceTitleBarPrivate;
/**************************************************************
* QMDIControl
*
* Used for displaying MDI controls in a maximized MDI window
*
*/
class QMDIControl : public QWidget
{
Q_OBJECT
signals:
void _q_minimize();
void _q_restore();
void _q_close();
public:
QMDIControl(QWidget *widget);
private:
QSize sizeHint() const;
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void leaveEvent(QEvent *event);
bool event(QEvent *event);
void initStyleOption(QStyleOptionComplex *option) const;
QStyle::SubControl activeControl; //control locked by pressing and holding the mouse
QStyle::SubControl hoverControl; //previously active hover control, used for tracking repaints
};
bool QMDIControl::event(QEvent *event)
{
if (event->type() == QEvent::ToolTip) {
QStyleOptionComplex opt;
initStyleOption(&opt);
#ifndef QT_NO_TOOLTIP
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
helpEvent->pos(), this);
if (ctrl == QStyle::SC_MdiCloseButton)
QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Close"), this);
else if (ctrl == QStyle::SC_MdiMinButton)
QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Minimize"), this);
else if (ctrl == QStyle::SC_MdiNormalButton)
QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Restore Down"), this);
else
QToolTip::hideText();
#endif // QT_NO_TOOLTIP
}
return QWidget::event(event);
}
void QMDIControl::initStyleOption(QStyleOptionComplex *option) const
{
option->initFrom(this);
option->subControls = QStyle::SC_All;
option->activeSubControls = QStyle::SC_None;
}
QMDIControl::QMDIControl(QWidget *widget)
: QWidget(widget), activeControl(QStyle::SC_None),
hoverControl(QStyle::SC_None)
{
setObjectName(QLatin1String("qt_maxcontrols"));
setFocusPolicy(Qt::NoFocus);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setMouseTracking(true);
}
QSize QMDIControl::sizeHint() const
{
ensurePolished();
QStyleOptionComplex opt;
initStyleOption(&opt);
QSize size(48, 16);
return style()->sizeFromContents(QStyle::CT_MdiControls, &opt, size, this);
}
void QMDIControl::mousePressEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton) {
event->ignore();
return;
}
QStyleOptionComplex opt;
initStyleOption(&opt);
QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
event->pos(), this);
activeControl = ctrl;
update();
}
void QMDIControl::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton) {
event->ignore();
return;
}
QStyleOptionTitleBar opt;
initStyleOption(&opt);
QStyle::SubControl under_mouse = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
event->pos(), this);
if (under_mouse == activeControl) {
switch (activeControl) {
case QStyle::SC_MdiCloseButton:
emit _q_close();
break;
case QStyle::SC_MdiNormalButton:
emit _q_restore();
break;
case QStyle::SC_MdiMinButton:
emit _q_minimize();
break;
default:
break;
}
}
activeControl = QStyle::SC_None;
update();
}
void QMDIControl::leaveEvent(QEvent * /*event*/)
{
hoverControl = QStyle::SC_None;
update();
}
void QMDIControl::mouseMoveEvent(QMouseEvent *event)
{
QStyleOptionTitleBar opt;
initStyleOption(&opt);
QStyle::SubControl under_mouse = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
event->pos(), this);
//test if hover state changes
if (hoverControl != under_mouse) {
hoverControl = under_mouse;
update();
}
}
void QMDIControl::paintEvent(QPaintEvent *)
{
QPainter p(this);
QStyleOptionComplex opt;
initStyleOption(&opt);
if (activeControl == hoverControl) {
opt.activeSubControls = activeControl;
opt.state |= QStyle::State_Sunken;
} else if (hoverControl != QStyle::SC_None && (activeControl == QStyle::SC_None)) {
opt.activeSubControls = hoverControl;
opt.state |= QStyle::State_MouseOver;
}
style()->drawComplexControl(QStyle::CC_MdiControls, &opt, &p, this);
}
class QWorkspaceTitleBar : public QWidget
{
Q_OBJECT
Q_DECLARE_PRIVATE(QWorkspaceTitleBar)
Q_PROPERTY(bool autoRaise READ autoRaise WRITE setAutoRaise)
Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
public:
QWorkspaceTitleBar (QWidget *w, QWidget *parent, Qt::WindowFlags f = 0);
~QWorkspaceTitleBar();
bool isActive() const;
bool usesActiveColor() const;
bool isMovable() const;
void setMovable(bool);
bool autoRaise() const;
void setAutoRaise(bool);
QWidget *window() const;
bool isTool() const;
QSize sizeHint() const;
void initStyleOption(QStyleOptionTitleBar *option) const;
public slots:
void setActive(bool);
signals:
void doActivate();
void doNormal();
void doClose();
void doMaximize();
void doMinimize();
void doShade();
void showOperationMenu();
void popupOperationMenu(const QPoint&);
void doubleClicked();
protected:
bool event(QEvent *);
#ifndef QT_NO_CONTEXTMENU
void contextMenuEvent(QContextMenuEvent *);
#endif
void mousePressEvent(QMouseEvent *);
void mouseDoubleClickEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void paintEvent(QPaintEvent *p);
private:
Q_DISABLE_COPY(QWorkspaceTitleBar)
};
class QWorkspaceTitleBarPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QWorkspaceTitleBar)
public:
QWorkspaceTitleBarPrivate()
:
lastControl(QStyle::SC_None),
#ifndef QT_NO_TOOLTIP
toolTip(0),
#endif
act(0), window(0), movable(1), pressed(0), autoraise(0), moving(0)
{
}
Qt::WindowFlags flags;
QStyle::SubControl buttonDown;
QStyle::SubControl lastControl;
QPoint moveOffset;
#ifndef QT_NO_TOOLTIP
QToolTip *toolTip;
#endif
bool act :1;
QPointer<QWidget> window;
bool movable :1;
bool pressed :1;
bool autoraise :1;
bool moving : 1;
int titleBarState() const;
void readColors();
};
inline int QWorkspaceTitleBarPrivate::titleBarState() const
{
Q_Q(const QWorkspaceTitleBar);
uint state = window ? window->windowState() : static_cast<Qt::WindowStates>(Qt::WindowNoState);
state |= uint((act && q->isActiveWindow()) ? QStyle::State_Active : QStyle::State_None);
return (int)state;
}
void QWorkspaceTitleBar::initStyleOption(QStyleOptionTitleBar *option) const
{
Q_D(const QWorkspaceTitleBar);
option->initFrom(this);
//################
if (d->window && (d->flags & Qt::WindowTitleHint)) {
option->text = d->window->windowTitle();
QIcon icon = d->window->windowIcon();
QSize s = icon.actualSize(QSize(64, 64));
option->icon = icon.pixmap(s);
}
option->subControls = QStyle::SC_All;
option->activeSubControls = QStyle::SC_None;
option->titleBarState = d->titleBarState();
option->titleBarFlags = d->flags;
option->state &= ~QStyle::State_MouseOver;
}
QWorkspaceTitleBar::QWorkspaceTitleBar(QWidget *w, QWidget *parent, Qt::WindowFlags f)
: QWidget(*new QWorkspaceTitleBarPrivate, parent, Qt::FramelessWindowHint)
{
Q_D(QWorkspaceTitleBar);
if (f == 0 && w)
f = w->windowFlags();
d->flags = f;
d->window = w;
d->buttonDown = QStyle::SC_None;
d->act = 0;
if (w) {
if (w->maximumSize() != QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX))
d->flags &= ~Qt::WindowMaximizeButtonHint;
setWindowTitle(w->windowTitle());
}
d->readColors();
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
setMouseTracking(true);
setAutoRaise(style()->styleHint(QStyle::SH_TitleBar_AutoRaise, 0, this));
}
QWorkspaceTitleBar::~QWorkspaceTitleBar()
{
}
#ifdef Q_WS_WIN
static inline QRgb colorref2qrgb(COLORREF col)
{
return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
}
#endif
void QWorkspaceTitleBarPrivate::readColors()
{
Q_Q(QWorkspaceTitleBar);
QPalette pal = q->palette();
bool colorsInitialized = false;
#ifdef Q_WS_WIN // ask system properties on windows
#ifndef SPI_GETGRADIENTCAPTIONS
#define SPI_GETGRADIENTCAPTIONS 0x1008
#endif
#ifndef COLOR_GRADIENTACTIVECAPTION
#define COLOR_GRADIENTACTIVECAPTION 27
#endif
#ifndef COLOR_GRADIENTINACTIVECAPTION
#define COLOR_GRADIENTINACTIVECAPTION 28
#endif
if (QApplication::desktopSettingsAware()) {
pal.setColor(QPalette::Active, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)));
pal.setColor(QPalette::Inactive, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)));
pal.setColor(QPalette::Active, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)));
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
colorsInitialized = true;
BOOL gradient = false;
SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
if (gradient) {
pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
} else {
pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight));
pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight));
}
}
#endif // Q_WS_WIN
if (!colorsInitialized) {
pal.setColor(QPalette::Active, QPalette::Highlight,
pal.color(QPalette::Active, QPalette::Highlight));
pal.setColor(QPalette::Active, QPalette::Base,
pal.color(QPalette::Active, QPalette::Highlight));
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));
}
q->setPalette(pal);
q->setActive(act);
}
void QWorkspaceTitleBar::mousePressEvent(QMouseEvent *e)
{
Q_D(QWorkspaceTitleBar);
if (!d->act)
emit doActivate();
if (e->button() == Qt::LeftButton) {
if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
&& !rect().adjusted(5, 5, -5, 0).contains(e->pos())) {
// propagate border events to the QWidgetResizeHandler
e->ignore();
return;
}
d->pressed = true;
QStyleOptionTitleBar opt;
initStyleOption(&opt);
QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
e->pos(), this);
switch (ctrl) {
case QStyle::SC_TitleBarSysMenu:
if (d->flags & Qt::WindowSystemMenuHint) {
d->buttonDown = QStyle::SC_None;
static QElapsedTimer *t = 0;
static QWorkspaceTitleBar *tc = 0;
if (!t)
t = new QElapsedTimer;
if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
emit showOperationMenu();
t->start();
tc = this;
} else {
tc = 0;
emit doClose();
return;
}
}
break;
case QStyle::SC_TitleBarShadeButton:
case QStyle::SC_TitleBarUnshadeButton:
if (d->flags & Qt::WindowShadeButtonHint)
d->buttonDown = ctrl;
break;
case QStyle::SC_TitleBarNormalButton:
d->buttonDown = ctrl;
break;
case QStyle::SC_TitleBarMinButton:
if (d->flags & Qt::WindowMinimizeButtonHint)
d->buttonDown = ctrl;
break;
case QStyle::SC_TitleBarMaxButton:
if (d->flags & Qt::WindowMaximizeButtonHint)
d->buttonDown = ctrl;
break;
case QStyle::SC_TitleBarCloseButton:
if (d->flags & Qt::WindowSystemMenuHint)
d->buttonDown = ctrl;
break;
case QStyle::SC_TitleBarLabel:
d->buttonDown = ctrl;
d->moveOffset = mapToParent(e->pos());
break;
default:
break;
}
update();
} else {
d->pressed = false;
}
}
#ifndef QT_NO_CONTEXTMENU
void QWorkspaceTitleBar::contextMenuEvent(QContextMenuEvent *e)
{
QStyleOptionTitleBar opt;
initStyleOption(&opt);
QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(),
this);
if(ctrl == QStyle::SC_TitleBarLabel || ctrl == QStyle::SC_TitleBarSysMenu) {
e->accept();
emit popupOperationMenu(e->globalPos());
} else {
e->ignore();
}
}
#endif // QT_NO_CONTEXTMENU
void QWorkspaceTitleBar::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QWorkspaceTitleBar);
if (!d->window) {
// could have been deleted as part of a double click event on the sysmenu
return;
}
if (e->button() == Qt::LeftButton && d->pressed) {
if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
&& !rect().adjusted(5, 5, -5, 0).contains(e->pos())) {
// propagate border events to the QWidgetResizeHandler
e->ignore();
d->buttonDown = QStyle::SC_None;
d->pressed = false;
return;
}
e->accept();
QStyleOptionTitleBar opt;
initStyleOption(&opt);
QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
e->pos(), this);
if (d->pressed) {
update();
d->pressed = false;
d->moving = false;
}
if (ctrl == d->buttonDown) {
d->buttonDown = QStyle::SC_None;
switch(ctrl) {
case QStyle::SC_TitleBarShadeButton:
case QStyle::SC_TitleBarUnshadeButton:
if(d->flags & Qt::WindowShadeButtonHint)
emit doShade();
break;
case QStyle::SC_TitleBarNormalButton:
if(d->flags & Qt::WindowMinMaxButtonsHint)
emit doNormal();
break;
case QStyle::SC_TitleBarMinButton:
if(d->flags & Qt::WindowMinimizeButtonHint) {
if (d->window && d->window->isMinimized())
emit doNormal();
else
emit doMinimize();
}
break;
case QStyle::SC_TitleBarMaxButton:
if(d->flags & Qt::WindowMaximizeButtonHint) {
if(d->window && d->window->isMaximized())
emit doNormal();
else
emit doMaximize();
}
break;
case QStyle::SC_TitleBarCloseButton:
if(d->flags & Qt::WindowSystemMenuHint) {
d->buttonDown = QStyle::SC_None;
emit doClose();
return;
}
break;
default:
break;
}
}
} else {
e->ignore();
}
}
void QWorkspaceTitleBar::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QWorkspaceTitleBar);
e->ignore();
if ((e->buttons() & Qt::LeftButton) && style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
&& !rect().adjusted(5, 5, -5, 0).contains(e->pos()) && !d->pressed) {
// propagate border events to the QWidgetResizeHandler
return;
}
QStyleOptionTitleBar opt;
initStyleOption(&opt);
QStyle::SubControl under_mouse = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
e->pos(), this);
if(under_mouse != d->lastControl) {
d->lastControl = under_mouse;
update();
}
switch (d->buttonDown) {
case QStyle::SC_None:
break;
case QStyle::SC_TitleBarSysMenu:
break;
case QStyle::SC_TitleBarLabel:
if (d->buttonDown == QStyle::SC_TitleBarLabel && d->movable && d->pressed) {
if (d->moving || (d->moveOffset - mapToParent(e->pos())).manhattanLength() >= 4) {
d->moving = true;
QPoint p = mapFromGlobal(e->globalPos());
QWidget *parent = d->window ? d->window->parentWidget() : 0;
if(parent && parent->inherits("QWorkspaceChild")) {
QWidget *workspace = parent->parentWidget();
p = workspace->mapFromGlobal(e->globalPos());
if (!workspace->rect().contains(p)) {
if (p.x() < 0)
p.rx() = 0;
if (p.y() < 0)
p.ry() = 0;
if (p.x() > workspace->width())
p.rx() = workspace->width();
if (p.y() > workspace->height())
p.ry() = workspace->height();
}
}
QPoint pp = p - d->moveOffset;
if (!parentWidget()->isMaximized())
parentWidget()->move(pp);
}
}
e->accept();
break;
default:
break;
}
}
bool QWorkspaceTitleBar::isTool() const
{
Q_D(const QWorkspaceTitleBar);
return (d->flags & Qt::WindowType_Mask) == Qt::Tool;
}
// from qwidget.cpp
extern QString qt_setWindowTitle_helperHelper(const QString &, const QWidget*);
void QWorkspaceTitleBar::paintEvent(QPaintEvent *)
{
Q_D(QWorkspaceTitleBar);
QStyleOptionTitleBar opt;
initStyleOption(&opt);
opt.subControls = QStyle::SC_TitleBarLabel;
opt.activeSubControls = d->buttonDown;
if (d->window && (d->flags & Qt::WindowTitleHint)) {
QString title = qt_setWindowTitle_helperHelper(opt.text, d->window);
int maxw = style()->subControlRect(QStyle::CC_TitleBar, &opt, QStyle::SC_TitleBarLabel,
this).width();
opt.text = fontMetrics().elidedText(title, Qt::ElideRight, maxw);
}
if (d->flags & Qt::WindowSystemMenuHint) {
opt.subControls |= QStyle::SC_TitleBarSysMenu | QStyle::SC_TitleBarCloseButton;
if (d->window && (d->flags & Qt::WindowShadeButtonHint)) {
if (d->window->isMinimized())
opt.subControls |= QStyle::SC_TitleBarUnshadeButton;
else
opt.subControls |= QStyle::SC_TitleBarShadeButton;
}
if (d->window && (d->flags & Qt::WindowMinMaxButtonsHint)) {
if(d->window && d->window->isMinimized())
opt.subControls |= QStyle::SC_TitleBarNormalButton;
else
opt.subControls |= QStyle::SC_TitleBarMinButton;
}
if (d->window && (d->flags & Qt::WindowMaximizeButtonHint) && !d->window->isMaximized())
opt.subControls |= QStyle::SC_TitleBarMaxButton;
}
QStyle::SubControl under_mouse = QStyle::SC_None;
under_mouse = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
mapFromGlobal(QCursor::pos()), this);
if ((d->buttonDown == under_mouse) && d->pressed) {
opt.state |= QStyle::State_Sunken;
} else if( autoRaise() && under_mouse != QStyle::SC_None && !d->pressed) {
opt.activeSubControls = under_mouse;
opt.state |= QStyle::State_MouseOver;
}
opt.palette.setCurrentColorGroup(usesActiveColor() ? QPalette::Active : QPalette::Inactive);
QPainter p(this);
style()->drawComplexControl(QStyle::CC_TitleBar, &opt, &p, this);
}
void QWorkspaceTitleBar::mouseDoubleClickEvent(QMouseEvent *e)
{
Q_D(QWorkspaceTitleBar);
if (e->button() != Qt::LeftButton) {
e->ignore();
return;
}
e->accept();
QStyleOptionTitleBar opt;
initStyleOption(&opt);
switch (style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(), this)) {
case QStyle::SC_TitleBarLabel:
emit doubleClicked();
break;
case QStyle::SC_TitleBarSysMenu:
if (d->flags & Qt::WindowSystemMenuHint)
emit doClose();
break;
default:
break;
}
}
void QWorkspaceTitleBar::leaveEvent(QEvent *)
{
Q_D(QWorkspaceTitleBar);
d->lastControl = QStyle::SC_None;
if(autoRaise() && !d->pressed)
update();
}
void QWorkspaceTitleBar::enterEvent(QEvent *)
{
Q_D(QWorkspaceTitleBar);
if(autoRaise() && !d->pressed)
update();
QEvent e(QEvent::Leave);
QApplication::sendEvent(parentWidget(), &e);
}
void QWorkspaceTitleBar::setActive(bool active)
{
Q_D(QWorkspaceTitleBar);
if (d->act == active)
return ;
d->act = active;
update();
}
bool QWorkspaceTitleBar::isActive() const
{
Q_D(const QWorkspaceTitleBar);
return d->act;
}
bool QWorkspaceTitleBar::usesActiveColor() const
{
return (isActive() && isActiveWindow()) ||
(!window() && QWidget::window()->isActiveWindow());
}
QWidget *QWorkspaceTitleBar::window() const
{
Q_D(const QWorkspaceTitleBar);
return d->window;
}
bool QWorkspaceTitleBar::event(QEvent *e)
{
Q_D(QWorkspaceTitleBar);
if (e->type() == QEvent::ApplicationPaletteChange) {
d->readColors();
} else if (e->type() == QEvent::WindowActivate
|| e->type() == QEvent::WindowDeactivate) {
if (d->act)
update();
}
return QWidget::event(e);
}
void QWorkspaceTitleBar::setMovable(bool b)
{
Q_D(QWorkspaceTitleBar);
d->movable = b;
}
bool QWorkspaceTitleBar::isMovable() const
{
Q_D(const QWorkspaceTitleBar);
return d->movable;
}
void QWorkspaceTitleBar::setAutoRaise(bool b)
{
Q_D(QWorkspaceTitleBar);
d->autoraise = b;
}
bool QWorkspaceTitleBar::autoRaise() const
{
Q_D(const QWorkspaceTitleBar);
return d->autoraise;
}
QSize QWorkspaceTitleBar::sizeHint() const
{
ensurePolished();
QStyleOptionTitleBar opt;
initStyleOption(&opt);
QRect menur = style()->subControlRect(QStyle::CC_TitleBar, &opt,
QStyle::SC_TitleBarSysMenu, this);
return QSize(menur.width(), style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, this));
}
/*!
\class QWorkspace
\obsolete
\brief The QWorkspace widget provides a workspace window that can be
used in an MDI application.
This class is deprecated. Use QMdiArea instead.
Multiple Document Interface (MDI) applications are typically
composed of a main window containing a menu bar, a toolbar, and
a central QWorkspace widget. The workspace itself is used to display
a number of child windows, each of which is a widget.
The workspace itself is an ordinary Qt widget. It has a standard
constructor that takes a parent widget.
Workspaces can be placed in any layout, but are typically given
as the central widget in a QMainWindow:
\snippet doc/src/snippets/code/src_gui_widgets_qworkspace.cpp 0
Child windows (MDI windows) are standard Qt widgets that are
inserted into the workspace with addWindow(). As with top-level
widgets, you can call functions such as show(), hide(),
showMaximized(), and setWindowTitle() on a child window to change
its appearance within the workspace. You can also provide widget
flags to determine the layout of the decoration or the behavior of
the widget itself.
To change or retrieve the geometry of a child window, you must
operate on its parentWidget(). The parentWidget() provides
access to the decorated frame that contains the child window
widget. When a child window is maximised, its decorated frame
is hidden. If the top-level widget contains a menu bar, it will display
the maximised window's operations menu to the left of the menu
entries, and the window's controls to the right.
A child window becomes active when it gets the keyboard focus,
or when setFocus() is called. The user can activate a window by moving
focus in the usual ways, for example by clicking a window or by pressing
Tab. The workspace emits a signal windowActivated() when the active
window changes, and the function activeWindow() returns a pointer to the
active child window, or 0 if no window is active.
The convenience function windowList() returns a list of all child
windows. This information could be used in a popup menu
containing a list of windows, for example. This feature is also
available as part of the \l{Window Menu} Solution.
QWorkspace provides two built-in layout strategies for child
windows: cascade() and tile(). Both are slots so you can easily
connect menu entries to them.
\table
\row \o \inlineimage mdi-cascade.png
\o \inlineimage mdi-tile.png
\endtable
If you want your users to be able to work with child windows
larger than the visible workspace area, set the scrollBarsEnabled
property to true.
\sa QDockWidget, {MDI Example}
*/
class QWorkspaceChild : public QWidget
{
Q_OBJECT
friend class QWorkspacePrivate;
friend class QWorkspace;
friend class QWorkspaceTitleBar;
public:
QWorkspaceChild(QWidget* window, QWorkspace* parent=0, Qt::WindowFlags flags = 0);
~QWorkspaceChild();
void setActive(bool);
bool isActive() const;
void adjustToFullscreen();
QWidget* windowWidget() const;
QWidget* iconWidget() const;
void doResize();
void doMove();
QSize sizeHint() const;
QSize minimumSizeHint() const;
QSize baseSize() const;
int frameWidth() const;
void show();
bool isWindowOrIconVisible() const;
signals:
void showOperationMenu();
void popupOperationMenu(const QPoint&);
public slots:
void activate();
void showMinimized();
void showMaximized();
void showNormal();
void showShaded();
void internalRaise();
void titleBarDoubleClicked();
protected:
void enterEvent(QEvent *);
void leaveEvent(QEvent *);
void childEvent(QChildEvent*);
void resizeEvent(QResizeEvent *);
void moveEvent(QMoveEvent *);
bool eventFilter(QObject *, QEvent *);
void paintEvent(QPaintEvent *);
void changeEvent(QEvent *);
private:
void updateMask();
Q_DISABLE_COPY(QWorkspaceChild)
QWidget *childWidget;
QWidgetResizeHandler *widgetResizeHandler;
QWorkspaceTitleBar *titlebar;
QPointer<QWorkspaceTitleBar> iconw;
QSize windowSize;
QSize shadeRestore;
QSize shadeRestoreMin;
bool act :1;
bool shademode :1;
};
int QWorkspaceChild::frameWidth() const
{
return contentsRect().left();
}
class QWorkspacePrivate : public QWidgetPrivate {
Q_DECLARE_PUBLIC(QWorkspace)
public:
QWorkspaceChild* active;
QList<QWorkspaceChild *> windows;
QList<QWorkspaceChild *> focus;
QList<QWidget *> icons;
QWorkspaceChild* maxWindow;
QRect maxRestore;
QPointer<QMDIControl> maxcontrols;
QPointer<QMenuBar> maxmenubar;
QHash<int, const char*> shortcutMap;
int px;
int py;
QWidget *becomeActive;
QPointer<QLabel> maxtools;
QString topTitle;
QMenu *popup, *toolPopup;
enum WSActs { RestoreAct, MoveAct, ResizeAct, MinimizeAct, MaximizeAct, CloseAct, StaysOnTopAct, ShadeAct, NCountAct };
QAction *actions[NCountAct];
QScrollBar *vbar, *hbar;
QWidget *corner;
int yoffset, xoffset;
QBrush background;
void init();
void insertIcon(QWidget* w);
void removeIcon(QWidget* w);
void place(QWidget*);
QWorkspaceChild* findChild(QWidget* w);
void showMaximizeControls();
void hideMaximizeControls();
void activateWindow(QWidget* w, bool change_focus = true);
void hideChild(QWorkspaceChild *c);
void showWindow(QWidget* w);
void maximizeWindow(QWidget* w);
void minimizeWindow(QWidget* w);
void normalizeWindow(QWidget* w);
QRect updateWorkspace();
private:
void _q_normalizeActiveWindow();
void _q_minimizeActiveWindow();
void _q_showOperationMenu();
void _q_popupOperationMenu(const QPoint&);
void _q_operationMenuActivated(QAction *);
void _q_scrollBarChanged();
void _q_updateActions();
bool inTitleChange;
};
static bool isChildOf(QWidget * child, QWidget * parent)
{
if (!parent || !child)
return false;
QWidget * w = child;
while(w && w != parent)
w = w->parentWidget();
return w != 0;
}
/*!
Constructs a workspace with the given \a parent.
*/
QWorkspace::QWorkspace(QWidget *parent)
: QWidget(*new QWorkspacePrivate, parent, 0)
{
Q_D(QWorkspace);
d->init();
}
#ifdef QT3_SUPPORT
/*!
Use one of the constructors that doesn't take the \a name
argument and then use setObjectName() instead.
*/
QWorkspace::QWorkspace(QWidget *parent, const char *name)
: QWidget(*new QWorkspacePrivate, parent, 0)
{
Q_D(QWorkspace);
setObjectName(QString::fromAscii(name));
d->init();
}
#endif // QT3_SUPPORT
/*!
\internal
*/
void
QWorkspacePrivate::init()
{
Q_Q(QWorkspace);
maxcontrols = 0;
active = 0;
maxWindow = 0;
maxtools = 0;
px = 0;
py = 0;
becomeActive = 0;
popup = new QMenu(q);
toolPopup = new QMenu(q);
popup->setObjectName(QLatin1String("qt_internal_mdi_popup"));
toolPopup->setObjectName(QLatin1String("qt_internal_mdi_tool_popup"));
actions[QWorkspacePrivate::RestoreAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarNormalButton, 0, q)),
QWorkspace::tr("&Restore"), q);
actions[QWorkspacePrivate::MoveAct] = new QAction(QWorkspace::tr("&Move"), q);
actions[QWorkspacePrivate::ResizeAct] = new QAction(QWorkspace::tr("&Size"), q);
actions[QWorkspacePrivate::MinimizeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarMinButton, 0, q)),
QWorkspace::tr("Mi&nimize"), q);
actions[QWorkspacePrivate::MaximizeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarMaxButton, 0, q)),
QWorkspace::tr("Ma&ximize"), q);
actions[QWorkspacePrivate::CloseAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, q)),
QWorkspace::tr("&Close")
#ifndef QT_NO_SHORTCUT
+QLatin1Char('\t')+(QString)QKeySequence(Qt::CTRL+Qt::Key_F4)
#endif
,q);
QObject::connect(actions[QWorkspacePrivate::CloseAct], SIGNAL(triggered()), q, SLOT(closeActiveWindow()));
actions[QWorkspacePrivate::StaysOnTopAct] = new QAction(QWorkspace::tr("Stay on &Top"), q);
actions[QWorkspacePrivate::StaysOnTopAct]->setChecked(true);
actions[QWorkspacePrivate::ShadeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarShadeButton, 0, q)),
QWorkspace::tr("Sh&ade"), q);
QObject::connect(popup, SIGNAL(aboutToShow()), q, SLOT(_q_updateActions()));
QObject::connect(popup, SIGNAL(triggered(QAction*)), q, SLOT(_q_operationMenuActivated(QAction*)));
popup->addAction(actions[QWorkspacePrivate::RestoreAct]);
popup->addAction(actions[QWorkspacePrivate::MoveAct]);
popup->addAction(actions[QWorkspacePrivate::ResizeAct]);
popup->addAction(actions[QWorkspacePrivate::MinimizeAct]);
popup->addAction(actions[QWorkspacePrivate::MaximizeAct]);
popup->addSeparator();
popup->addAction(actions[QWorkspacePrivate::CloseAct]);
QObject::connect(toolPopup, SIGNAL(aboutToShow()), q, SLOT(_q_updateActions()));
QObject::connect(toolPopup, SIGNAL(triggered(QAction*)), q, SLOT(_q_operationMenuActivated(QAction*)));
toolPopup->addAction(actions[QWorkspacePrivate::MoveAct]);
toolPopup->addAction(actions[QWorkspacePrivate::ResizeAct]);
toolPopup->addAction(actions[QWorkspacePrivate::StaysOnTopAct]);
toolPopup->addSeparator();
toolPopup->addAction(actions[QWorkspacePrivate::ShadeAct]);
toolPopup->addAction(actions[QWorkspacePrivate::CloseAct]);
#ifndef QT_NO_SHORTCUT
// Set up shortcut bindings (id -> slot), most used first
QList <QKeySequence> shortcuts = QKeySequence::keyBindings(QKeySequence::NextChild);
foreach (const QKeySequence &seq, shortcuts)
shortcutMap.insert(q->grabShortcut(seq), "activateNextWindow");
shortcuts = QKeySequence::keyBindings(QKeySequence::PreviousChild);
foreach (const QKeySequence &seq, shortcuts)
shortcutMap.insert(q->grabShortcut(seq), "activatePreviousWindow");
shortcuts = QKeySequence::keyBindings(QKeySequence::Close);
foreach (const QKeySequence &seq, shortcuts)
shortcutMap.insert(q->grabShortcut(seq), "closeActiveWindow");
shortcutMap.insert(q->grabShortcut(QKeySequence(QLatin1String("ALT+-"))), "_q_showOperationMenu");
#endif // QT_NO_SHORTCUT
q->setBackgroundRole(QPalette::Dark);
q->setAutoFillBackground(true);
q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
hbar = vbar = 0;
corner = 0;
xoffset = yoffset = 0;
q->window()->installEventFilter(q);
inTitleChange = false;
updateWorkspace();
}
/*!
Destroys the workspace and frees any allocated resources.
*/
QWorkspace::~QWorkspace()
{
}
/*! \reimp */
QSize QWorkspace::sizeHint() const
{
QSize s(QApplication::desktop()->size());
return QSize(s.width()*2/3, s.height()*2/3);
}
#ifdef QT3_SUPPORT
/*!
Sets the background color to \a c.
Use setBackground() instead.
*/
void QWorkspace::setPaletteBackgroundColor(const QColor & c)
{
setBackground(c);
}
/*!
Sets the background pixmap to \a pm.
Use setBackground() instead.
*/
void QWorkspace::setPaletteBackgroundPixmap(const QPixmap & pm)
{
setBackground(pm);
}
#endif // QT3_SUPPORT
/*!
\property QWorkspace::background
\brief the workspace's background
*/
QBrush QWorkspace::background() const
{
Q_D(const QWorkspace);
if (d->background.style() == Qt::NoBrush)
return palette().dark();
return d->background;
}
void QWorkspace::setBackground(const QBrush &background)
{
Q_D(QWorkspace);
d->background = background;
setAttribute(Qt::WA_OpaquePaintEvent, background.style() == Qt::NoBrush);
update();
}
/*!
Adds widget \a w as new sub window to the workspace. If \a flags
are non-zero, they will override the flags set on the widget.
Returns the widget used for the window frame.
To remove the widget \a w from the workspace, simply call
setParent() with the new parent (or 0 to make it a stand-alone
window).
*/
QWidget * QWorkspace::addWindow(QWidget *w, Qt::WindowFlags flags)
{
Q_D(QWorkspace);
if (!w)
return 0;
w->setAutoFillBackground(true);
QWidgetPrivate::adjustFlags(flags);
#if 0
bool wasMaximized = w->isMaximized();
bool wasMinimized = w->isMinimized();
#endif
bool hasSize = w->testAttribute(Qt::WA_Resized);
int x = w->x();
int y = w->y();
bool hasPos = w->testAttribute(Qt::WA_Moved);
QSize s = w->size().expandedTo(qSmartMinSize(w));
if (!hasSize && w->sizeHint().isValid())
w->adjustSize();
QWorkspaceChild* child = new QWorkspaceChild(w, this, flags);
child->setObjectName(QLatin1String("qt_workspacechild"));
child->installEventFilter(this);
connect(child, SIGNAL(popupOperationMenu(QPoint)),
this, SLOT(_q_popupOperationMenu(QPoint)));
connect(child, SIGNAL(showOperationMenu()),
this, SLOT(_q_showOperationMenu()));
d->windows.append(child);
if (child->isVisibleTo(this))
d->focus.append(child);
child->internalRaise();
if (!hasPos)
d->place(child);
if (!hasSize)
child->adjustSize();
if (hasPos)
child->move(x, y);
return child;
#if 0
if (wasMaximized)
w->showMaximized();
else if (wasMinimized)
w->showMinimized();
else if (!hasBeenHidden)
d->activateWindow(w);
d->updateWorkspace();
return child;
#endif
}
/*! \reimp */
void QWorkspace::childEvent(QChildEvent * e)
{
Q_D(QWorkspace);
if (e->removed()) {
if (d->windows.removeAll(static_cast<QWorkspaceChild*>(e->child()))) {
d->focus.removeAll(static_cast<QWorkspaceChild*>(e->child()));
if (d->maxWindow == e->child())
d->maxWindow = 0;
d->updateWorkspace();
}
}
}
/*! \reimp */
#ifndef QT_NO_WHEELEVENT
void QWorkspace::wheelEvent(QWheelEvent *e)
{
Q_D(QWorkspace);
if (!scrollBarsEnabled())
return;
// the scroll bars are children of the workspace, so if we receive
// a wheel event we redirect to the scroll bars using a direct event
// call, /not/ using sendEvent() because if the scroll bar ignores the
// event QApplication::sendEvent() will propagate the event to the parent widget,
// which is us, who /just/ sent it.
if (d->vbar && d->vbar->isVisible() && !(e->modifiers() & Qt::AltModifier))
d->vbar->event(e);
else if (d->hbar && d->hbar->isVisible())
d->hbar->event(e);
}
#endif
void QWorkspacePrivate::activateWindow(QWidget* w, bool change_focus)
{
Q_Q(QWorkspace);
if (!w) {
active = 0;
emit q->windowActivated(0);
return;
}
if (!q->isVisible()) {
becomeActive = w;
return;
}
if (active && active->windowWidget() == w) {
if (!isChildOf(q->focusWidget(), w)) // child window does not have focus
active->setActive(true);
return;
}
active = 0;
// First deactivate all other workspace clients
QList<QWorkspaceChild *>::Iterator it(windows.begin());
while (it != windows.end()) {
QWorkspaceChild* c = *it;
++it;
if (c->windowWidget() == w)
active = c;
else
c->setActive(false);
}
if (!active)
return;
// Then activate the new one, so the focus is stored correctly
active->setActive(true);
if (!active)
return;
if (maxWindow && maxWindow != active && active->windowWidget() &&
(active->windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint))
active->showMaximized();
active->internalRaise();
if (change_focus) {
int from = focus.indexOf(active);
if (from >= 0)
focus.move(from, focus.size() - 1);
}
updateWorkspace();
emit q->windowActivated(w);
}
/*!
Returns a pointer to the widget corresponding to the active child
window, or 0 if no window is active.
\sa setActiveWindow()
*/
QWidget* QWorkspace::activeWindow() const
{
Q_D(const QWorkspace);
return d->active? d->active->windowWidget() : 0;
}
/*!
Makes the child window that contains \a w the active child window.
\sa activeWindow()
*/
void QWorkspace::setActiveWindow(QWidget *w)
{
Q_D(QWorkspace);
d->activateWindow(w, true);
if (w && w->isMinimized())
w->setWindowState(w->windowState() & ~Qt::WindowMinimized);
}
void QWorkspacePrivate::place(QWidget *w)
{
Q_Q(QWorkspace);
QList<QWidget *> widgets;
for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it)
if (*it != w)
widgets.append(*it);
int overlap, minOverlap = 0;
int possible;
QRect r1(0, 0, 0, 0);
QRect r2(0, 0, 0, 0);
QRect maxRect = q->rect();
int x = maxRect.left(), y = maxRect.top();
QPoint wpos(maxRect.left(), maxRect.top());
bool firstPass = true;
do {
if (y + w->height() > maxRect.bottom()) {
overlap = -1;
} else if(x + w->width() > maxRect.right()) {
overlap = -2;
} else {
overlap = 0;
r1.setRect(x, y, w->width(), w->height());
QWidget *l;
QList<QWidget *>::Iterator it(widgets.begin());
while (it != widgets.end()) {
l = *it;
++it;
if (maxWindow == l)
r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
else
r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
QRect(l->x(), l->y(), l->width(), l->height()));
if (r2.intersects(r1)) {
r2.setCoords(qMax(r1.left(), r2.left()),
qMax(r1.top(), r2.top()),
qMin(r1.right(), r2.right()),
qMin(r1.bottom(), r2.bottom())
);
overlap += (r2.right() - r2.left()) *
(r2.bottom() - r2.top());
}
}
}
if (overlap == 0) {
wpos = QPoint(x, y);
break;
}
if (firstPass) {
firstPass = false;
minOverlap = overlap;
} else if (overlap >= 0 && overlap < minOverlap) {
minOverlap = overlap;
wpos = QPoint(x, y);
}
if (overlap > 0) {
possible = maxRect.right();
if (possible - w->width() > x) possible -= w->width();
QWidget *l;
QList<QWidget *>::Iterator it(widgets.begin());
while (it != widgets.end()) {
l = *it;
++it;
if (maxWindow == l)
r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
else
r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
QRect(l->x(), l->y(), l->width(), l->height()));
if((y < r2.bottom()) && (r2.top() < w->height() + y)) {
if(r2.right() > x)
possible = possible < r2.right() ?
possible : r2.right();
if(r2.left() - w->width() > x)
possible = possible < r2.left() - w->width() ?
possible : r2.left() - w->width();
}
}
x = possible;
} else if (overlap == -2) {
x = maxRect.left();
possible = maxRect.bottom();
if (possible - w->height() > y) possible -= w->height();
QWidget *l;
QList<QWidget *>::Iterator it(widgets.begin());
while (it != widgets.end()) {
l = *it;
++it;
if (maxWindow == l)
r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
else
r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
QRect(l->x(), l->y(), l->width(), l->height()));
if(r2.bottom() > y)
possible = possible < r2.bottom() ?
possible : r2.bottom();
if(r2.top() - w->height() > y)
possible = possible < r2.top() - w->height() ?
possible : r2.top() - w->height();
}
y = possible;
}
}
while(overlap != 0 && overlap != -1);
QRect resultRect = w->geometry();
resultRect.moveTo(wpos);
w->setGeometry(QStyle::visualRect(q->layoutDirection(), maxRect, resultRect));
updateWorkspace();
}
void QWorkspacePrivate::insertIcon(QWidget* w)
{
Q_Q(QWorkspace);
if (!w || icons.contains(w))
return;
icons.append(w);
if (w->parentWidget() != q) {
w->setParent(q, 0);
w->move(0,0);
}
QRect cr = updateWorkspace();
int x = 0;
int y = cr.height() - w->height();
QList<QWidget *>::Iterator it(icons.begin());
while (it != icons.end()) {
QWidget* i = *it;
++it;
if (x > 0 && x + i->width() > cr.width()){
x = 0;
y -= i->height();
}
if (i != w &&
i->geometry().intersects(QRect(x, y, w->width(), w->height())))
x += i->width();
}
w->move(x, y);
if (q->isVisibleTo(q->parentWidget())) {
w->show();
w->lower();
}
updateWorkspace();
}
void QWorkspacePrivate::removeIcon(QWidget* w)
{
if (icons.removeAll(w))
w->hide();
}
/*! \reimp */
void QWorkspace::resizeEvent(QResizeEvent *)
{
Q_D(QWorkspace);
if (d->maxWindow) {
d->maxWindow->adjustToFullscreen();
if (d->maxWindow->windowWidget())
d->maxWindow->windowWidget()->overrideWindowState(Qt::WindowMaximized);
}
d->updateWorkspace();
}
/*! \reimp */
void QWorkspace::showEvent(QShowEvent *e)
{
Q_D(QWorkspace);
if (d->maxWindow)
d->showMaximizeControls();
QWidget::showEvent(e);
if (d->becomeActive) {
d->activateWindow(d->becomeActive);
d->becomeActive = 0;
} else if (d->windows.count() > 0 && !d->active) {
d->activateWindow(d->windows.first()->windowWidget());
}
// // force a frame repaint - this is a workaround for what seems to be a bug
// // introduced when changing the QWidget::show() implementation. Might be
// // a windows bug as well though.
// for (int i = 0; i < d->windows.count(); ++i) {
// QWorkspaceChild* c = d->windows.at(i);
// c->update(c->rect());
// }
d->updateWorkspace();
}
/*! \reimp */
void QWorkspace::hideEvent(QHideEvent *)
{
Q_D(QWorkspace);
if (!isVisible())
d->hideMaximizeControls();
}
/*! \reimp */
void QWorkspace::paintEvent(QPaintEvent *)
{
Q_D(QWorkspace);
if (d->background.style() != Qt::NoBrush) {
QPainter p(this);
p.fillRect(0, 0, width(), height(), d->background);
}
}
void QWorkspacePrivate::minimizeWindow(QWidget* w)
{
QWorkspaceChild* c = findChild(w);
if (!w || !(w->windowFlags() & Qt::WindowMinimizeButtonHint))
return;
if (c) {
bool wasMax = false;
if (c == maxWindow) {
wasMax = true;
maxWindow = 0;
hideMaximizeControls();
for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it) {
QWorkspaceChild* c = *it;
if (c->titlebar)
c->titlebar->setMovable(true);
c->widgetResizeHandler->setActive(true);
}
}
c->hide();
if (wasMax)
c->setGeometry(maxRestore);
if (!focus.contains(c))
focus.append(c);
insertIcon(c->iconWidget());
if (!maxWindow)
activateWindow(w);
updateWorkspace();
w->overrideWindowState(Qt::WindowMinimized);
c->overrideWindowState(Qt::WindowMinimized);
}
}
void QWorkspacePrivate::normalizeWindow(QWidget* w)
{
Q_Q(QWorkspace);
QWorkspaceChild* c = findChild(w);
if (!w)
return;
if (c) {
w->overrideWindowState(Qt::WindowNoState);
hideMaximizeControls();
if (!maxmenubar || q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q) || !maxWindow) {
if (w->minimumSize() != w->maximumSize())
c->widgetResizeHandler->setActive(true);
if (c->titlebar)
c->titlebar->setMovable(true);
}
w->overrideWindowState(Qt::WindowNoState);
c->overrideWindowState(Qt::WindowNoState);
if (c == maxWindow) {
c->setGeometry(maxRestore);
maxWindow = 0;
} else {
if (c->iconw)
removeIcon(c->iconw->parentWidget());
c->show();
}
hideMaximizeControls();
for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it) {
QWorkspaceChild* c = *it;
if (c->titlebar)
c->titlebar->setMovable(true);
if (c->childWidget && c->childWidget->minimumSize() != c->childWidget->maximumSize())
c->widgetResizeHandler->setActive(true);
}
activateWindow(w, true);
updateWorkspace();
}
}
void QWorkspacePrivate::maximizeWindow(QWidget* w)
{
Q_Q(QWorkspace);
QWorkspaceChild* c = findChild(w);
if (!w || !(w->windowFlags() & Qt::WindowMaximizeButtonHint))
return;
if (!c || c == maxWindow)
return;
bool updatesEnabled = q->updatesEnabled();
q->setUpdatesEnabled(false);
if (c->iconw && icons.contains(c->iconw->parentWidget()))
normalizeWindow(w);
QRect r(c->geometry());
QWorkspaceChild *oldMaxWindow = maxWindow;
maxWindow = c;
showMaximizeControls();
c->adjustToFullscreen();
c->show();
c->internalRaise();
if (oldMaxWindow != c) {
if (oldMaxWindow) {
oldMaxWindow->setGeometry(maxRestore);
oldMaxWindow->overrideWindowState(Qt::WindowNoState);
if(oldMaxWindow->windowWidget())
oldMaxWindow->windowWidget()->overrideWindowState(Qt::WindowNoState);
}
maxRestore = r;
}
activateWindow(w);
if(!maxmenubar || q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
if (!active && becomeActive) {
active = (QWorkspaceChild*)becomeActive->parentWidget();
active->setActive(true);
becomeActive = 0;
emit q->windowActivated(active->windowWidget());
}
c->widgetResizeHandler->setActive(false);
if (c->titlebar)
c->titlebar->setMovable(false);
}
updateWorkspace();
w->overrideWindowState(Qt::WindowMaximized);
c->overrideWindowState(Qt::WindowMaximized);
q->setUpdatesEnabled(updatesEnabled);
}
void QWorkspacePrivate::showWindow(QWidget* w)
{
if (w->isMinimized() && (w->windowFlags() & Qt::WindowMinimizeButtonHint))
minimizeWindow(w);
else if ((maxWindow || w->isMaximized()) && w->windowFlags() & Qt::WindowMaximizeButtonHint)
maximizeWindow(w);
else if (w->windowFlags() & Qt::WindowMaximizeButtonHint)
normalizeWindow(w);
else
w->parentWidget()->show();
if (maxWindow)
maxWindow->internalRaise();
updateWorkspace();
}
QWorkspaceChild* QWorkspacePrivate::findChild(QWidget* w)
{
QList<QWorkspaceChild *>::Iterator it(windows.begin());
while (it != windows.end()) {
QWorkspaceChild* c = *it;
++it;
if (c->windowWidget() == w)
return c;
}
return 0;
}
/*!
Returns a list of all visible or minimized child windows. If \a
order is CreationOrder (the default), the windows are listed in
the order in which they were inserted into the workspace. If \a
order is StackingOrder, the windows are listed in their stacking
order, with the topmost window as the last item in the list.
*/
QWidgetList QWorkspace::windowList(WindowOrder order) const
{
Q_D(const QWorkspace);
QWidgetList windows;
if (order == StackingOrder) {
QObjectList cl = children();
for (int i = 0; i < cl.size(); ++i) {
QWorkspaceChild *c = qobject_cast<QWorkspaceChild*>(cl.at(i));
if (c && c->isWindowOrIconVisible())
windows.append(c->windowWidget());
}
} else {
QList<QWorkspaceChild *>::ConstIterator it(d->windows.begin());
while (it != d->windows.end()) {
QWorkspaceChild* c = *it;
++it;
if (c && c->isWindowOrIconVisible())
windows.append(c->windowWidget());
}
}
return windows;
}
/*! \reimp */
bool QWorkspace::event(QEvent *e)
{
#ifndef QT_NO_SHORTCUT
Q_D(QWorkspace);
if (e->type() == QEvent::Shortcut) {
QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
const char *theSlot = d->shortcutMap.value(se->shortcutId(), 0);
if (theSlot)
QMetaObject::invokeMethod(this, theSlot);
} else
#endif
if (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut){
return true;
}
return QWidget::event(e);
}
/*! \reimp */
bool QWorkspace::eventFilter(QObject *o, QEvent * e)
{
Q_D(QWorkspace);
static QElapsedTimer* t = 0;
static QWorkspace* tc = 0;
if (o == d->maxtools) {
switch (e->type()) {
case QEvent::MouseButtonPress:
{
QMenuBar* b = (QMenuBar*)o->parent();
if (!t)
t = new QElapsedTimer;
if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
if (isRightToLeft()) {
QPoint p = b->mapToGlobal(QPoint(b->x() + b->width(), b->y() + b->height()));
p.rx() -= d->popup->sizeHint().width();
d->_q_popupOperationMenu(p);
} else {
d->_q_popupOperationMenu(b->mapToGlobal(QPoint(b->x(), b->y() + b->height())));
}
t->start();
tc = this;
} else {
tc = 0;
closeActiveWindow();
}
return true;
}
default:
break;
}
return QWidget::eventFilter(o, e);
}
switch (e->type()) {
case QEvent::HideToParent:
break;
case QEvent::ShowToParent:
if (QWorkspaceChild *c = qobject_cast<QWorkspaceChild*>(o))
if (!d->focus.contains(c))
d->focus.append(c);
d->updateWorkspace();
break;
case QEvent::WindowTitleChange:
if (!d->inTitleChange) {
if (o == window())
d->topTitle = window()->windowTitle();
if (d->maxWindow && d->maxWindow->windowWidget() && d->topTitle.size()) {
d->inTitleChange = true;
window()->setWindowTitle(tr("%1 - [%2]")
.arg(d->topTitle).arg(d->maxWindow->windowWidget()->windowTitle()));
d->inTitleChange = false;
}
}
break;
case QEvent::ModifiedChange:
if (o == d->maxWindow)
window()->setWindowModified(d->maxWindow->isWindowModified());
break;
case QEvent::Close:
if (o == window())
{
QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
while (it != d->windows.end()) {
QWorkspaceChild* c = *it;
++it;
if (c->shademode)
c->showShaded();
}
} else if (qobject_cast<QWorkspaceChild*>(o)) {
d->popup->hide();
}
d->updateWorkspace();
break;
default:
break;
}
return QWidget::eventFilter(o, e);
}
static QMenuBar *findMenuBar(QWidget *w)
{
// don't search recursively to avoid finding a menu bar of a
// mainwindow that happens to be a workspace window (like
// a mainwindow in designer)
QList<QObject *> children = w->children();
for (int i = 0; i < children.count(); ++i) {
QMenuBar *bar = qobject_cast<QMenuBar *>(children.at(i));
if (bar)
return bar;
}
return 0;
}
void QWorkspacePrivate::showMaximizeControls()
{
Q_Q(QWorkspace);
Q_ASSERT(maxWindow);
// merge windowtitle and modified state
if (!topTitle.size())
topTitle = q->window()->windowTitle();
if (maxWindow->windowWidget()) {
QString docTitle = maxWindow->windowWidget()->windowTitle();
if (topTitle.size() && docTitle.size()) {
inTitleChange = true;
q->window()->setWindowTitle(QWorkspace::tr("%1 - [%2]").arg(topTitle).arg(docTitle));
inTitleChange = false;
}
q->window()->setWindowModified(maxWindow->windowWidget()->isWindowModified());
}
if (!q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
QMenuBar* b = 0;
// Do a breadth-first search first on every parent,
QWidget* w = q->parentWidget();
while (w) {
b = findMenuBar(w);
if (b)
break;
w = w->parentWidget();
}
// last attempt.
if (!b)
b = findMenuBar(q->window());
if (!b)
return;
if (!maxcontrols) {
maxmenubar = b;
maxcontrols = new QMDIControl(b);
QObject::connect(maxcontrols, SIGNAL(_q_minimize()),
q, SLOT(_q_minimizeActiveWindow()));
QObject::connect(maxcontrols, SIGNAL(_q_restore()),
q, SLOT(_q_normalizeActiveWindow()));
QObject::connect(maxcontrols, SIGNAL(_q_close()),
q, SLOT(closeActiveWindow()));
}
b->setCornerWidget(maxcontrols);
if (b->isVisible())
maxcontrols->show();
if (!active && becomeActive) {
active = (QWorkspaceChild*)becomeActive->parentWidget();
active->setActive(true);
becomeActive = 0;
emit q->windowActivated(active->windowWidget());
}
if (active) {
if (!maxtools) {
maxtools = new QLabel(q->window());
maxtools->setObjectName(QLatin1String("qt_maxtools"));
maxtools->installEventFilter(q);
}
if (active->windowWidget() && !active->windowWidget()->windowIcon().isNull()) {
QIcon icon = active->windowWidget()->windowIcon();
int iconSize = maxcontrols->size().height();
maxtools->setPixmap(icon.pixmap(QSize(iconSize, iconSize)));
} else {
QPixmap pm = q->style()->standardPixmap(QStyle::SP_TitleBarMenuButton, 0, q);
if (pm.isNull()) {
pm = QPixmap(14,14);
pm.fill(Qt::black);
}
maxtools->setPixmap(pm);
}
b->setCornerWidget(maxtools, Qt::TopLeftCorner);
if (b->isVisible())
maxtools->show();
}
}
}
void QWorkspacePrivate::hideMaximizeControls()
{
Q_Q(QWorkspace);
if (maxmenubar && !q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
if (maxmenubar) {
maxmenubar->setCornerWidget(0, Qt::TopLeftCorner);
maxmenubar->setCornerWidget(0, Qt::TopRightCorner);
}
if (maxcontrols) {
maxcontrols->deleteLater();
maxcontrols = 0;
}
if (maxtools) {
maxtools->deleteLater();
maxtools = 0;
}
}
//unmerge the title bar/modification state
if (topTitle.size()) {
inTitleChange = true;
q->window()->setWindowTitle(topTitle);
inTitleChange = false;
}
q->window()->setWindowModified(false);
}
/*!
Closes the child window that is currently active.
\sa closeAllWindows()
*/
void QWorkspace::closeActiveWindow()
{
Q_D(QWorkspace);
if (d->maxWindow && d->maxWindow->windowWidget())
d->maxWindow->windowWidget()->close();
else if (d->active && d->active->windowWidget())
d->active->windowWidget()->close();
d->updateWorkspace();
}
/*!
Closes all child windows.
If any child window fails to accept the close event, the remaining windows
will remain open.
\sa closeActiveWindow()
*/
void QWorkspace::closeAllWindows()
{
Q_D(QWorkspace);
bool did_close = true;
QList<QWorkspaceChild *>::const_iterator it = d->windows.constBegin();
while (it != d->windows.constEnd() && did_close) {
QWorkspaceChild *c = *it;
++it;
if (c->windowWidget() && !c->windowWidget()->isHidden())
did_close = c->windowWidget()->close();
}
}
void QWorkspacePrivate::_q_normalizeActiveWindow()
{
if (maxWindow)
maxWindow->showNormal();
else if (active)
active->showNormal();
}
void QWorkspacePrivate::_q_minimizeActiveWindow()
{
if (maxWindow)
maxWindow->showMinimized();
else if (active)
active->showMinimized();
}
void QWorkspacePrivate::_q_showOperationMenu()
{
Q_Q(QWorkspace);
if (!active || !active->windowWidget())
return;
Q_ASSERT((active->windowWidget()->windowFlags() & Qt::WindowSystemMenuHint));
QPoint p;
QMenu *popup = (active->titlebar && active->titlebar->isTool()) ? toolPopup : this->popup;
if (q->isRightToLeft()) {
p = QPoint(active->windowWidget()->mapToGlobal(QPoint(active->windowWidget()->width(),0)));
p.rx() -= popup->sizeHint().width();
} else {
p = QPoint(active->windowWidget()->mapToGlobal(QPoint(0,0)));
}
if (!active->isVisible()) {
p = active->iconWidget()->mapToGlobal(QPoint(0,0));
p.ry() -= popup->sizeHint().height();
}
_q_popupOperationMenu(p);
}
void QWorkspacePrivate::_q_popupOperationMenu(const QPoint& p)
{
if (!active || !active->windowWidget() || !(active->windowWidget()->windowFlags() & Qt::WindowSystemMenuHint))
return;
if (active->titlebar && active->titlebar->isTool())
toolPopup->popup(p);
else
popup->popup(p);
}
void QWorkspacePrivate::_q_updateActions()
{
Q_Q(QWorkspace);
for (int i = 1; i < NCountAct-1; i++) {
bool enable = active != 0;
actions[i]->setEnabled(enable);
}
if (!active || !active->windowWidget())
return;
QWidget *windowWidget = active->windowWidget();
bool canResize = windowWidget->maximumSize() != windowWidget->minimumSize();
actions[QWorkspacePrivate::ResizeAct]->setEnabled(canResize);
actions[QWorkspacePrivate::MinimizeAct]->setEnabled((windowWidget->windowFlags() & Qt::WindowMinimizeButtonHint));
actions[QWorkspacePrivate::MaximizeAct]->setEnabled((windowWidget->windowFlags() & Qt::WindowMaximizeButtonHint) && canResize);
if (active == maxWindow) {
actions[QWorkspacePrivate::MoveAct]->setEnabled(false);
actions[QWorkspacePrivate::ResizeAct]->setEnabled(false);
actions[QWorkspacePrivate::MaximizeAct]->setEnabled(false);
actions[QWorkspacePrivate::RestoreAct]->setEnabled(true);
} else if (active->isVisible()){
actions[QWorkspacePrivate::RestoreAct]->setEnabled(false);
} else {
actions[QWorkspacePrivate::MoveAct]->setEnabled(false);
actions[QWorkspacePrivate::ResizeAct]->setEnabled(false);
actions[QWorkspacePrivate::MinimizeAct]->setEnabled(false);
actions[QWorkspacePrivate::RestoreAct]->setEnabled(true);
}
if (active->shademode) {
actions[QWorkspacePrivate::ShadeAct]->setIcon(
QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarUnshadeButton, 0, q)));
actions[QWorkspacePrivate::ShadeAct]->setText(QWorkspace::tr("&Unshade"));
} else {
actions[QWorkspacePrivate::ShadeAct]->setIcon(
QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarShadeButton, 0, q)));
actions[QWorkspacePrivate::ShadeAct]->setText(QWorkspace::tr("Sh&ade"));
}
actions[QWorkspacePrivate::StaysOnTopAct]->setEnabled(!active->shademode && canResize);
actions[QWorkspacePrivate::StaysOnTopAct]->setChecked(
(active->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint));
}
void QWorkspacePrivate::_q_operationMenuActivated(QAction *action)
{
if (!active)
return;
if(action == actions[QWorkspacePrivate::RestoreAct]) {
active->showNormal();
} else if(action == actions[QWorkspacePrivate::MoveAct]) {
active->doMove();
} else if(action == actions[QWorkspacePrivate::ResizeAct]) {
if (active->shademode)
active->showShaded();
active->doResize();
} else if(action == actions[QWorkspacePrivate::MinimizeAct]) {
active->showMinimized();
} else if(action == actions[QWorkspacePrivate::MaximizeAct]) {
active->showMaximized();
} else if(action == actions[QWorkspacePrivate::ShadeAct]) {
active->showShaded();
} else if(action == actions[QWorkspacePrivate::StaysOnTopAct]) {
if(QWidget* w = active->windowWidget()) {
if ((w->windowFlags() & Qt::WindowStaysOnTopHint)) {
w->overrideWindowFlags(w->windowFlags() & ~Qt::WindowStaysOnTopHint);
} else {
w->overrideWindowFlags(w->windowFlags() | Qt::WindowStaysOnTopHint);
w->parentWidget()->raise();
}
}
}
}
void QWorkspacePrivate::hideChild(QWorkspaceChild *c)
{
Q_Q(QWorkspace);
// bool updatesEnabled = q->updatesEnabled();
// q->setUpdatesEnabled(false);
focus.removeAll(c);
QRect restore;
if (maxWindow == c)
restore = maxRestore;
if (active == c) {
q->setFocus();
q->activatePreviousWindow();
}
if (active == c)
activateWindow(0);
if (maxWindow == c) {
hideMaximizeControls();
maxWindow = 0;
}
c->hide();
if (!restore.isEmpty())
c->setGeometry(restore);
// q->setUpdatesEnabled(updatesEnabled);
}
/*!
Gives the input focus to the next window in the list of child
windows.
\sa activatePreviousWindow()
*/
void QWorkspace::activateNextWindow()
{
Q_D(QWorkspace);
if (d->focus.isEmpty())
return;
if (!d->active) {
if (d->focus.first())
d->activateWindow(d->focus.first()->windowWidget(), false);
return;
}
int a = d->focus.indexOf(d->active) + 1;
a = a % d->focus.count();
if (d->focus.at(a))
d->activateWindow(d->focus.at(a)->windowWidget(), false);
else
d->activateWindow(0);
}
/*!
Gives the input focus to the previous window in the list of child
windows.
\sa activateNextWindow()
*/
void QWorkspace::activatePreviousWindow()
{
Q_D(QWorkspace);
if (d->focus.isEmpty())
return;
if (!d->active) {
if (d->focus.last())
d->activateWindow(d->focus.first()->windowWidget(), false);
else
d->activateWindow(0);
return;
}
int a = d->focus.indexOf(d->active) - 1;
if (a < 0)
a = d->focus.count()-1;
if (d->focus.at(a))
d->activateWindow(d->focus.at(a)->windowWidget(), false);
else
d->activateWindow(0);
}
/*!
\fn void QWorkspace::windowActivated(QWidget* w)
This signal is emitted when the child window \a w becomes active.
Note that \a w can be 0, and that more than one signal may be
emitted for a single activation event.
\sa activeWindow(), windowList()
*/
/*!
Arranges all the child windows in a cascade pattern.
\sa tile(), arrangeIcons()
*/
void QWorkspace::cascade()
{
Q_D(QWorkspace);
blockSignals(true);
if (d->maxWindow)
d->maxWindow->showNormal();
if (d->vbar) {
d->vbar->blockSignals(true);
d->vbar->setValue(0);
d->vbar->blockSignals(false);
d->hbar->blockSignals(true);
d->hbar->setValue(0);
d->hbar->blockSignals(false);
d->_q_scrollBarChanged();
}
const int xoffset = 13;
const int yoffset = 20;
// make a list of all relevant mdi clients
QList<QWorkspaceChild *> widgets;
QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
QWorkspaceChild* wc = 0;
for (it = d->focus.begin(); it != d->focus.end(); ++it) {
wc = *it;
if (wc->windowWidget()->isVisibleTo(this) && !(wc->titlebar && wc->titlebar->isTool()))
widgets.append(wc);
}
int x = 0;
int y = 0;
it = widgets.begin();
while (it != widgets.end()) {
QWorkspaceChild *child = *it;
++it;
QSize prefSize = child->windowWidget()->sizeHint().expandedTo(qSmartMinSize(child->windowWidget()));
if (!prefSize.isValid())
prefSize = child->windowWidget()->size();
prefSize = prefSize.expandedTo(qSmartMinSize(child->windowWidget()));
if (prefSize.isValid())
prefSize += QSize(child->baseSize().width(), child->baseSize().height());
int w = prefSize.width();
int h = prefSize.height();
child->showNormal();
if (y + h > height())
y = 0;
if (x + w > width())
x = 0;
child->setGeometry(x, y, w, h);
x += xoffset;
y += yoffset;
child->internalRaise();
}
d->updateWorkspace();
blockSignals(false);
}
/*!
Arranges all child windows in a tile pattern.
\sa cascade(), arrangeIcons()
*/
void QWorkspace::tile()
{
Q_D(QWorkspace);
blockSignals(true);
QWidget *oldActive = d->active ? d->active->windowWidget() : 0;
if (d->maxWindow)
d->maxWindow->showNormal();
if (d->vbar) {
d->vbar->blockSignals(true);
d->vbar->setValue(0);
d->vbar->blockSignals(false);
d->hbar->blockSignals(true);
d->hbar->setValue(0);
d->hbar->blockSignals(false);
d->_q_scrollBarChanged();
}
int rows = 1;
int cols = 1;
int n = 0;
QWorkspaceChild* c;
QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
while (it != d->windows.end()) {
c = *it;
++it;
if (!c->windowWidget()->isHidden()
&& !(c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)
&& !c->iconw)
n++;
}
while (rows * cols < n) {
if (cols <= rows)
cols++;
else
rows++;
}
int add = cols * rows - n;
bool* used = new bool[cols*rows];
for (int i = 0; i < rows*cols; i++)
used[i] = false;
int row = 0;
int col = 0;
int w = width() / cols;
int h = height() / rows;
it = d->windows.begin();
while (it != d->windows.end()) {
c = *it;
++it;
if (c->iconw || c->windowWidget()->isHidden() || (c->titlebar && c->titlebar->isTool()))
continue;
if (!row && !col) {
w -= c->baseSize().width();
h -= c->baseSize().height();
}
if ((c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
QPoint p = c->pos();
if (p.x()+c->width() < 0)
p.setX(0);
if (p.x() > width())
p.setX(width() - c->width());
if (p.y() + 10 < 0)
p.setY(0);
if (p.y() > height())
p.setY(height() - c->height());
if (p != c->pos())
c->QWidget::move(p);
} else {
c->showNormal();
used[row*cols+col] = true;
QSize sz(w, h);
QSize bsize(c->baseSize());
sz = sz.expandedTo(c->windowWidget()->minimumSize()).boundedTo(c->windowWidget()->maximumSize());
sz += bsize;
if ( add ) {
if (sz.height() == h + bsize.height()) // no relevant constrains
sz.rheight() *= 2;
used[(row+1)*cols+col] = true;
add--;
}
c->setGeometry(col*w + col*bsize.width(), row*h + row*bsize.height(), sz.width(), sz.height());
while(row < rows && col < cols && used[row*cols+col]) {
col++;
if (col == cols) {
col = 0;
row++;
}
}
}
}
delete [] used;
d->activateWindow(oldActive);
d->updateWorkspace();
blockSignals(false);
}
/*!
Arranges all iconified windows at the bottom of the workspace.
\sa cascade(), tile()
*/
void QWorkspace::arrangeIcons()
{
Q_D(QWorkspace);
QRect cr = d->updateWorkspace();
int x = 0;
int y = -1;
QList<QWidget *>::Iterator it(d->icons.begin());
while (it != d->icons.end()) {
QWidget* i = *it;
if (y == -1)
y = cr.height() - i->height();
if (x > 0 && x + i->width() > cr.width()) {
x = 0;
y -= i->height();
}
i->move(x, y);
x += i->width();
++it;
}
d->updateWorkspace();
}
QWorkspaceChild::QWorkspaceChild(QWidget* window, QWorkspace *parent, Qt::WindowFlags flags)
: QWidget(parent,
Qt::FramelessWindowHint | Qt::SubWindow)
{
setAttribute(Qt::WA_DeleteOnClose);
setAttribute(Qt::WA_NoMousePropagation);
setMouseTracking(true);
act = false;
iconw = 0;
shademode = false;
titlebar = 0;
setAutoFillBackground(true);
setBackgroundRole(QPalette::Window);
if (window) {
flags |= (window->windowFlags() & Qt::MSWindowsOwnDC);
if (flags)
window->setParent(this, flags & ~Qt::WindowType_Mask);
else
window->setParent(this);
}
if (window && (flags & (Qt::WindowTitleHint
| Qt::WindowSystemMenuHint
| Qt::WindowMinimizeButtonHint
| Qt::WindowMaximizeButtonHint
| Qt::WindowContextHelpButtonHint))) {
titlebar = new QWorkspaceTitleBar(window, this, flags);
connect(titlebar, SIGNAL(doActivate()),
this, SLOT(activate()));
connect(titlebar, SIGNAL(doClose()),
window, SLOT(close()));
connect(titlebar, SIGNAL(doMinimize()),
this, SLOT(showMinimized()));
connect(titlebar, SIGNAL(doNormal()),
this, SLOT(showNormal()));
connect(titlebar, SIGNAL(doMaximize()),
this, SLOT(showMaximized()));
connect(titlebar, SIGNAL(popupOperationMenu(QPoint)),
this, SIGNAL(popupOperationMenu(QPoint)));
connect(titlebar, SIGNAL(showOperationMenu()),
this, SIGNAL(showOperationMenu()));
connect(titlebar, SIGNAL(doShade()),
this, SLOT(showShaded()));
connect(titlebar, SIGNAL(doubleClicked()),
this, SLOT(titleBarDoubleClicked()));
}
setMinimumSize(128, 0);
int fw = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
setContentsMargins(fw, fw, fw, fw);
childWidget = window;
if (!childWidget)
return;
setWindowTitle(childWidget->windowTitle());
QPoint p;
QSize s;
QSize cs;
bool hasBeenResized = childWidget->testAttribute(Qt::WA_Resized);
if (!hasBeenResized)
cs = childWidget->sizeHint().expandedTo(childWidget->minimumSizeHint()).expandedTo(childWidget->minimumSize()).boundedTo(childWidget->maximumSize());
else
cs = childWidget->size();
windowSize = cs;
int th = titlebar ? titlebar->sizeHint().height() : 0;
if (titlebar) {
if (!childWidget->windowIcon().isNull())
titlebar->setWindowIcon(childWidget->windowIcon());
if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
th -= contentsRect().y();
p = QPoint(contentsRect().x(),
th + contentsRect().y());
s = QSize(cs.width() + 2*frameWidth(),
cs.height() + 2*frameWidth() + th);
} else {
p = QPoint(contentsRect().x(), contentsRect().y());
s = QSize(cs.width() + 2*frameWidth(),
cs.height() + 2*frameWidth());
}
childWidget->move(p);
resize(s);
childWidget->installEventFilter(this);
widgetResizeHandler = new QWidgetResizeHandler(this, window);
widgetResizeHandler->setSizeProtection(!parent->scrollBarsEnabled());
widgetResizeHandler->setFrameWidth(frameWidth());
connect(widgetResizeHandler, SIGNAL(activate()),
this, SLOT(activate()));
if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
widgetResizeHandler->setExtraHeight(th + contentsRect().y() - 2*frameWidth());
else
widgetResizeHandler->setExtraHeight(th + contentsRect().y() - frameWidth());
if (childWidget->minimumSize() == childWidget->maximumSize())
widgetResizeHandler->setActive(QWidgetResizeHandler::Resize, false);
setBaseSize(baseSize());
}
QWorkspaceChild::~QWorkspaceChild()
{
QWorkspace *workspace = qobject_cast<QWorkspace*>(parentWidget());
if (iconw) {
if (workspace)
workspace->d_func()->removeIcon(iconw->parentWidget());
delete iconw->parentWidget();
}
if (workspace) {
workspace->d_func()->focus.removeAll(this);
if (workspace->d_func()->active == this)
workspace->activatePreviousWindow();
if (workspace->d_func()->active == this)
workspace->d_func()->activateWindow(0);
if (workspace->d_func()->maxWindow == this) {
workspace->d_func()->hideMaximizeControls();
workspace->d_func()->maxWindow = 0;
}
}
}
void QWorkspaceChild::moveEvent(QMoveEvent *)
{
((QWorkspace*)parentWidget())->d_func()->updateWorkspace();
}
void QWorkspaceChild::resizeEvent(QResizeEvent *)
{
bool wasMax = isMaximized();
QRect r = contentsRect();
QRect cr;
updateMask();
if (titlebar) {
int th = titlebar->sizeHint().height();
QRect tbrect(0, 0, width(), th);
if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
tbrect = QRect(r.x(), r.y(), r.width(), th);
titlebar->setGeometry(tbrect);
if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
th -= frameWidth();
cr = QRect(r.x(), r.y() + th + (shademode ? (frameWidth() * 3) : 0),
r.width(), r.height() - th);
} else {
cr = r;
}
if (!childWidget)
return;
bool doContentsResize = (windowSize == childWidget->size()
|| !(childWidget->testAttribute(Qt::WA_Resized) && childWidget->testAttribute(Qt::WA_PendingResizeEvent))
||childWidget->isMaximized());
windowSize = cr.size();
childWidget->move(cr.topLeft());
if (doContentsResize)
childWidget->resize(cr.size());
((QWorkspace*)parentWidget())->d_func()->updateWorkspace();
if (wasMax) {
overrideWindowState(Qt::WindowMaximized);
childWidget->overrideWindowState(Qt::WindowMaximized);
}
}
QSize QWorkspaceChild::baseSize() const
{
int th = titlebar ? titlebar->sizeHint().height() : 0;
if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
th -= frameWidth();
return QSize(2*frameWidth(), 2*frameWidth() + th);
}
QSize QWorkspaceChild::sizeHint() const
{
if (!childWidget)
return QWidget::sizeHint() + baseSize();
QSize prefSize = windowWidget()->sizeHint().expandedTo(windowWidget()->minimumSizeHint());
prefSize = prefSize.expandedTo(windowWidget()->minimumSize()).boundedTo(windowWidget()->maximumSize());
prefSize += baseSize();
return prefSize;
}
QSize QWorkspaceChild::minimumSizeHint() const
{
if (!childWidget)
return QWidget::minimumSizeHint() + baseSize();
QSize s = childWidget->minimumSize();
if (s.isEmpty())
s = childWidget->minimumSizeHint();
return s + baseSize();
}
void QWorkspaceChild::activate()
{
((QWorkspace*)parentWidget())->d_func()->activateWindow(windowWidget());
}
bool QWorkspaceChild::eventFilter(QObject * o, QEvent * e)
{
if (!isActive()
&& (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::FocusIn)) {
if (iconw) {
((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
if (iconw) {
((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
delete iconw->parentWidget();
iconw = 0;
}
}
activate();
}
// for all widgets except the window, that's the only thing we
// process, and if we have no childWidget we skip totally
if (o != childWidget || childWidget == 0)
return false;
switch (e->type()) {
case QEvent::ShowToParent:
if (((QWorkspace*)parentWidget())->d_func()->focus.indexOf(this) < 0)
((QWorkspace*)parentWidget())->d_func()->focus.append(this);
if (windowWidget() && (windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
internalRaise();
show();
}
((QWorkspace*)parentWidget())->d_func()->showWindow(windowWidget());
break;
case QEvent::WindowStateChange: {
if (static_cast<QWindowStateChangeEvent*>(e)->isOverride())
break;
Qt::WindowStates state = windowWidget()->windowState();
if (state & Qt::WindowMinimized) {
((QWorkspace*)parentWidget())->d_func()->minimizeWindow(windowWidget());
} else if (state & Qt::WindowMaximized) {
if (windowWidget()->maximumSize().isValid() &&
(windowWidget()->maximumWidth() < parentWidget()->width() ||
windowWidget()->maximumHeight() < parentWidget()->height())) {
windowWidget()->resize(windowWidget()->maximumSize());
windowWidget()->overrideWindowState(Qt::WindowNoState);
if (titlebar)
titlebar->update();
break;
}
if ((windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint))
((QWorkspace*)parentWidget())->d_func()->maximizeWindow(windowWidget());
else
((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
} else {
((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
if (iconw) {
((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
delete iconw->parentWidget();
}
}
} break;
case QEvent::HideToParent:
{
QWidget * w = iconw;
if (w && (w = w->parentWidget())) {
((QWorkspace*)parentWidget())->d_func()->removeIcon(w);
delete w;
}
((QWorkspace*)parentWidget())->d_func()->hideChild(this);
} break;
case QEvent::WindowIconChange:
{
QWorkspace* ws = (QWorkspace*)parentWidget();
if (ws->d_func()->maxtools && ws->d_func()->maxWindow == this) {
int iconSize = ws->d_func()->maxtools->size().height();
ws->d_func()->maxtools->setPixmap(childWidget->windowIcon().pixmap(QSize(iconSize, iconSize)));
}
}
// fall through
case QEvent::WindowTitleChange:
setWindowTitle(windowWidget()->windowTitle());
if (titlebar)
titlebar->update();
if (iconw)
iconw->update();
break;
case QEvent::ModifiedChange:
setWindowModified(windowWidget()->isWindowModified());
if (titlebar)
titlebar->update();
if (iconw)
iconw->update();
break;
case QEvent::Resize:
{
QResizeEvent* re = (QResizeEvent*)e;
if (re->size() != windowSize && !shademode) {
resize(re->size() + baseSize());
childWidget->update(); //workaround
}
}
break;
case QEvent::WindowDeactivate:
if (titlebar && titlebar->isActive()) {
update();
}
break;
case QEvent::WindowActivate:
if (titlebar && titlebar->isActive()) {
update();
}
break;
default:
break;
}
return QWidget::eventFilter(o, e);
}
void QWorkspaceChild::childEvent(QChildEvent* e)
{
if (e->type() == QEvent::ChildRemoved && e->child() == childWidget) {
childWidget = 0;
if (iconw) {
((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
delete iconw->parentWidget();
}
close();
}
}
void QWorkspaceChild::doResize()
{
widgetResizeHandler->doResize();
}
void QWorkspaceChild::doMove()
{
widgetResizeHandler->doMove();
}
void QWorkspaceChild::enterEvent(QEvent *)
{
}
void QWorkspaceChild::leaveEvent(QEvent *)
{
#ifndef QT_NO_CURSOR
if (!widgetResizeHandler->isButtonDown())
setCursor(Qt::ArrowCursor);
#endif
}
void QWorkspaceChild::paintEvent(QPaintEvent *)
{
QPainter p(this);
QStyleOptionFrame opt;
opt.rect = rect();
opt.palette = palette();
opt.state = QStyle::State_None;
opt.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
opt.midLineWidth = 1;
if (titlebar && titlebar->isActive() && isActiveWindow())
opt.state |= QStyle::State_Active;
style()->drawPrimitive(QStyle::PE_FrameWindow, &opt, &p, this);
}
void QWorkspaceChild::changeEvent(QEvent *ev)
{
if(ev->type() == QEvent::StyleChange) {
resizeEvent(0);
if (iconw) {
QFrame *frame = qobject_cast<QFrame*>(iconw->parentWidget());
Q_ASSERT(frame);
if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar)) {
frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
frame->resize(196+2*frame->frameWidth(), 20 + 2*frame->frameWidth());
} else {
frame->resize(196, 20);
}
}
updateMask();
}
QWidget::changeEvent(ev);
}
void QWorkspaceChild::setActive(bool b)
{
if (!childWidget)
return;
bool hasFocus = isChildOf(window()->focusWidget(), this);
if (act == b && (act == hasFocus))
return;
act = b;
if (titlebar)
titlebar->setActive(act);
if (iconw)
iconw->setActive(act);
update();
QList<QWidget*> wl = qFindChildren<QWidget*>(childWidget);
if (act) {
for (int i = 0; i < wl.size(); ++i) {
QWidget *w = wl.at(i);
w->removeEventFilter(this);
}
if (!hasFocus) {
QWidget *lastfocusw = childWidget->focusWidget();
if (lastfocusw && lastfocusw->focusPolicy() != Qt::NoFocus) {
lastfocusw->setFocus();
} else if (childWidget->focusPolicy() != Qt::NoFocus) {
childWidget->setFocus();
} else {
// find something, anything, that accepts focus, and use that.
for (int i = 0; i < wl.size(); ++i) {
QWidget *w = wl.at(i);
if(w->focusPolicy() != Qt::NoFocus) {
w->setFocus();
hasFocus = true;
break;
}
}
if (!hasFocus)
setFocus();
}
}
} else {
for (int i = 0; i < wl.size(); ++i) {
QWidget *w = wl.at(i);
w->removeEventFilter(this);
w->installEventFilter(this);
}
}
}
bool QWorkspaceChild::isActive() const
{
return act;
}
QWidget* QWorkspaceChild::windowWidget() const
{
return childWidget;
}
bool QWorkspaceChild::isWindowOrIconVisible() const
{
return childWidget && (!isHidden() || (iconw && !iconw->isHidden()));
}
void QWorkspaceChild::updateMask()
{
QStyleOptionTitleBar titleBarOptions;
titleBarOptions.rect = rect();
titleBarOptions.titleBarFlags = windowFlags();
titleBarOptions.titleBarState = windowState();
QStyleHintReturnMask frameMask;
if (style()->styleHint(QStyle::SH_WindowFrame_Mask, &titleBarOptions, this, &frameMask)) {
setMask(frameMask.region);
} else if (!mask().isEmpty()) {
clearMask();
}
if (iconw) {
QFrame *frame = qobject_cast<QFrame *>(iconw->parentWidget());
Q_ASSERT(frame);
titleBarOptions.rect = frame->rect();
titleBarOptions.titleBarFlags = frame->windowFlags();
titleBarOptions.titleBarState = frame->windowState() | Qt::WindowMinimized;
if (style()->styleHint(QStyle::SH_WindowFrame_Mask, &titleBarOptions, frame, &frameMask)) {
frame->setMask(frameMask.region);
} else if (!frame->mask().isEmpty()) {
frame->clearMask();
}
}
}
QWidget* QWorkspaceChild::iconWidget() const
{
if (!iconw) {
QWorkspaceChild* that = (QWorkspaceChild*) this;
QFrame* frame = new QFrame(that, Qt::Window);
QVBoxLayout *vbox = new QVBoxLayout(frame);
vbox->setMargin(0);
QWorkspaceTitleBar *tb = new QWorkspaceTitleBar(windowWidget(), frame);
vbox->addWidget(tb);
tb->setObjectName(QLatin1String("_workspacechild_icon_"));
QStyleOptionTitleBar opt;
tb->initStyleOption(&opt);
int th = style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, tb);
int iconSize = style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, 0, this);
if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar)) {
frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
frame->resize(iconSize+2*frame->frameWidth(), th+2*frame->frameWidth());
} else {
frame->resize(iconSize, th);
}
that->iconw = tb;
that->updateMask();
iconw->setActive(isActive());
connect(iconw, SIGNAL(doActivate()),
this, SLOT(activate()));
connect(iconw, SIGNAL(doClose()),
windowWidget(), SLOT(close()));
connect(iconw, SIGNAL(doNormal()),
this, SLOT(showNormal()));
connect(iconw, SIGNAL(doMaximize()),
this, SLOT(showMaximized()));
connect(iconw, SIGNAL(popupOperationMenu(QPoint)),
this, SIGNAL(popupOperationMenu(QPoint)));
connect(iconw, SIGNAL(showOperationMenu()),
this, SIGNAL(showOperationMenu()));
connect(iconw, SIGNAL(doubleClicked()),
this, SLOT(titleBarDoubleClicked()));
}
if (windowWidget()) {
iconw->setWindowTitle(windowWidget()->windowTitle());
}
return iconw->parentWidget();
}
void QWorkspaceChild::showMinimized()
{
windowWidget()->setWindowState(Qt::WindowMinimized | (windowWidget()->windowState() & ~Qt::WindowMaximized));
}
void QWorkspaceChild::showMaximized()
{
windowWidget()->setWindowState(Qt::WindowMaximized | (windowWidget()->windowState() & ~Qt::WindowMinimized));
}
void QWorkspaceChild::showNormal()
{
windowWidget()->setWindowState(windowWidget()->windowState() & ~(Qt::WindowMinimized|Qt::WindowMaximized));
}
void QWorkspaceChild::showShaded()
{
if (!titlebar)
return;
((QWorkspace*)parentWidget())->d_func()->activateWindow(windowWidget());
QWidget* w = windowWidget();
if (shademode) {
w->overrideWindowState(Qt::WindowNoState);
overrideWindowState(Qt::WindowNoState);
shademode = false;
resize(shadeRestore.expandedTo(minimumSizeHint()));
setMinimumSize(shadeRestoreMin);
style()->polish(this);
} else {
shadeRestore = size();
shadeRestoreMin = minimumSize();
setMinimumHeight(0);
shademode = true;
w->overrideWindowState(Qt::WindowMinimized);
overrideWindowState(Qt::WindowMinimized);
if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
resize(width(), titlebar->height());
else
resize(width(), titlebar->height() + 2*frameWidth() + 1);
style()->polish(this);
}
titlebar->update();
}
void QWorkspaceChild::titleBarDoubleClicked()
{
if (!windowWidget())
return;
if (iconw)
showNormal();
else if (windowWidget()->windowFlags() & Qt::WindowShadeButtonHint)
showShaded();
else if (windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint)
showMaximized();
}
void QWorkspaceChild::adjustToFullscreen()
{
if (!childWidget)
return;
if(!((QWorkspace*)parentWidget())->d_func()->maxmenubar || style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, this)) {
setGeometry(parentWidget()->rect());
} else {
int fw = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
bool noBorder = style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar);
int th = titlebar ? titlebar->sizeHint().height() : 0;
int w = parentWidget()->width() + 2*fw;
int h = parentWidget()->height() + (noBorder ? fw : 2*fw) + th;
w = qMax(w, childWidget->minimumWidth());
h = qMax(h, childWidget->minimumHeight());
setGeometry(-fw, (noBorder ? 0 : -fw) - th, w, h);
}
childWidget->overrideWindowState(Qt::WindowMaximized);
overrideWindowState(Qt::WindowMaximized);
}
void QWorkspaceChild::internalRaise()
{
QWidget *stackUnderWidget = 0;
if (!windowWidget() || (windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint) == 0) {
QList<QWorkspaceChild *>::Iterator it(((QWorkspace*)parent())->d_func()->windows.begin());
while (it != ((QWorkspace*)parent())->d_func()->windows.end()) {
QWorkspaceChild* c = *it;
++it;
if (c->windowWidget() &&
!c->windowWidget()->isHidden() &&
(c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
if (stackUnderWidget)
c->stackUnder(stackUnderWidget);
else
c->raise();
stackUnderWidget = c;
}
}
}
if (stackUnderWidget) {
if (iconw)
iconw->parentWidget()->stackUnder(stackUnderWidget);
stackUnder(stackUnderWidget);
} else {
if (iconw)
iconw->parentWidget()->raise();
raise();
}
}
void QWorkspaceChild::show()
{
if (childWidget && childWidget->isHidden())
childWidget->show();
QWidget::show();
}
bool QWorkspace::scrollBarsEnabled() const
{
Q_D(const QWorkspace);
return d->vbar != 0;
}
/*!
\property QWorkspace::scrollBarsEnabled
\brief whether the workspace provides scroll bars
If this property is true, the workspace will provide scroll bars if any
of the child windows extend beyond the edges of the visible
workspace. The workspace area will automatically increase to
contain child windows if they are resized beyond the right or
bottom edges of the visible area.
If this property is false (the default), resizing child windows
out of the visible area of the workspace is not permitted, although
it is still possible to position them partially outside the visible area.
*/
void QWorkspace::setScrollBarsEnabled(bool enable)
{
Q_D(QWorkspace);
if ((d->vbar != 0) == enable)
return;
d->xoffset = d->yoffset = 0;
if (enable) {
d->vbar = new QScrollBar(Qt::Vertical, this);
d->vbar->setObjectName(QLatin1String("vertical scrollbar"));
connect(d->vbar, SIGNAL(valueChanged(int)), this, SLOT(_q_scrollBarChanged()));
d->hbar = new QScrollBar(Qt::Horizontal, this);
d->hbar->setObjectName(QLatin1String("horizontal scrollbar"));
connect(d->hbar, SIGNAL(valueChanged(int)), this, SLOT(_q_scrollBarChanged()));
d->corner = new QWidget(this);
d->corner->setBackgroundRole(QPalette::Window);
d->corner->setObjectName(QLatin1String("qt_corner"));
d->updateWorkspace();
} else {
delete d->vbar;
delete d->hbar;
delete d->corner;
d->vbar = d->hbar = 0;
d->corner = 0;
}
QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
while (it != d->windows.end()) {
QWorkspaceChild *child = *it;
++it;
child->widgetResizeHandler->setSizeProtection(!enable);
}
}
QRect QWorkspacePrivate::updateWorkspace()
{
Q_Q(QWorkspace);
QRect cr(q->rect());
if (q->scrollBarsEnabled() && !maxWindow) {
corner->raise();
vbar->raise();
hbar->raise();
if (maxWindow)
maxWindow->internalRaise();
QRect r(0, 0, 0, 0);
QList<QWorkspaceChild *>::Iterator it(windows.begin());
while (it != windows.end()) {
QWorkspaceChild *child = *it;
++it;
if (!child->isHidden())
r = r.unite(child->geometry());
}
vbar->blockSignals(true);
hbar->blockSignals(true);
int hsbExt = hbar->sizeHint().height();
int vsbExt = vbar->sizeHint().width();
bool showv = yoffset || yoffset + r.bottom() - q->height() + 1 > 0 || yoffset + r.top() < 0;
bool showh = xoffset || xoffset + r.right() - q->width() + 1 > 0 || xoffset + r.left() < 0;
if (showh && !showv)
showv = yoffset + r.bottom() - q->height() + hsbExt + 1 > 0;
if (showv && !showh)
showh = xoffset + r.right() - q->width() + vsbExt + 1 > 0;
if (!showh)
hsbExt = 0;
if (!showv)
vsbExt = 0;
if (showv) {
vbar->setSingleStep(qMax(q->height() / 12, 30));
vbar->setPageStep(q->height() - hsbExt);
vbar->setMinimum(qMin(0, yoffset + qMin(0, r.top())));
vbar->setMaximum(qMax(0, yoffset + qMax(0, r.bottom() - q->height() + hsbExt + 1)));
vbar->setGeometry(q->width() - vsbExt, 0, vsbExt, q->height() - hsbExt);
vbar->setValue(yoffset);
vbar->show();
} else {
vbar->hide();
}
if (showh) {
hbar->setSingleStep(qMax(q->width() / 12, 30));
hbar->setPageStep(q->width() - vsbExt);
hbar->setMinimum(qMin(0, xoffset + qMin(0, r.left())));
hbar->setMaximum(qMax(0, xoffset + qMax(0, r.right() - q->width() + vsbExt + 1)));
hbar->setGeometry(0, q->height() - hsbExt, q->width() - vsbExt, hsbExt);
hbar->setValue(xoffset);
hbar->show();
} else {
hbar->hide();
}
if (showh && showv) {
corner->setGeometry(q->width() - vsbExt, q->height() - hsbExt, vsbExt, hsbExt);
corner->show();
} else {
corner->hide();
}
vbar->blockSignals(false);
hbar->blockSignals(false);
cr.setRect(0, 0, q->width() - vsbExt, q->height() - hsbExt);
}
QList<QWidget *>::Iterator ii(icons.begin());
while (ii != icons.end()) {
QWidget* w = *ii;
++ii;
int x = w->x();
int y = w->y();
bool m = false;
if (x+w->width() > cr.width()) {
m = true;
x = cr.width() - w->width();
}
if (y+w->height() > cr.height()) {
y = cr.height() - w->height();
m = true;
}
if (m) {
if (QWorkspaceChild *child = qobject_cast<QWorkspaceChild*>(w))
child->move(x, y);
else
w->move(x, y);
}
}
return cr;
}
void QWorkspacePrivate::_q_scrollBarChanged()
{
int ver = yoffset - vbar->value();
int hor = xoffset - hbar->value();
yoffset = vbar->value();
xoffset = hbar->value();
QList<QWorkspaceChild *>::Iterator it(windows.begin());
while (it != windows.end()) {
QWorkspaceChild *child = *it;
++it;
// we do not use move() due to the reimplementation in QWorkspaceChild
child->setGeometry(child->x() + hor, child->y() + ver, child->width(), child->height());
}
updateWorkspace();
}
/*!
\enum QWorkspace::WindowOrder
Specifies the order in which child windows are returned from windowList().
\value CreationOrder The windows are returned in the order of their creation
\value StackingOrder The windows are returned in the order of their stacking
*/
/*!\reimp */
void QWorkspace::changeEvent(QEvent *ev)
{
Q_D(QWorkspace);
if(ev->type() == QEvent::StyleChange) {
if (isVisible() && d->maxWindow && d->maxmenubar) {
if(style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, this)) {
d->hideMaximizeControls(); //hide any visible maximized controls
d->showMaximizeControls(); //updates the modification state as well
}
}
}
QWidget::changeEvent(ev);
}
QT_END_NAMESPACE
#include "moc_qworkspace.cpp"
#include "qworkspace.moc"
#endif // QT_NO_WORKSPACE