mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-27 04:13:08 +00:00
3338 lines
102 KiB
C++
3338 lines
102 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Contact: http://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtGui module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
|
**
|
|
** 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 or version 3 as published by the Free
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
** following information to ensure the GNU Lesser General Public License
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
** rights. These rights are described in The Qt Company 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.
|
|
**
|
|
** $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 <qwidget_p.h>
|
|
#include <qwidgetresizehandler_p.h>
|
|
#include <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 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();
|
|
}
|
|
|
|
|
|
/*!
|
|
\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')+QKeySequence(Qt::CTRL+Qt::Key_F4).toString()
|
|
#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);
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
\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);
|
|
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::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 = childWidget->findChildren<QWidget*>();
|
|
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.united(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 "moc_qworkspace.h"
|
|
|
|
#endif // QT_NO_WORKSPACE
|