1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qworkspace.h"
43 #ifndef QT_NO_WORKSPACE
44 #include "qapplication.h"
45 #include "qbitmap.h"
46 #include "qcursor.h"
47 #include "qdesktopwidget.h"
48 #include "qevent.h"
49 #include "qhash.h"
50 #include "qicon.h"
51 #include "qimage.h"
52 #include "qlabel.h"
53 #include "qlayout.h"
54 #include "qmenubar.h"
55 #include "qmenu.h"
56 #include "qpainter.h"
57 #include "qpointer.h"
58 #include "qscrollbar.h"
59 #include "qstyle.h"
60 #include "qstyleoption.h"
61 #include "qelapsedtimer.h"
62 #include "qtooltip.h"
63 #include "qdebug.h"
64 #include <private/qwidget_p.h>
65 #include <private/qwidgetresizehandler_p.h>
66 #include <private/qlayoutengine_p.h>
67
68 QT_BEGIN_NAMESPACE
69
70 class QWorkspaceTitleBarPrivate;
71
72
73 /**************************************************************
74 * QMDIControl
75 *
76 * Used for displaying MDI controls in a maximized MDI window
77 *
78 */
79 class QMDIControl : public QWidget
80 {
81 Q_OBJECT
82 signals:
83 void _q_minimize();
84 void _q_restore();
85 void _q_close();
86
87 public:
88 QMDIControl(QWidget *widget);
89
90 private:
91 QSize sizeHint() const;
92 void paintEvent(QPaintEvent *event);
93 void mousePressEvent(QMouseEvent *event);
94 void mouseReleaseEvent(QMouseEvent *event);
95 void mouseMoveEvent(QMouseEvent *event);
96 void leaveEvent(QEvent *event);
97 bool event(QEvent *event);
98 void initStyleOption(QStyleOptionComplex *option) const;
99 QStyle::SubControl activeControl; //control locked by pressing and holding the mouse
100 QStyle::SubControl hoverControl; //previously active hover control, used for tracking repaints
101 };
102
event(QEvent * event)103 bool QMDIControl::event(QEvent *event)
104 {
105 if (event->type() == QEvent::ToolTip) {
106 QStyleOptionComplex opt;
107 initStyleOption(&opt);
108 #ifndef QT_NO_TOOLTIP
109 QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
110 QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
111 helpEvent->pos(), this);
112 if (ctrl == QStyle::SC_MdiCloseButton)
113 QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Close"), this);
114 else if (ctrl == QStyle::SC_MdiMinButton)
115 QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Minimize"), this);
116 else if (ctrl == QStyle::SC_MdiNormalButton)
117 QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Restore Down"), this);
118 else
119 QToolTip::hideText();
120 #endif // QT_NO_TOOLTIP
121 }
122 return QWidget::event(event);
123 }
124
initStyleOption(QStyleOptionComplex * option) const125 void QMDIControl::initStyleOption(QStyleOptionComplex *option) const
126 {
127 option->initFrom(this);
128 option->subControls = QStyle::SC_All;
129 option->activeSubControls = QStyle::SC_None;
130 }
131
QMDIControl(QWidget * widget)132 QMDIControl::QMDIControl(QWidget *widget)
133 : QWidget(widget), activeControl(QStyle::SC_None),
134 hoverControl(QStyle::SC_None)
135 {
136 setObjectName(QLatin1String("qt_maxcontrols"));
137 setFocusPolicy(Qt::NoFocus);
138 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
139 setMouseTracking(true);
140 }
141
sizeHint() const142 QSize QMDIControl::sizeHint() const
143 {
144 ensurePolished();
145 QStyleOptionComplex opt;
146 initStyleOption(&opt);
147 QSize size(48, 16);
148 return style()->sizeFromContents(QStyle::CT_MdiControls, &opt, size, this);
149 }
150
mousePressEvent(QMouseEvent * event)151 void QMDIControl::mousePressEvent(QMouseEvent *event)
152 {
153 if (event->button() != Qt::LeftButton) {
154 event->ignore();
155 return;
156 }
157 QStyleOptionComplex opt;
158 initStyleOption(&opt);
159 QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
160 event->pos(), this);
161 activeControl = ctrl;
162 update();
163 }
164
mouseReleaseEvent(QMouseEvent * event)165 void QMDIControl::mouseReleaseEvent(QMouseEvent *event)
166 {
167 if (event->button() != Qt::LeftButton) {
168 event->ignore();
169 return;
170 }
171 QStyleOptionTitleBar opt;
172 initStyleOption(&opt);
173 QStyle::SubControl under_mouse = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
174 event->pos(), this);
175 if (under_mouse == activeControl) {
176 switch (activeControl) {
177 case QStyle::SC_MdiCloseButton:
178 emit _q_close();
179 break;
180 case QStyle::SC_MdiNormalButton:
181 emit _q_restore();
182 break;
183 case QStyle::SC_MdiMinButton:
184 emit _q_minimize();
185 break;
186 default:
187 break;
188 }
189 }
190 activeControl = QStyle::SC_None;
191 update();
192 }
193
leaveEvent(QEvent *)194 void QMDIControl::leaveEvent(QEvent * /*event*/)
195 {
196 hoverControl = QStyle::SC_None;
197 update();
198 }
199
mouseMoveEvent(QMouseEvent * event)200 void QMDIControl::mouseMoveEvent(QMouseEvent *event)
201 {
202 QStyleOptionTitleBar opt;
203 initStyleOption(&opt);
204 QStyle::SubControl under_mouse = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
205 event->pos(), this);
206 //test if hover state changes
207 if (hoverControl != under_mouse) {
208 hoverControl = under_mouse;
209 update();
210 }
211 }
212
paintEvent(QPaintEvent *)213 void QMDIControl::paintEvent(QPaintEvent *)
214 {
215 QPainter p(this);
216 QStyleOptionComplex opt;
217 initStyleOption(&opt);
218 if (activeControl == hoverControl) {
219 opt.activeSubControls = activeControl;
220 opt.state |= QStyle::State_Sunken;
221 } else if (hoverControl != QStyle::SC_None && (activeControl == QStyle::SC_None)) {
222 opt.activeSubControls = hoverControl;
223 opt.state |= QStyle::State_MouseOver;
224 }
225 style()->drawComplexControl(QStyle::CC_MdiControls, &opt, &p, this);
226 }
227
228 class QWorkspaceTitleBar : public QWidget
229 {
230 Q_OBJECT
231 Q_DECLARE_PRIVATE(QWorkspaceTitleBar)
232 Q_PROPERTY(bool autoRaise READ autoRaise WRITE setAutoRaise)
233 Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
234
235 public:
236 QWorkspaceTitleBar (QWidget *w, QWidget *parent, Qt::WindowFlags f = 0);
237 ~QWorkspaceTitleBar();
238
239 bool isActive() const;
240 bool usesActiveColor() const;
241
242 bool isMovable() const;
243 void setMovable(bool);
244
245 bool autoRaise() const;
246 void setAutoRaise(bool);
247
248 QWidget *window() const;
249 bool isTool() const;
250
251 QSize sizeHint() const;
252 void initStyleOption(QStyleOptionTitleBar *option) const;
253
254 public slots:
255 void setActive(bool);
256
257 signals:
258 void doActivate();
259 void doNormal();
260 void doClose();
261 void doMaximize();
262 void doMinimize();
263 void doShade();
264 void showOperationMenu();
265 void popupOperationMenu(const QPoint&);
266 void doubleClicked();
267
268 protected:
269 bool event(QEvent *);
270 #ifndef QT_NO_CONTEXTMENU
271 void contextMenuEvent(QContextMenuEvent *);
272 #endif
273 void mousePressEvent(QMouseEvent *);
274 void mouseDoubleClickEvent(QMouseEvent *);
275 void mouseReleaseEvent(QMouseEvent *);
276 void mouseMoveEvent(QMouseEvent *);
277 void enterEvent(QEvent *e);
278 void leaveEvent(QEvent *e);
279 void paintEvent(QPaintEvent *p);
280
281 private:
282 Q_DISABLE_COPY(QWorkspaceTitleBar)
283 };
284
285
286 class QWorkspaceTitleBarPrivate : public QWidgetPrivate
287 {
288 Q_DECLARE_PUBLIC(QWorkspaceTitleBar)
289 public:
QWorkspaceTitleBarPrivate()290 QWorkspaceTitleBarPrivate()
291 :
292 lastControl(QStyle::SC_None),
293 #ifndef QT_NO_TOOLTIP
294 toolTip(0),
295 #endif
296 act(0), window(0), movable(1), pressed(0), autoraise(0), moving(0)
297 {
298 }
299
300 Qt::WindowFlags flags;
301 QStyle::SubControl buttonDown;
302 QStyle::SubControl lastControl;
303 QPoint moveOffset;
304 #ifndef QT_NO_TOOLTIP
305 QToolTip *toolTip;
306 #endif
307 bool act :1;
308 QPointer<QWidget> window;
309 bool movable :1;
310 bool pressed :1;
311 bool autoraise :1;
312 bool moving : 1;
313
314 int titleBarState() const;
315 void readColors();
316 };
317
titleBarState() const318 inline int QWorkspaceTitleBarPrivate::titleBarState() const
319 {
320 Q_Q(const QWorkspaceTitleBar);
321 uint state = window ? window->windowState() : static_cast<Qt::WindowStates>(Qt::WindowNoState);
322 state |= uint((act && q->isActiveWindow()) ? QStyle::State_Active : QStyle::State_None);
323 return (int)state;
324 }
325
initStyleOption(QStyleOptionTitleBar * option) const326 void QWorkspaceTitleBar::initStyleOption(QStyleOptionTitleBar *option) const
327 {
328 Q_D(const QWorkspaceTitleBar);
329 option->initFrom(this);
330 //################
331 if (d->window && (d->flags & Qt::WindowTitleHint)) {
332 option->text = d->window->windowTitle();
333 QIcon icon = d->window->windowIcon();
334 QSize s = icon.actualSize(QSize(64, 64));
335 option->icon = icon.pixmap(s);
336 }
337 option->subControls = QStyle::SC_All;
338 option->activeSubControls = QStyle::SC_None;
339 option->titleBarState = d->titleBarState();
340 option->titleBarFlags = d->flags;
341 option->state &= ~QStyle::State_MouseOver;
342 }
343
QWorkspaceTitleBar(QWidget * w,QWidget * parent,Qt::WindowFlags f)344 QWorkspaceTitleBar::QWorkspaceTitleBar(QWidget *w, QWidget *parent, Qt::WindowFlags f)
345 : QWidget(*new QWorkspaceTitleBarPrivate, parent, Qt::FramelessWindowHint)
346 {
347 Q_D(QWorkspaceTitleBar);
348 if (f == 0 && w)
349 f = w->windowFlags();
350 d->flags = f;
351 d->window = w;
352 d->buttonDown = QStyle::SC_None;
353 d->act = 0;
354 if (w) {
355 if (w->maximumSize() != QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX))
356 d->flags &= ~Qt::WindowMaximizeButtonHint;
357 setWindowTitle(w->windowTitle());
358 }
359
360 d->readColors();
361 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
362 setMouseTracking(true);
363 setAutoRaise(style()->styleHint(QStyle::SH_TitleBar_AutoRaise, 0, this));
364 }
365
~QWorkspaceTitleBar()366 QWorkspaceTitleBar::~QWorkspaceTitleBar()
367 {
368 }
369
370
371 #ifdef Q_WS_WIN
colorref2qrgb(COLORREF col)372 static inline QRgb colorref2qrgb(COLORREF col)
373 {
374 return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
375 }
376 #endif
377
readColors()378 void QWorkspaceTitleBarPrivate::readColors()
379 {
380 Q_Q(QWorkspaceTitleBar);
381 QPalette pal = q->palette();
382
383 bool colorsInitialized = false;
384
385 #ifdef Q_WS_WIN // ask system properties on windows
386 #ifndef SPI_GETGRADIENTCAPTIONS
387 #define SPI_GETGRADIENTCAPTIONS 0x1008
388 #endif
389 #ifndef COLOR_GRADIENTACTIVECAPTION
390 #define COLOR_GRADIENTACTIVECAPTION 27
391 #endif
392 #ifndef COLOR_GRADIENTINACTIVECAPTION
393 #define COLOR_GRADIENTINACTIVECAPTION 28
394 #endif
395 if (QApplication::desktopSettingsAware()) {
396 pal.setColor(QPalette::Active, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)));
397 pal.setColor(QPalette::Inactive, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)));
398 pal.setColor(QPalette::Active, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)));
399 pal.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
400
401 colorsInitialized = true;
402 BOOL gradient = false;
403 SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
404
405 if (gradient) {
406 pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
407 pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
408 } else {
409 pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight));
410 pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight));
411 }
412 }
413 #endif // Q_WS_WIN
414 if (!colorsInitialized) {
415 pal.setColor(QPalette::Active, QPalette::Highlight,
416 pal.color(QPalette::Active, QPalette::Highlight));
417 pal.setColor(QPalette::Active, QPalette::Base,
418 pal.color(QPalette::Active, QPalette::Highlight));
419 pal.setColor(QPalette::Inactive, QPalette::Highlight,
420 pal.color(QPalette::Inactive, QPalette::Dark));
421 pal.setColor(QPalette::Inactive, QPalette::Base,
422 pal.color(QPalette::Inactive, QPalette::Dark));
423 pal.setColor(QPalette::Inactive, QPalette::HighlightedText,
424 pal.color(QPalette::Inactive, QPalette::Window));
425 }
426
427 q->setPalette(pal);
428 q->setActive(act);
429 }
430
mousePressEvent(QMouseEvent * e)431 void QWorkspaceTitleBar::mousePressEvent(QMouseEvent *e)
432 {
433 Q_D(QWorkspaceTitleBar);
434 if (!d->act)
435 emit doActivate();
436 if (e->button() == Qt::LeftButton) {
437 if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
438 && !rect().adjusted(5, 5, -5, 0).contains(e->pos())) {
439 // propagate border events to the QWidgetResizeHandler
440 e->ignore();
441 return;
442 }
443
444 d->pressed = true;
445 QStyleOptionTitleBar opt;
446 initStyleOption(&opt);
447 QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
448 e->pos(), this);
449 switch (ctrl) {
450 case QStyle::SC_TitleBarSysMenu:
451 if (d->flags & Qt::WindowSystemMenuHint) {
452 d->buttonDown = QStyle::SC_None;
453 static QElapsedTimer *t = 0;
454 static QWorkspaceTitleBar *tc = 0;
455 if (!t)
456 t = new QElapsedTimer;
457 if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
458 emit showOperationMenu();
459 t->start();
460 tc = this;
461 } else {
462 tc = 0;
463 emit doClose();
464 return;
465 }
466 }
467 break;
468
469 case QStyle::SC_TitleBarShadeButton:
470 case QStyle::SC_TitleBarUnshadeButton:
471 if (d->flags & Qt::WindowShadeButtonHint)
472 d->buttonDown = ctrl;
473 break;
474
475 case QStyle::SC_TitleBarNormalButton:
476 d->buttonDown = ctrl;
477 break;
478
479 case QStyle::SC_TitleBarMinButton:
480 if (d->flags & Qt::WindowMinimizeButtonHint)
481 d->buttonDown = ctrl;
482 break;
483
484 case QStyle::SC_TitleBarMaxButton:
485 if (d->flags & Qt::WindowMaximizeButtonHint)
486 d->buttonDown = ctrl;
487 break;
488
489 case QStyle::SC_TitleBarCloseButton:
490 if (d->flags & Qt::WindowSystemMenuHint)
491 d->buttonDown = ctrl;
492 break;
493
494 case QStyle::SC_TitleBarLabel:
495 d->buttonDown = ctrl;
496 d->moveOffset = mapToParent(e->pos());
497 break;
498
499 default:
500 break;
501 }
502 update();
503 } else {
504 d->pressed = false;
505 }
506 }
507
508 #ifndef QT_NO_CONTEXTMENU
contextMenuEvent(QContextMenuEvent * e)509 void QWorkspaceTitleBar::contextMenuEvent(QContextMenuEvent *e)
510 {
511 QStyleOptionTitleBar opt;
512 initStyleOption(&opt);
513 QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(),
514 this);
515 if(ctrl == QStyle::SC_TitleBarLabel || ctrl == QStyle::SC_TitleBarSysMenu) {
516 e->accept();
517 emit popupOperationMenu(e->globalPos());
518 } else {
519 e->ignore();
520 }
521 }
522 #endif // QT_NO_CONTEXTMENU
523
mouseReleaseEvent(QMouseEvent * e)524 void QWorkspaceTitleBar::mouseReleaseEvent(QMouseEvent *e)
525 {
526 Q_D(QWorkspaceTitleBar);
527 if (!d->window) {
528 // could have been deleted as part of a double click event on the sysmenu
529 return;
530 }
531 if (e->button() == Qt::LeftButton && d->pressed) {
532 if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
533 && !rect().adjusted(5, 5, -5, 0).contains(e->pos())) {
534 // propagate border events to the QWidgetResizeHandler
535 e->ignore();
536 d->buttonDown = QStyle::SC_None;
537 d->pressed = false;
538 return;
539 }
540 e->accept();
541 QStyleOptionTitleBar opt;
542 initStyleOption(&opt);
543 QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
544 e->pos(), this);
545
546 if (d->pressed) {
547 update();
548 d->pressed = false;
549 d->moving = false;
550 }
551 if (ctrl == d->buttonDown) {
552 d->buttonDown = QStyle::SC_None;
553 switch(ctrl) {
554 case QStyle::SC_TitleBarShadeButton:
555 case QStyle::SC_TitleBarUnshadeButton:
556 if(d->flags & Qt::WindowShadeButtonHint)
557 emit doShade();
558 break;
559
560 case QStyle::SC_TitleBarNormalButton:
561 if(d->flags & Qt::WindowMinMaxButtonsHint)
562 emit doNormal();
563 break;
564
565 case QStyle::SC_TitleBarMinButton:
566 if(d->flags & Qt::WindowMinimizeButtonHint) {
567 if (d->window && d->window->isMinimized())
568 emit doNormal();
569 else
570 emit doMinimize();
571 }
572 break;
573
574 case QStyle::SC_TitleBarMaxButton:
575 if(d->flags & Qt::WindowMaximizeButtonHint) {
576 if(d->window && d->window->isMaximized())
577 emit doNormal();
578 else
579 emit doMaximize();
580 }
581 break;
582
583 case QStyle::SC_TitleBarCloseButton:
584 if(d->flags & Qt::WindowSystemMenuHint) {
585 d->buttonDown = QStyle::SC_None;
586 emit doClose();
587 return;
588 }
589 break;
590
591 default:
592 break;
593 }
594 }
595 } else {
596 e->ignore();
597 }
598 }
599
mouseMoveEvent(QMouseEvent * e)600 void QWorkspaceTitleBar::mouseMoveEvent(QMouseEvent *e)
601 {
602 Q_D(QWorkspaceTitleBar);
603 e->ignore();
604 if ((e->buttons() & Qt::LeftButton) && style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
605 && !rect().adjusted(5, 5, -5, 0).contains(e->pos()) && !d->pressed) {
606 // propagate border events to the QWidgetResizeHandler
607 return;
608 }
609
610 QStyleOptionTitleBar opt;
611 initStyleOption(&opt);
612 QStyle::SubControl under_mouse = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
613 e->pos(), this);
614 if(under_mouse != d->lastControl) {
615 d->lastControl = under_mouse;
616 update();
617 }
618
619 switch (d->buttonDown) {
620 case QStyle::SC_None:
621 break;
622 case QStyle::SC_TitleBarSysMenu:
623 break;
624 case QStyle::SC_TitleBarLabel:
625 if (d->buttonDown == QStyle::SC_TitleBarLabel && d->movable && d->pressed) {
626 if (d->moving || (d->moveOffset - mapToParent(e->pos())).manhattanLength() >= 4) {
627 d->moving = true;
628 QPoint p = mapFromGlobal(e->globalPos());
629
630 QWidget *parent = d->window ? d->window->parentWidget() : 0;
631 if(parent && parent->inherits("QWorkspaceChild")) {
632 QWidget *workspace = parent->parentWidget();
633 p = workspace->mapFromGlobal(e->globalPos());
634 if (!workspace->rect().contains(p)) {
635 if (p.x() < 0)
636 p.rx() = 0;
637 if (p.y() < 0)
638 p.ry() = 0;
639 if (p.x() > workspace->width())
640 p.rx() = workspace->width();
641 if (p.y() > workspace->height())
642 p.ry() = workspace->height();
643 }
644 }
645
646 QPoint pp = p - d->moveOffset;
647 if (!parentWidget()->isMaximized())
648 parentWidget()->move(pp);
649 }
650 }
651 e->accept();
652 break;
653 default:
654 break;
655 }
656 }
657
isTool() const658 bool QWorkspaceTitleBar::isTool() const
659 {
660 Q_D(const QWorkspaceTitleBar);
661 return (d->flags & Qt::WindowType_Mask) == Qt::Tool;
662 }
663
664 // from qwidget.cpp
665 extern QString qt_setWindowTitle_helperHelper(const QString &, const QWidget*);
666
paintEvent(QPaintEvent *)667 void QWorkspaceTitleBar::paintEvent(QPaintEvent *)
668 {
669 Q_D(QWorkspaceTitleBar);
670 QStyleOptionTitleBar opt;
671 initStyleOption(&opt);
672 opt.subControls = QStyle::SC_TitleBarLabel;
673 opt.activeSubControls = d->buttonDown;
674
675 if (d->window && (d->flags & Qt::WindowTitleHint)) {
676 QString title = qt_setWindowTitle_helperHelper(opt.text, d->window);
677 int maxw = style()->subControlRect(QStyle::CC_TitleBar, &opt, QStyle::SC_TitleBarLabel,
678 this).width();
679 opt.text = fontMetrics().elidedText(title, Qt::ElideRight, maxw);
680 }
681
682 if (d->flags & Qt::WindowSystemMenuHint) {
683 opt.subControls |= QStyle::SC_TitleBarSysMenu | QStyle::SC_TitleBarCloseButton;
684 if (d->window && (d->flags & Qt::WindowShadeButtonHint)) {
685 if (d->window->isMinimized())
686 opt.subControls |= QStyle::SC_TitleBarUnshadeButton;
687 else
688 opt.subControls |= QStyle::SC_TitleBarShadeButton;
689 }
690 if (d->window && (d->flags & Qt::WindowMinMaxButtonsHint)) {
691 if(d->window && d->window->isMinimized())
692 opt.subControls |= QStyle::SC_TitleBarNormalButton;
693 else
694 opt.subControls |= QStyle::SC_TitleBarMinButton;
695 }
696 if (d->window && (d->flags & Qt::WindowMaximizeButtonHint) && !d->window->isMaximized())
697 opt.subControls |= QStyle::SC_TitleBarMaxButton;
698 }
699
700 QStyle::SubControl under_mouse = QStyle::SC_None;
701 under_mouse = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
702 mapFromGlobal(QCursor::pos()), this);
703 if ((d->buttonDown == under_mouse) && d->pressed) {
704 opt.state |= QStyle::State_Sunken;
705 } else if( autoRaise() && under_mouse != QStyle::SC_None && !d->pressed) {
706 opt.activeSubControls = under_mouse;
707 opt.state |= QStyle::State_MouseOver;
708 }
709 opt.palette.setCurrentColorGroup(usesActiveColor() ? QPalette::Active : QPalette::Inactive);
710
711 QPainter p(this);
712 style()->drawComplexControl(QStyle::CC_TitleBar, &opt, &p, this);
713 }
714
mouseDoubleClickEvent(QMouseEvent * e)715 void QWorkspaceTitleBar::mouseDoubleClickEvent(QMouseEvent *e)
716 {
717 Q_D(QWorkspaceTitleBar);
718 if (e->button() != Qt::LeftButton) {
719 e->ignore();
720 return;
721 }
722 e->accept();
723 QStyleOptionTitleBar opt;
724 initStyleOption(&opt);
725 switch (style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(), this)) {
726 case QStyle::SC_TitleBarLabel:
727 emit doubleClicked();
728 break;
729
730 case QStyle::SC_TitleBarSysMenu:
731 if (d->flags & Qt::WindowSystemMenuHint)
732 emit doClose();
733 break;
734
735 default:
736 break;
737 }
738 }
739
leaveEvent(QEvent *)740 void QWorkspaceTitleBar::leaveEvent(QEvent *)
741 {
742 Q_D(QWorkspaceTitleBar);
743 d->lastControl = QStyle::SC_None;
744 if(autoRaise() && !d->pressed)
745 update();
746 }
747
enterEvent(QEvent *)748 void QWorkspaceTitleBar::enterEvent(QEvent *)
749 {
750 Q_D(QWorkspaceTitleBar);
751 if(autoRaise() && !d->pressed)
752 update();
753 QEvent e(QEvent::Leave);
754 QApplication::sendEvent(parentWidget(), &e);
755 }
756
setActive(bool active)757 void QWorkspaceTitleBar::setActive(bool active)
758 {
759 Q_D(QWorkspaceTitleBar);
760 if (d->act == active)
761 return ;
762
763 d->act = active;
764 update();
765 }
766
isActive() const767 bool QWorkspaceTitleBar::isActive() const
768 {
769 Q_D(const QWorkspaceTitleBar);
770 return d->act;
771 }
772
usesActiveColor() const773 bool QWorkspaceTitleBar::usesActiveColor() const
774 {
775 return (isActive() && isActiveWindow()) ||
776 (!window() && QWidget::window()->isActiveWindow());
777 }
778
window() const779 QWidget *QWorkspaceTitleBar::window() const
780 {
781 Q_D(const QWorkspaceTitleBar);
782 return d->window;
783 }
784
event(QEvent * e)785 bool QWorkspaceTitleBar::event(QEvent *e)
786 {
787 Q_D(QWorkspaceTitleBar);
788 if (e->type() == QEvent::ApplicationPaletteChange) {
789 d->readColors();
790 } else if (e->type() == QEvent::WindowActivate
791 || e->type() == QEvent::WindowDeactivate) {
792 if (d->act)
793 update();
794 }
795 return QWidget::event(e);
796 }
797
setMovable(bool b)798 void QWorkspaceTitleBar::setMovable(bool b)
799 {
800 Q_D(QWorkspaceTitleBar);
801 d->movable = b;
802 }
803
isMovable() const804 bool QWorkspaceTitleBar::isMovable() const
805 {
806 Q_D(const QWorkspaceTitleBar);
807 return d->movable;
808 }
809
setAutoRaise(bool b)810 void QWorkspaceTitleBar::setAutoRaise(bool b)
811 {
812 Q_D(QWorkspaceTitleBar);
813 d->autoraise = b;
814 }
815
autoRaise() const816 bool QWorkspaceTitleBar::autoRaise() const
817 {
818 Q_D(const QWorkspaceTitleBar);
819 return d->autoraise;
820 }
821
sizeHint() const822 QSize QWorkspaceTitleBar::sizeHint() const
823 {
824 ensurePolished();
825 QStyleOptionTitleBar opt;
826 initStyleOption(&opt);
827 QRect menur = style()->subControlRect(QStyle::CC_TitleBar, &opt,
828 QStyle::SC_TitleBarSysMenu, this);
829 return QSize(menur.width(), style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, this));
830 }
831
832 /*!
833 \class QWorkspace
834 \obsolete
835 \brief The QWorkspace widget provides a workspace window that can be
836 used in an MDI application.
837
838 This class is deprecated. Use QMdiArea instead.
839
840 Multiple Document Interface (MDI) applications are typically
841 composed of a main window containing a menu bar, a toolbar, and
842 a central QWorkspace widget. The workspace itself is used to display
843 a number of child windows, each of which is a widget.
844
845 The workspace itself is an ordinary Qt widget. It has a standard
846 constructor that takes a parent widget.
847 Workspaces can be placed in any layout, but are typically given
848 as the central widget in a QMainWindow:
849
850 \snippet doc/src/snippets/code/src_gui_widgets_qworkspace.cpp 0
851
852 Child windows (MDI windows) are standard Qt widgets that are
853 inserted into the workspace with addWindow(). As with top-level
854 widgets, you can call functions such as show(), hide(),
855 showMaximized(), and setWindowTitle() on a child window to change
856 its appearance within the workspace. You can also provide widget
857 flags to determine the layout of the decoration or the behavior of
858 the widget itself.
859
860 To change or retrieve the geometry of a child window, you must
861 operate on its parentWidget(). The parentWidget() provides
862 access to the decorated frame that contains the child window
863 widget. When a child window is maximised, its decorated frame
864 is hidden. If the top-level widget contains a menu bar, it will display
865 the maximised window's operations menu to the left of the menu
866 entries, and the window's controls to the right.
867
868 A child window becomes active when it gets the keyboard focus,
869 or when setFocus() is called. The user can activate a window by moving
870 focus in the usual ways, for example by clicking a window or by pressing
871 Tab. The workspace emits a signal windowActivated() when the active
872 window changes, and the function activeWindow() returns a pointer to the
873 active child window, or 0 if no window is active.
874
875 The convenience function windowList() returns a list of all child
876 windows. This information could be used in a popup menu
877 containing a list of windows, for example. This feature is also
878 available as part of the \l{Window Menu} Solution.
879
880 QWorkspace provides two built-in layout strategies for child
881 windows: cascade() and tile(). Both are slots so you can easily
882 connect menu entries to them.
883
884 \table
885 \row \o \inlineimage mdi-cascade.png
886 \o \inlineimage mdi-tile.png
887 \endtable
888
889 If you want your users to be able to work with child windows
890 larger than the visible workspace area, set the scrollBarsEnabled
891 property to true.
892
893 \sa QDockWidget, {MDI Example}
894 */
895
896
897 class QWorkspaceChild : public QWidget
898 {
899 Q_OBJECT
900
901 friend class QWorkspacePrivate;
902 friend class QWorkspace;
903 friend class QWorkspaceTitleBar;
904
905 public:
906 QWorkspaceChild(QWidget* window, QWorkspace* parent=0, Qt::WindowFlags flags = 0);
907 ~QWorkspaceChild();
908
909 void setActive(bool);
910 bool isActive() const;
911
912 void adjustToFullscreen();
913
914 QWidget* windowWidget() const;
915 QWidget* iconWidget() const;
916
917 void doResize();
918 void doMove();
919
920 QSize sizeHint() const;
921 QSize minimumSizeHint() const;
922
923 QSize baseSize() const;
924
925 int frameWidth() const;
926
927 void show();
928
929 bool isWindowOrIconVisible() const;
930
931 signals:
932 void showOperationMenu();
933 void popupOperationMenu(const QPoint&);
934
935 public slots:
936 void activate();
937 void showMinimized();
938 void showMaximized();
939 void showNormal();
940 void showShaded();
941 void internalRaise();
942 void titleBarDoubleClicked();
943
944 protected:
945 void enterEvent(QEvent *);
946 void leaveEvent(QEvent *);
947 void childEvent(QChildEvent*);
948 void resizeEvent(QResizeEvent *);
949 void moveEvent(QMoveEvent *);
950 bool eventFilter(QObject *, QEvent *);
951
952 void paintEvent(QPaintEvent *);
953 void changeEvent(QEvent *);
954
955 private:
956 void updateMask();
957
958 Q_DISABLE_COPY(QWorkspaceChild)
959
960 QWidget *childWidget;
961 QWidgetResizeHandler *widgetResizeHandler;
962 QWorkspaceTitleBar *titlebar;
963 QPointer<QWorkspaceTitleBar> iconw;
964 QSize windowSize;
965 QSize shadeRestore;
966 QSize shadeRestoreMin;
967 bool act :1;
968 bool shademode :1;
969 };
970
frameWidth() const971 int QWorkspaceChild::frameWidth() const
972 {
973 return contentsRect().left();
974 }
975
976
977
978 class QWorkspacePrivate : public QWidgetPrivate {
979 Q_DECLARE_PUBLIC(QWorkspace)
980 public:
981 QWorkspaceChild* active;
982 QList<QWorkspaceChild *> windows;
983 QList<QWorkspaceChild *> focus;
984 QList<QWidget *> icons;
985 QWorkspaceChild* maxWindow;
986 QRect maxRestore;
987 QPointer<QMDIControl> maxcontrols;
988 QPointer<QMenuBar> maxmenubar;
989 QHash<int, const char*> shortcutMap;
990
991 int px;
992 int py;
993 QWidget *becomeActive;
994 QPointer<QLabel> maxtools;
995 QString topTitle;
996
997 QMenu *popup, *toolPopup;
998 enum WSActs { RestoreAct, MoveAct, ResizeAct, MinimizeAct, MaximizeAct, CloseAct, StaysOnTopAct, ShadeAct, NCountAct };
999 QAction *actions[NCountAct];
1000
1001 QScrollBar *vbar, *hbar;
1002 QWidget *corner;
1003 int yoffset, xoffset;
1004 QBrush background;
1005
1006 void init();
1007 void insertIcon(QWidget* w);
1008 void removeIcon(QWidget* w);
1009 void place(QWidget*);
1010
1011 QWorkspaceChild* findChild(QWidget* w);
1012 void showMaximizeControls();
1013 void hideMaximizeControls();
1014 void activateWindow(QWidget* w, bool change_focus = true);
1015 void hideChild(QWorkspaceChild *c);
1016 void showWindow(QWidget* w);
1017 void maximizeWindow(QWidget* w);
1018 void minimizeWindow(QWidget* w);
1019 void normalizeWindow(QWidget* w);
1020
1021 QRect updateWorkspace();
1022
1023 private:
1024 void _q_normalizeActiveWindow();
1025 void _q_minimizeActiveWindow();
1026 void _q_showOperationMenu();
1027 void _q_popupOperationMenu(const QPoint&);
1028 void _q_operationMenuActivated(QAction *);
1029 void _q_scrollBarChanged();
1030 void _q_updateActions();
1031 bool inTitleChange;
1032 };
1033
isChildOf(QWidget * child,QWidget * parent)1034 static bool isChildOf(QWidget * child, QWidget * parent)
1035 {
1036 if (!parent || !child)
1037 return false;
1038 QWidget * w = child;
1039 while(w && w != parent)
1040 w = w->parentWidget();
1041 return w != 0;
1042 }
1043
1044 /*!
1045 Constructs a workspace with the given \a parent.
1046 */
QWorkspace(QWidget * parent)1047 QWorkspace::QWorkspace(QWidget *parent)
1048 : QWidget(*new QWorkspacePrivate, parent, 0)
1049 {
1050 Q_D(QWorkspace);
1051 d->init();
1052 }
1053
1054 #ifdef QT3_SUPPORT
1055 /*!
1056 Use one of the constructors that doesn't take the \a name
1057 argument and then use setObjectName() instead.
1058 */
QWorkspace(QWidget * parent,const char * name)1059 QWorkspace::QWorkspace(QWidget *parent, const char *name)
1060 : QWidget(*new QWorkspacePrivate, parent, 0)
1061 {
1062 Q_D(QWorkspace);
1063 setObjectName(QString::fromAscii(name));
1064 d->init();
1065 }
1066 #endif // QT3_SUPPORT
1067
1068 /*!
1069 \internal
1070 */
1071 void
init()1072 QWorkspacePrivate::init()
1073 {
1074 Q_Q(QWorkspace);
1075
1076 maxcontrols = 0;
1077 active = 0;
1078 maxWindow = 0;
1079 maxtools = 0;
1080 px = 0;
1081 py = 0;
1082 becomeActive = 0;
1083 popup = new QMenu(q);
1084 toolPopup = new QMenu(q);
1085 popup->setObjectName(QLatin1String("qt_internal_mdi_popup"));
1086 toolPopup->setObjectName(QLatin1String("qt_internal_mdi_tool_popup"));
1087
1088 actions[QWorkspacePrivate::RestoreAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarNormalButton, 0, q)),
1089 QWorkspace::tr("&Restore"), q);
1090 actions[QWorkspacePrivate::MoveAct] = new QAction(QWorkspace::tr("&Move"), q);
1091 actions[QWorkspacePrivate::ResizeAct] = new QAction(QWorkspace::tr("&Size"), q);
1092 actions[QWorkspacePrivate::MinimizeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarMinButton, 0, q)),
1093 QWorkspace::tr("Mi&nimize"), q);
1094 actions[QWorkspacePrivate::MaximizeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarMaxButton, 0, q)),
1095 QWorkspace::tr("Ma&ximize"), q);
1096 actions[QWorkspacePrivate::CloseAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, q)),
1097 QWorkspace::tr("&Close")
1098 #ifndef QT_NO_SHORTCUT
1099 +QLatin1Char('\t')+(QString)QKeySequence(Qt::CTRL+Qt::Key_F4)
1100 #endif
1101 ,q);
1102 QObject::connect(actions[QWorkspacePrivate::CloseAct], SIGNAL(triggered()), q, SLOT(closeActiveWindow()));
1103 actions[QWorkspacePrivate::StaysOnTopAct] = new QAction(QWorkspace::tr("Stay on &Top"), q);
1104 actions[QWorkspacePrivate::StaysOnTopAct]->setChecked(true);
1105 actions[QWorkspacePrivate::ShadeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarShadeButton, 0, q)),
1106 QWorkspace::tr("Sh&ade"), q);
1107
1108 QObject::connect(popup, SIGNAL(aboutToShow()), q, SLOT(_q_updateActions()));
1109 QObject::connect(popup, SIGNAL(triggered(QAction*)), q, SLOT(_q_operationMenuActivated(QAction*)));
1110 popup->addAction(actions[QWorkspacePrivate::RestoreAct]);
1111 popup->addAction(actions[QWorkspacePrivate::MoveAct]);
1112 popup->addAction(actions[QWorkspacePrivate::ResizeAct]);
1113 popup->addAction(actions[QWorkspacePrivate::MinimizeAct]);
1114 popup->addAction(actions[QWorkspacePrivate::MaximizeAct]);
1115 popup->addSeparator();
1116 popup->addAction(actions[QWorkspacePrivate::CloseAct]);
1117
1118 QObject::connect(toolPopup, SIGNAL(aboutToShow()), q, SLOT(_q_updateActions()));
1119 QObject::connect(toolPopup, SIGNAL(triggered(QAction*)), q, SLOT(_q_operationMenuActivated(QAction*)));
1120 toolPopup->addAction(actions[QWorkspacePrivate::MoveAct]);
1121 toolPopup->addAction(actions[QWorkspacePrivate::ResizeAct]);
1122 toolPopup->addAction(actions[QWorkspacePrivate::StaysOnTopAct]);
1123 toolPopup->addSeparator();
1124 toolPopup->addAction(actions[QWorkspacePrivate::ShadeAct]);
1125 toolPopup->addAction(actions[QWorkspacePrivate::CloseAct]);
1126
1127 #ifndef QT_NO_SHORTCUT
1128 // Set up shortcut bindings (id -> slot), most used first
1129 QList <QKeySequence> shortcuts = QKeySequence::keyBindings(QKeySequence::NextChild);
1130 foreach (const QKeySequence &seq, shortcuts)
1131 shortcutMap.insert(q->grabShortcut(seq), "activateNextWindow");
1132
1133 shortcuts = QKeySequence::keyBindings(QKeySequence::PreviousChild);
1134 foreach (const QKeySequence &seq, shortcuts)
1135 shortcutMap.insert(q->grabShortcut(seq), "activatePreviousWindow");
1136
1137 shortcuts = QKeySequence::keyBindings(QKeySequence::Close);
1138 foreach (const QKeySequence &seq, shortcuts)
1139 shortcutMap.insert(q->grabShortcut(seq), "closeActiveWindow");
1140
1141 shortcutMap.insert(q->grabShortcut(QKeySequence(QLatin1String("ALT+-"))), "_q_showOperationMenu");
1142 #endif // QT_NO_SHORTCUT
1143
1144 q->setBackgroundRole(QPalette::Dark);
1145 q->setAutoFillBackground(true);
1146 q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
1147
1148 hbar = vbar = 0;
1149 corner = 0;
1150 xoffset = yoffset = 0;
1151
1152 q->window()->installEventFilter(q);
1153
1154 inTitleChange = false;
1155 updateWorkspace();
1156 }
1157
1158 /*!
1159 Destroys the workspace and frees any allocated resources.
1160 */
1161
~QWorkspace()1162 QWorkspace::~QWorkspace()
1163 {
1164 }
1165
1166 /*! \reimp */
sizeHint() const1167 QSize QWorkspace::sizeHint() const
1168 {
1169 QSize s(QApplication::desktop()->size());
1170 return QSize(s.width()*2/3, s.height()*2/3);
1171 }
1172
1173
1174 #ifdef QT3_SUPPORT
1175 /*!
1176 Sets the background color to \a c.
1177 Use setBackground() instead.
1178 */
setPaletteBackgroundColor(const QColor & c)1179 void QWorkspace::setPaletteBackgroundColor(const QColor & c)
1180 {
1181 setBackground(c);
1182 }
1183
1184 /*!
1185 Sets the background pixmap to \a pm.
1186 Use setBackground() instead.
1187 */
setPaletteBackgroundPixmap(const QPixmap & pm)1188 void QWorkspace::setPaletteBackgroundPixmap(const QPixmap & pm)
1189 {
1190 setBackground(pm);
1191 }
1192 #endif // QT3_SUPPORT
1193
1194 /*!
1195 \property QWorkspace::background
1196 \brief the workspace's background
1197 */
background() const1198 QBrush QWorkspace::background() const
1199 {
1200 Q_D(const QWorkspace);
1201 if (d->background.style() == Qt::NoBrush)
1202 return palette().dark();
1203 return d->background;
1204 }
1205
setBackground(const QBrush & background)1206 void QWorkspace::setBackground(const QBrush &background)
1207 {
1208 Q_D(QWorkspace);
1209 d->background = background;
1210 setAttribute(Qt::WA_OpaquePaintEvent, background.style() == Qt::NoBrush);
1211 update();
1212 }
1213
1214 /*!
1215 Adds widget \a w as new sub window to the workspace. If \a flags
1216 are non-zero, they will override the flags set on the widget.
1217
1218 Returns the widget used for the window frame.
1219
1220 To remove the widget \a w from the workspace, simply call
1221 setParent() with the new parent (or 0 to make it a stand-alone
1222 window).
1223 */
addWindow(QWidget * w,Qt::WindowFlags flags)1224 QWidget * QWorkspace::addWindow(QWidget *w, Qt::WindowFlags flags)
1225 {
1226 Q_D(QWorkspace);
1227 if (!w)
1228 return 0;
1229
1230 w->setAutoFillBackground(true);
1231
1232 QWidgetPrivate::adjustFlags(flags);
1233
1234 #if 0
1235 bool wasMaximized = w->isMaximized();
1236 bool wasMinimized = w->isMinimized();
1237 #endif
1238 bool hasSize = w->testAttribute(Qt::WA_Resized);
1239 int x = w->x();
1240 int y = w->y();
1241 bool hasPos = w->testAttribute(Qt::WA_Moved);
1242 if (!hasSize && w->sizeHint().isValid())
1243 w->adjustSize();
1244
1245 QWorkspaceChild* child = new QWorkspaceChild(w, this, flags);
1246 child->setObjectName(QLatin1String("qt_workspacechild"));
1247 child->installEventFilter(this);
1248
1249 connect(child, SIGNAL(popupOperationMenu(QPoint)),
1250 this, SLOT(_q_popupOperationMenu(QPoint)));
1251 connect(child, SIGNAL(showOperationMenu()),
1252 this, SLOT(_q_showOperationMenu()));
1253 d->windows.append(child);
1254 if (child->isVisibleTo(this))
1255 d->focus.append(child);
1256 child->internalRaise();
1257
1258 if (!hasPos)
1259 d->place(child);
1260 if (!hasSize)
1261 child->adjustSize();
1262 if (hasPos)
1263 child->move(x, y);
1264
1265 return child;
1266
1267 #if 0
1268 if (wasMaximized)
1269 w->showMaximized();
1270 else if (wasMinimized)
1271 w->showMinimized();
1272 else if (!hasBeenHidden)
1273 d->activateWindow(w);
1274
1275 d->updateWorkspace();
1276 return child;
1277 #endif
1278 }
1279
1280 /*! \reimp */
childEvent(QChildEvent * e)1281 void QWorkspace::childEvent(QChildEvent * e)
1282 {
1283 Q_D(QWorkspace);
1284 if (e->removed()) {
1285 if (d->windows.removeAll(static_cast<QWorkspaceChild*>(e->child()))) {
1286 d->focus.removeAll(static_cast<QWorkspaceChild*>(e->child()));
1287 if (d->maxWindow == e->child())
1288 d->maxWindow = 0;
1289 d->updateWorkspace();
1290 }
1291 }
1292 }
1293
1294 /*! \reimp */
1295 #ifndef QT_NO_WHEELEVENT
wheelEvent(QWheelEvent * e)1296 void QWorkspace::wheelEvent(QWheelEvent *e)
1297 {
1298 Q_D(QWorkspace);
1299 if (!scrollBarsEnabled())
1300 return;
1301 // the scroll bars are children of the workspace, so if we receive
1302 // a wheel event we redirect to the scroll bars using a direct event
1303 // call, /not/ using sendEvent() because if the scroll bar ignores the
1304 // event QApplication::sendEvent() will propagate the event to the parent widget,
1305 // which is us, who /just/ sent it.
1306 if (d->vbar && d->vbar->isVisible() && !(e->modifiers() & Qt::AltModifier))
1307 d->vbar->event(e);
1308 else if (d->hbar && d->hbar->isVisible())
1309 d->hbar->event(e);
1310 }
1311 #endif
1312
activateWindow(QWidget * w,bool change_focus)1313 void QWorkspacePrivate::activateWindow(QWidget* w, bool change_focus)
1314 {
1315 Q_Q(QWorkspace);
1316 if (!w) {
1317 active = 0;
1318 emit q->windowActivated(0);
1319 return;
1320 }
1321 if (!q->isVisible()) {
1322 becomeActive = w;
1323 return;
1324 }
1325
1326 if (active && active->windowWidget() == w) {
1327 if (!isChildOf(q->focusWidget(), w)) // child window does not have focus
1328 active->setActive(true);
1329 return;
1330 }
1331
1332 active = 0;
1333 // First deactivate all other workspace clients
1334 QList<QWorkspaceChild *>::Iterator it(windows.begin());
1335 while (it != windows.end()) {
1336 QWorkspaceChild* c = *it;
1337 ++it;
1338 if (c->windowWidget() == w)
1339 active = c;
1340 else
1341 c->setActive(false);
1342 }
1343
1344 if (!active)
1345 return;
1346
1347 // Then activate the new one, so the focus is stored correctly
1348 active->setActive(true);
1349
1350 if (!active)
1351 return;
1352
1353 if (maxWindow && maxWindow != active && active->windowWidget() &&
1354 (active->windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint))
1355 active->showMaximized();
1356
1357 active->internalRaise();
1358
1359 if (change_focus) {
1360 int from = focus.indexOf(active);
1361 if (from >= 0)
1362 focus.move(from, focus.size() - 1);
1363 }
1364
1365 updateWorkspace();
1366 emit q->windowActivated(w);
1367 }
1368
1369
1370 /*!
1371 Returns a pointer to the widget corresponding to the active child
1372 window, or 0 if no window is active.
1373
1374 \sa setActiveWindow()
1375 */
activeWindow() const1376 QWidget* QWorkspace::activeWindow() const
1377 {
1378 Q_D(const QWorkspace);
1379 return d->active? d->active->windowWidget() : 0;
1380 }
1381
1382 /*!
1383 Makes the child window that contains \a w the active child window.
1384
1385 \sa activeWindow()
1386 */
setActiveWindow(QWidget * w)1387 void QWorkspace::setActiveWindow(QWidget *w)
1388 {
1389 Q_D(QWorkspace);
1390 d->activateWindow(w, true);
1391 if (w && w->isMinimized())
1392 w->setWindowState(w->windowState() & ~Qt::WindowMinimized);
1393 }
1394
place(QWidget * w)1395 void QWorkspacePrivate::place(QWidget *w)
1396 {
1397 Q_Q(QWorkspace);
1398
1399 QList<QWidget *> widgets;
1400 for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it)
1401 if (*it != w)
1402 widgets.append(*it);
1403
1404 int overlap, minOverlap = 0;
1405 int possible;
1406
1407 QRect r1(0, 0, 0, 0);
1408 QRect r2(0, 0, 0, 0);
1409 QRect maxRect = q->rect();
1410 int x = maxRect.left(), y = maxRect.top();
1411 QPoint wpos(maxRect.left(), maxRect.top());
1412
1413 bool firstPass = true;
1414
1415 do {
1416 if (y + w->height() > maxRect.bottom()) {
1417 overlap = -1;
1418 } else if(x + w->width() > maxRect.right()) {
1419 overlap = -2;
1420 } else {
1421 overlap = 0;
1422
1423 r1.setRect(x, y, w->width(), w->height());
1424
1425 QWidget *l;
1426 QList<QWidget *>::Iterator it(widgets.begin());
1427 while (it != widgets.end()) {
1428 l = *it;
1429 ++it;
1430
1431 if (maxWindow == l)
1432 r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
1433 else
1434 r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
1435 QRect(l->x(), l->y(), l->width(), l->height()));
1436
1437 if (r2.intersects(r1)) {
1438 r2.setCoords(qMax(r1.left(), r2.left()),
1439 qMax(r1.top(), r2.top()),
1440 qMin(r1.right(), r2.right()),
1441 qMin(r1.bottom(), r2.bottom())
1442 );
1443
1444 overlap += (r2.right() - r2.left()) *
1445 (r2.bottom() - r2.top());
1446 }
1447 }
1448 }
1449
1450 if (overlap == 0) {
1451 wpos = QPoint(x, y);
1452 break;
1453 }
1454
1455 if (firstPass) {
1456 firstPass = false;
1457 minOverlap = overlap;
1458 } else if (overlap >= 0 && overlap < minOverlap) {
1459 minOverlap = overlap;
1460 wpos = QPoint(x, y);
1461 }
1462
1463 if (overlap > 0) {
1464 possible = maxRect.right();
1465 if (possible - w->width() > x) possible -= w->width();
1466
1467 QWidget *l;
1468 QList<QWidget *>::Iterator it(widgets.begin());
1469 while (it != widgets.end()) {
1470 l = *it;
1471 ++it;
1472 if (maxWindow == l)
1473 r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
1474 else
1475 r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
1476 QRect(l->x(), l->y(), l->width(), l->height()));
1477
1478 if((y < r2.bottom()) && (r2.top() < w->height() + y)) {
1479 if(r2.right() > x)
1480 possible = possible < r2.right() ?
1481 possible : r2.right();
1482
1483 if(r2.left() - w->width() > x)
1484 possible = possible < r2.left() - w->width() ?
1485 possible : r2.left() - w->width();
1486 }
1487 }
1488
1489 x = possible;
1490 } else if (overlap == -2) {
1491 x = maxRect.left();
1492 possible = maxRect.bottom();
1493
1494 if (possible - w->height() > y) possible -= w->height();
1495
1496 QWidget *l;
1497 QList<QWidget *>::Iterator it(widgets.begin());
1498 while (it != widgets.end()) {
1499 l = *it;
1500 ++it;
1501 if (maxWindow == l)
1502 r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
1503 else
1504 r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
1505 QRect(l->x(), l->y(), l->width(), l->height()));
1506
1507 if(r2.bottom() > y)
1508 possible = possible < r2.bottom() ?
1509 possible : r2.bottom();
1510
1511 if(r2.top() - w->height() > y)
1512 possible = possible < r2.top() - w->height() ?
1513 possible : r2.top() - w->height();
1514 }
1515
1516 y = possible;
1517 }
1518 }
1519 while(overlap != 0 && overlap != -1);
1520
1521 QRect resultRect = w->geometry();
1522 resultRect.moveTo(wpos);
1523 w->setGeometry(QStyle::visualRect(q->layoutDirection(), maxRect, resultRect));
1524 updateWorkspace();
1525 }
1526
1527
insertIcon(QWidget * w)1528 void QWorkspacePrivate::insertIcon(QWidget* w)
1529 {
1530 Q_Q(QWorkspace);
1531 if (!w || icons.contains(w))
1532 return;
1533 icons.append(w);
1534 if (w->parentWidget() != q) {
1535 w->setParent(q, 0);
1536 w->move(0,0);
1537 }
1538 QRect cr = updateWorkspace();
1539 int x = 0;
1540 int y = cr.height() - w->height();
1541
1542 QList<QWidget *>::Iterator it(icons.begin());
1543 while (it != icons.end()) {
1544 QWidget* i = *it;
1545 ++it;
1546 if (x > 0 && x + i->width() > cr.width()){
1547 x = 0;
1548 y -= i->height();
1549 }
1550
1551 if (i != w &&
1552 i->geometry().intersects(QRect(x, y, w->width(), w->height())))
1553 x += i->width();
1554 }
1555 w->move(x, y);
1556
1557 if (q->isVisibleTo(q->parentWidget())) {
1558 w->show();
1559 w->lower();
1560 }
1561 updateWorkspace();
1562 }
1563
1564
removeIcon(QWidget * w)1565 void QWorkspacePrivate::removeIcon(QWidget* w)
1566 {
1567 if (icons.removeAll(w))
1568 w->hide();
1569 }
1570
1571
1572 /*! \reimp */
resizeEvent(QResizeEvent *)1573 void QWorkspace::resizeEvent(QResizeEvent *)
1574 {
1575 Q_D(QWorkspace);
1576 if (d->maxWindow) {
1577 d->maxWindow->adjustToFullscreen();
1578 if (d->maxWindow->windowWidget())
1579 d->maxWindow->windowWidget()->overrideWindowState(Qt::WindowMaximized);
1580 }
1581 d->updateWorkspace();
1582 }
1583
1584 /*! \reimp */
showEvent(QShowEvent * e)1585 void QWorkspace::showEvent(QShowEvent *e)
1586 {
1587 Q_D(QWorkspace);
1588 if (d->maxWindow)
1589 d->showMaximizeControls();
1590 QWidget::showEvent(e);
1591 if (d->becomeActive) {
1592 d->activateWindow(d->becomeActive);
1593 d->becomeActive = 0;
1594 } else if (d->windows.count() > 0 && !d->active) {
1595 d->activateWindow(d->windows.first()->windowWidget());
1596 }
1597
1598 // // force a frame repaint - this is a workaround for what seems to be a bug
1599 // // introduced when changing the QWidget::show() implementation. Might be
1600 // // a windows bug as well though.
1601 // for (int i = 0; i < d->windows.count(); ++i) {
1602 // QWorkspaceChild* c = d->windows.at(i);
1603 // c->update(c->rect());
1604 // }
1605
1606 d->updateWorkspace();
1607 }
1608
1609 /*! \reimp */
hideEvent(QHideEvent *)1610 void QWorkspace::hideEvent(QHideEvent *)
1611 {
1612 Q_D(QWorkspace);
1613 if (!isVisible())
1614 d->hideMaximizeControls();
1615 }
1616
1617 /*! \reimp */
paintEvent(QPaintEvent *)1618 void QWorkspace::paintEvent(QPaintEvent *)
1619 {
1620 Q_D(QWorkspace);
1621
1622 if (d->background.style() != Qt::NoBrush) {
1623 QPainter p(this);
1624 p.fillRect(0, 0, width(), height(), d->background);
1625 }
1626 }
1627
minimizeWindow(QWidget * w)1628 void QWorkspacePrivate::minimizeWindow(QWidget* w)
1629 {
1630 QWorkspaceChild* c = findChild(w);
1631
1632 if (!w || !(w->windowFlags() & Qt::WindowMinimizeButtonHint))
1633 return;
1634
1635 if (c) {
1636 bool wasMax = false;
1637 if (c == maxWindow) {
1638 wasMax = true;
1639 maxWindow = 0;
1640 hideMaximizeControls();
1641 for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it) {
1642 QWorkspaceChild* c = *it;
1643 if (c->titlebar)
1644 c->titlebar->setMovable(true);
1645 c->widgetResizeHandler->setActive(true);
1646 }
1647 }
1648 c->hide();
1649 if (wasMax)
1650 c->setGeometry(maxRestore);
1651 if (!focus.contains(c))
1652 focus.append(c);
1653 insertIcon(c->iconWidget());
1654
1655 if (!maxWindow)
1656 activateWindow(w);
1657
1658 updateWorkspace();
1659
1660 w->overrideWindowState(Qt::WindowMinimized);
1661 c->overrideWindowState(Qt::WindowMinimized);
1662 }
1663 }
1664
normalizeWindow(QWidget * w)1665 void QWorkspacePrivate::normalizeWindow(QWidget* w)
1666 {
1667 Q_Q(QWorkspace);
1668 QWorkspaceChild* c = findChild(w);
1669 if (!w)
1670 return;
1671 if (c) {
1672 w->overrideWindowState(Qt::WindowNoState);
1673 hideMaximizeControls();
1674 if (!maxmenubar || q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q) || !maxWindow) {
1675 if (w->minimumSize() != w->maximumSize())
1676 c->widgetResizeHandler->setActive(true);
1677 if (c->titlebar)
1678 c->titlebar->setMovable(true);
1679 }
1680 w->overrideWindowState(Qt::WindowNoState);
1681 c->overrideWindowState(Qt::WindowNoState);
1682
1683 if (c == maxWindow) {
1684 c->setGeometry(maxRestore);
1685 maxWindow = 0;
1686 } else {
1687 if (c->iconw)
1688 removeIcon(c->iconw->parentWidget());
1689 c->show();
1690 }
1691
1692 hideMaximizeControls();
1693 for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it) {
1694 QWorkspaceChild* c = *it;
1695 if (c->titlebar)
1696 c->titlebar->setMovable(true);
1697 if (c->childWidget && c->childWidget->minimumSize() != c->childWidget->maximumSize())
1698 c->widgetResizeHandler->setActive(true);
1699 }
1700 activateWindow(w, true);
1701 updateWorkspace();
1702 }
1703 }
1704
maximizeWindow(QWidget * w)1705 void QWorkspacePrivate::maximizeWindow(QWidget* w)
1706 {
1707 Q_Q(QWorkspace);
1708 QWorkspaceChild* c = findChild(w);
1709
1710 if (!w || !(w->windowFlags() & Qt::WindowMaximizeButtonHint))
1711 return;
1712
1713 if (!c || c == maxWindow)
1714 return;
1715
1716 bool updatesEnabled = q->updatesEnabled();
1717 q->setUpdatesEnabled(false);
1718
1719 if (c->iconw && icons.contains(c->iconw->parentWidget()))
1720 normalizeWindow(w);
1721 QRect r(c->geometry());
1722 QWorkspaceChild *oldMaxWindow = maxWindow;
1723 maxWindow = c;
1724
1725 showMaximizeControls();
1726
1727 c->adjustToFullscreen();
1728 c->show();
1729 c->internalRaise();
1730 if (oldMaxWindow != c) {
1731 if (oldMaxWindow) {
1732 oldMaxWindow->setGeometry(maxRestore);
1733 oldMaxWindow->overrideWindowState(Qt::WindowNoState);
1734 if(oldMaxWindow->windowWidget())
1735 oldMaxWindow->windowWidget()->overrideWindowState(Qt::WindowNoState);
1736 }
1737 maxRestore = r;
1738 }
1739
1740 activateWindow(w);
1741
1742 if(!maxmenubar || q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
1743 if (!active && becomeActive) {
1744 active = (QWorkspaceChild*)becomeActive->parentWidget();
1745 active->setActive(true);
1746 becomeActive = 0;
1747 emit q->windowActivated(active->windowWidget());
1748 }
1749 c->widgetResizeHandler->setActive(false);
1750 if (c->titlebar)
1751 c->titlebar->setMovable(false);
1752 }
1753 updateWorkspace();
1754
1755 w->overrideWindowState(Qt::WindowMaximized);
1756 c->overrideWindowState(Qt::WindowMaximized);
1757 q->setUpdatesEnabled(updatesEnabled);
1758 }
1759
showWindow(QWidget * w)1760 void QWorkspacePrivate::showWindow(QWidget* w)
1761 {
1762 if (w->isMinimized() && (w->windowFlags() & Qt::WindowMinimizeButtonHint))
1763 minimizeWindow(w);
1764 else if ((maxWindow || w->isMaximized()) && w->windowFlags() & Qt::WindowMaximizeButtonHint)
1765 maximizeWindow(w);
1766 else if (w->windowFlags() & Qt::WindowMaximizeButtonHint)
1767 normalizeWindow(w);
1768 else
1769 w->parentWidget()->show();
1770 if (maxWindow)
1771 maxWindow->internalRaise();
1772 updateWorkspace();
1773 }
1774
1775
findChild(QWidget * w)1776 QWorkspaceChild* QWorkspacePrivate::findChild(QWidget* w)
1777 {
1778 QList<QWorkspaceChild *>::Iterator it(windows.begin());
1779 while (it != windows.end()) {
1780 QWorkspaceChild* c = *it;
1781 ++it;
1782 if (c->windowWidget() == w)
1783 return c;
1784 }
1785 return 0;
1786 }
1787
1788 /*!
1789 Returns a list of all visible or minimized child windows. If \a
1790 order is CreationOrder (the default), the windows are listed in
1791 the order in which they were inserted into the workspace. If \a
1792 order is StackingOrder, the windows are listed in their stacking
1793 order, with the topmost window as the last item in the list.
1794 */
windowList(WindowOrder order) const1795 QWidgetList QWorkspace::windowList(WindowOrder order) const
1796 {
1797 Q_D(const QWorkspace);
1798 QWidgetList windows;
1799 if (order == StackingOrder) {
1800 QObjectList cl = children();
1801 for (int i = 0; i < cl.size(); ++i) {
1802 QWorkspaceChild *c = qobject_cast<QWorkspaceChild*>(cl.at(i));
1803 if (c && c->isWindowOrIconVisible())
1804 windows.append(c->windowWidget());
1805 }
1806 } else {
1807 QList<QWorkspaceChild *>::ConstIterator it(d->windows.begin());
1808 while (it != d->windows.end()) {
1809 QWorkspaceChild* c = *it;
1810 ++it;
1811 if (c && c->isWindowOrIconVisible())
1812 windows.append(c->windowWidget());
1813 }
1814 }
1815 return windows;
1816 }
1817
1818
1819 /*! \reimp */
event(QEvent * e)1820 bool QWorkspace::event(QEvent *e)
1821 {
1822 #ifndef QT_NO_SHORTCUT
1823 Q_D(QWorkspace);
1824 if (e->type() == QEvent::Shortcut) {
1825 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
1826 const char *theSlot = d->shortcutMap.value(se->shortcutId(), 0);
1827 if (theSlot)
1828 QMetaObject::invokeMethod(this, theSlot);
1829 } else
1830 #endif
1831 if (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut){
1832 return true;
1833 }
1834 return QWidget::event(e);
1835 }
1836
1837 /*! \reimp */
eventFilter(QObject * o,QEvent * e)1838 bool QWorkspace::eventFilter(QObject *o, QEvent * e)
1839 {
1840 Q_D(QWorkspace);
1841 static QElapsedTimer* t = 0;
1842 static QWorkspace* tc = 0;
1843 if (o == d->maxtools) {
1844 switch (e->type()) {
1845 case QEvent::MouseButtonPress:
1846 {
1847 QMenuBar* b = (QMenuBar*)o->parent();
1848 if (!t)
1849 t = new QElapsedTimer;
1850 if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
1851 if (isRightToLeft()) {
1852 QPoint p = b->mapToGlobal(QPoint(b->x() + b->width(), b->y() + b->height()));
1853 p.rx() -= d->popup->sizeHint().width();
1854 d->_q_popupOperationMenu(p);
1855 } else {
1856 d->_q_popupOperationMenu(b->mapToGlobal(QPoint(b->x(), b->y() + b->height())));
1857 }
1858 t->start();
1859 tc = this;
1860 } else {
1861 tc = 0;
1862 closeActiveWindow();
1863 }
1864 return true;
1865 }
1866 default:
1867 break;
1868 }
1869 return QWidget::eventFilter(o, e);
1870 }
1871 switch (e->type()) {
1872 case QEvent::HideToParent:
1873 break;
1874 case QEvent::ShowToParent:
1875 if (QWorkspaceChild *c = qobject_cast<QWorkspaceChild*>(o))
1876 if (!d->focus.contains(c))
1877 d->focus.append(c);
1878 d->updateWorkspace();
1879 break;
1880 case QEvent::WindowTitleChange:
1881 if (!d->inTitleChange) {
1882 if (o == window())
1883 d->topTitle = window()->windowTitle();
1884 if (d->maxWindow && d->maxWindow->windowWidget() && d->topTitle.size()) {
1885 d->inTitleChange = true;
1886 window()->setWindowTitle(tr("%1 - [%2]")
1887 .arg(d->topTitle).arg(d->maxWindow->windowWidget()->windowTitle()));
1888 d->inTitleChange = false;
1889 }
1890 }
1891 break;
1892
1893 case QEvent::ModifiedChange:
1894 if (o == d->maxWindow)
1895 window()->setWindowModified(d->maxWindow->isWindowModified());
1896 break;
1897
1898 case QEvent::Close:
1899 if (o == window())
1900 {
1901 QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
1902 while (it != d->windows.end()) {
1903 QWorkspaceChild* c = *it;
1904 ++it;
1905 if (c->shademode)
1906 c->showShaded();
1907 }
1908 } else if (qobject_cast<QWorkspaceChild*>(o)) {
1909 d->popup->hide();
1910 }
1911 d->updateWorkspace();
1912 break;
1913 default:
1914 break;
1915 }
1916 return QWidget::eventFilter(o, e);
1917 }
1918
findMenuBar(QWidget * w)1919 static QMenuBar *findMenuBar(QWidget *w)
1920 {
1921 // don't search recursively to avoid finding a menu bar of a
1922 // mainwindow that happens to be a workspace window (like
1923 // a mainwindow in designer)
1924 QList<QObject *> children = w->children();
1925 for (int i = 0; i < children.count(); ++i) {
1926 QMenuBar *bar = qobject_cast<QMenuBar *>(children.at(i));
1927 if (bar)
1928 return bar;
1929 }
1930 return 0;
1931 }
1932
showMaximizeControls()1933 void QWorkspacePrivate::showMaximizeControls()
1934 {
1935 Q_Q(QWorkspace);
1936 Q_ASSERT(maxWindow);
1937
1938 // merge windowtitle and modified state
1939 if (!topTitle.size())
1940 topTitle = q->window()->windowTitle();
1941
1942 if (maxWindow->windowWidget()) {
1943 QString docTitle = maxWindow->windowWidget()->windowTitle();
1944 if (topTitle.size() && docTitle.size()) {
1945 inTitleChange = true;
1946 q->window()->setWindowTitle(QWorkspace::tr("%1 - [%2]").arg(topTitle).arg(docTitle));
1947 inTitleChange = false;
1948 }
1949 q->window()->setWindowModified(maxWindow->windowWidget()->isWindowModified());
1950 }
1951
1952 if (!q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
1953 QMenuBar* b = 0;
1954
1955 // Do a breadth-first search first on every parent,
1956 QWidget* w = q->parentWidget();
1957 while (w) {
1958 b = findMenuBar(w);
1959 if (b)
1960 break;
1961 w = w->parentWidget();
1962 }
1963
1964 // last attempt.
1965 if (!b)
1966 b = findMenuBar(q->window());
1967
1968 if (!b)
1969 return;
1970
1971 if (!maxcontrols) {
1972 maxmenubar = b;
1973 maxcontrols = new QMDIControl(b);
1974 QObject::connect(maxcontrols, SIGNAL(_q_minimize()),
1975 q, SLOT(_q_minimizeActiveWindow()));
1976 QObject::connect(maxcontrols, SIGNAL(_q_restore()),
1977 q, SLOT(_q_normalizeActiveWindow()));
1978 QObject::connect(maxcontrols, SIGNAL(_q_close()),
1979 q, SLOT(closeActiveWindow()));
1980 }
1981
1982 b->setCornerWidget(maxcontrols);
1983 if (b->isVisible())
1984 maxcontrols->show();
1985 if (!active && becomeActive) {
1986 active = (QWorkspaceChild*)becomeActive->parentWidget();
1987 active->setActive(true);
1988 becomeActive = 0;
1989 emit q->windowActivated(active->windowWidget());
1990 }
1991 if (active) {
1992 if (!maxtools) {
1993 maxtools = new QLabel(q->window());
1994 maxtools->setObjectName(QLatin1String("qt_maxtools"));
1995 maxtools->installEventFilter(q);
1996 }
1997 if (active->windowWidget() && !active->windowWidget()->windowIcon().isNull()) {
1998 QIcon icon = active->windowWidget()->windowIcon();
1999 int iconSize = maxcontrols->size().height();
2000 maxtools->setPixmap(icon.pixmap(QSize(iconSize, iconSize)));
2001 } else {
2002 QPixmap pm = q->style()->standardPixmap(QStyle::SP_TitleBarMenuButton, 0, q);
2003 if (pm.isNull()) {
2004 pm = QPixmap(14,14);
2005 pm.fill(Qt::black);
2006 }
2007 maxtools->setPixmap(pm);
2008 }
2009 b->setCornerWidget(maxtools, Qt::TopLeftCorner);
2010 if (b->isVisible())
2011 maxtools->show();
2012 }
2013 }
2014 }
2015
2016
hideMaximizeControls()2017 void QWorkspacePrivate::hideMaximizeControls()
2018 {
2019 Q_Q(QWorkspace);
2020 if (maxmenubar && !q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
2021 if (maxmenubar) {
2022 maxmenubar->setCornerWidget(0, Qt::TopLeftCorner);
2023 maxmenubar->setCornerWidget(0, Qt::TopRightCorner);
2024 }
2025 if (maxcontrols) {
2026 maxcontrols->deleteLater();
2027 maxcontrols = 0;
2028 }
2029 if (maxtools) {
2030 maxtools->deleteLater();
2031 maxtools = 0;
2032 }
2033 }
2034
2035 //unmerge the title bar/modification state
2036 if (topTitle.size()) {
2037 inTitleChange = true;
2038 q->window()->setWindowTitle(topTitle);
2039 inTitleChange = false;
2040 }
2041 q->window()->setWindowModified(false);
2042 }
2043
2044 /*!
2045 Closes the child window that is currently active.
2046
2047 \sa closeAllWindows()
2048 */
closeActiveWindow()2049 void QWorkspace::closeActiveWindow()
2050 {
2051 Q_D(QWorkspace);
2052 if (d->maxWindow && d->maxWindow->windowWidget())
2053 d->maxWindow->windowWidget()->close();
2054 else if (d->active && d->active->windowWidget())
2055 d->active->windowWidget()->close();
2056 d->updateWorkspace();
2057 }
2058
2059 /*!
2060 Closes all child windows.
2061
2062 If any child window fails to accept the close event, the remaining windows
2063 will remain open.
2064
2065 \sa closeActiveWindow()
2066 */
closeAllWindows()2067 void QWorkspace::closeAllWindows()
2068 {
2069 Q_D(QWorkspace);
2070 bool did_close = true;
2071 QList<QWorkspaceChild *>::const_iterator it = d->windows.constBegin();
2072 while (it != d->windows.constEnd() && did_close) {
2073 QWorkspaceChild *c = *it;
2074 ++it;
2075 if (c->windowWidget() && !c->windowWidget()->isHidden())
2076 did_close = c->windowWidget()->close();
2077 }
2078 }
2079
_q_normalizeActiveWindow()2080 void QWorkspacePrivate::_q_normalizeActiveWindow()
2081 {
2082 if (maxWindow)
2083 maxWindow->showNormal();
2084 else if (active)
2085 active->showNormal();
2086 }
2087
_q_minimizeActiveWindow()2088 void QWorkspacePrivate::_q_minimizeActiveWindow()
2089 {
2090 if (maxWindow)
2091 maxWindow->showMinimized();
2092 else if (active)
2093 active->showMinimized();
2094 }
2095
_q_showOperationMenu()2096 void QWorkspacePrivate::_q_showOperationMenu()
2097 {
2098 Q_Q(QWorkspace);
2099 if (!active || !active->windowWidget())
2100 return;
2101 Q_ASSERT((active->windowWidget()->windowFlags() & Qt::WindowSystemMenuHint));
2102 QPoint p;
2103 QMenu *popup = (active->titlebar && active->titlebar->isTool()) ? toolPopup : this->popup;
2104 if (q->isRightToLeft()) {
2105 p = QPoint(active->windowWidget()->mapToGlobal(QPoint(active->windowWidget()->width(),0)));
2106 p.rx() -= popup->sizeHint().width();
2107 } else {
2108 p = QPoint(active->windowWidget()->mapToGlobal(QPoint(0,0)));
2109 }
2110 if (!active->isVisible()) {
2111 p = active->iconWidget()->mapToGlobal(QPoint(0,0));
2112 p.ry() -= popup->sizeHint().height();
2113 }
2114 _q_popupOperationMenu(p);
2115 }
2116
_q_popupOperationMenu(const QPoint & p)2117 void QWorkspacePrivate::_q_popupOperationMenu(const QPoint& p)
2118 {
2119 if (!active || !active->windowWidget() || !(active->windowWidget()->windowFlags() & Qt::WindowSystemMenuHint))
2120 return;
2121 if (active->titlebar && active->titlebar->isTool())
2122 toolPopup->popup(p);
2123 else
2124 popup->popup(p);
2125 }
2126
_q_updateActions()2127 void QWorkspacePrivate::_q_updateActions()
2128 {
2129 Q_Q(QWorkspace);
2130 for (int i = 1; i < NCountAct-1; i++) {
2131 bool enable = active != 0;
2132 actions[i]->setEnabled(enable);
2133 }
2134
2135 if (!active || !active->windowWidget())
2136 return;
2137
2138 QWidget *windowWidget = active->windowWidget();
2139 bool canResize = windowWidget->maximumSize() != windowWidget->minimumSize();
2140 actions[QWorkspacePrivate::ResizeAct]->setEnabled(canResize);
2141 actions[QWorkspacePrivate::MinimizeAct]->setEnabled((windowWidget->windowFlags() & Qt::WindowMinimizeButtonHint));
2142 actions[QWorkspacePrivate::MaximizeAct]->setEnabled((windowWidget->windowFlags() & Qt::WindowMaximizeButtonHint) && canResize);
2143
2144 if (active == maxWindow) {
2145 actions[QWorkspacePrivate::MoveAct]->setEnabled(false);
2146 actions[QWorkspacePrivate::ResizeAct]->setEnabled(false);
2147 actions[QWorkspacePrivate::MaximizeAct]->setEnabled(false);
2148 actions[QWorkspacePrivate::RestoreAct]->setEnabled(true);
2149 } else if (active->isVisible()){
2150 actions[QWorkspacePrivate::RestoreAct]->setEnabled(false);
2151 } else {
2152 actions[QWorkspacePrivate::MoveAct]->setEnabled(false);
2153 actions[QWorkspacePrivate::ResizeAct]->setEnabled(false);
2154 actions[QWorkspacePrivate::MinimizeAct]->setEnabled(false);
2155 actions[QWorkspacePrivate::RestoreAct]->setEnabled(true);
2156 }
2157 if (active->shademode) {
2158 actions[QWorkspacePrivate::ShadeAct]->setIcon(
2159 QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarUnshadeButton, 0, q)));
2160 actions[QWorkspacePrivate::ShadeAct]->setText(QWorkspace::tr("&Unshade"));
2161 } else {
2162 actions[QWorkspacePrivate::ShadeAct]->setIcon(
2163 QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarShadeButton, 0, q)));
2164 actions[QWorkspacePrivate::ShadeAct]->setText(QWorkspace::tr("Sh&ade"));
2165 }
2166 actions[QWorkspacePrivate::StaysOnTopAct]->setEnabled(!active->shademode && canResize);
2167 actions[QWorkspacePrivate::StaysOnTopAct]->setChecked(
2168 (active->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint));
2169 }
2170
_q_operationMenuActivated(QAction * action)2171 void QWorkspacePrivate::_q_operationMenuActivated(QAction *action)
2172 {
2173 if (!active)
2174 return;
2175 if(action == actions[QWorkspacePrivate::RestoreAct]) {
2176 active->showNormal();
2177 } else if(action == actions[QWorkspacePrivate::MoveAct]) {
2178 active->doMove();
2179 } else if(action == actions[QWorkspacePrivate::ResizeAct]) {
2180 if (active->shademode)
2181 active->showShaded();
2182 active->doResize();
2183 } else if(action == actions[QWorkspacePrivate::MinimizeAct]) {
2184 active->showMinimized();
2185 } else if(action == actions[QWorkspacePrivate::MaximizeAct]) {
2186 active->showMaximized();
2187 } else if(action == actions[QWorkspacePrivate::ShadeAct]) {
2188 active->showShaded();
2189 } else if(action == actions[QWorkspacePrivate::StaysOnTopAct]) {
2190 if(QWidget* w = active->windowWidget()) {
2191 if ((w->windowFlags() & Qt::WindowStaysOnTopHint)) {
2192 w->overrideWindowFlags(w->windowFlags() & ~Qt::WindowStaysOnTopHint);
2193 } else {
2194 w->overrideWindowFlags(w->windowFlags() | Qt::WindowStaysOnTopHint);
2195 w->parentWidget()->raise();
2196 }
2197 }
2198 }
2199 }
2200
2201
hideChild(QWorkspaceChild * c)2202 void QWorkspacePrivate::hideChild(QWorkspaceChild *c)
2203 {
2204 Q_Q(QWorkspace);
2205
2206 // bool updatesEnabled = q->updatesEnabled();
2207 // q->setUpdatesEnabled(false);
2208 focus.removeAll(c);
2209 QRect restore;
2210 if (maxWindow == c)
2211 restore = maxRestore;
2212 if (active == c) {
2213 q->setFocus();
2214 q->activatePreviousWindow();
2215 }
2216 if (active == c)
2217 activateWindow(0);
2218 if (maxWindow == c) {
2219 hideMaximizeControls();
2220 maxWindow = 0;
2221 }
2222 c->hide();
2223 if (!restore.isEmpty())
2224 c->setGeometry(restore);
2225 // q->setUpdatesEnabled(updatesEnabled);
2226 }
2227
2228 /*!
2229 Gives the input focus to the next window in the list of child
2230 windows.
2231
2232 \sa activatePreviousWindow()
2233 */
activateNextWindow()2234 void QWorkspace::activateNextWindow()
2235 {
2236 Q_D(QWorkspace);
2237
2238 if (d->focus.isEmpty())
2239 return;
2240 if (!d->active) {
2241 if (d->focus.first())
2242 d->activateWindow(d->focus.first()->windowWidget(), false);
2243 return;
2244 }
2245
2246 int a = d->focus.indexOf(d->active) + 1;
2247
2248 a = a % d->focus.count();
2249
2250 if (d->focus.at(a))
2251 d->activateWindow(d->focus.at(a)->windowWidget(), false);
2252 else
2253 d->activateWindow(0);
2254 }
2255
2256 /*!
2257 Gives the input focus to the previous window in the list of child
2258 windows.
2259
2260 \sa activateNextWindow()
2261 */
activatePreviousWindow()2262 void QWorkspace::activatePreviousWindow()
2263 {
2264 Q_D(QWorkspace);
2265
2266 if (d->focus.isEmpty())
2267 return;
2268 if (!d->active) {
2269 if (d->focus.last())
2270 d->activateWindow(d->focus.first()->windowWidget(), false);
2271 else
2272 d->activateWindow(0);
2273 return;
2274 }
2275
2276 int a = d->focus.indexOf(d->active) - 1;
2277 if (a < 0)
2278 a = d->focus.count()-1;
2279
2280 if (d->focus.at(a))
2281 d->activateWindow(d->focus.at(a)->windowWidget(), false);
2282 else
2283 d->activateWindow(0);
2284 }
2285
2286
2287 /*!
2288 \fn void QWorkspace::windowActivated(QWidget* w)
2289
2290 This signal is emitted when the child window \a w becomes active.
2291 Note that \a w can be 0, and that more than one signal may be
2292 emitted for a single activation event.
2293
2294 \sa activeWindow(), windowList()
2295 */
2296
2297 /*!
2298 Arranges all the child windows in a cascade pattern.
2299
2300 \sa tile(), arrangeIcons()
2301 */
cascade()2302 void QWorkspace::cascade()
2303 {
2304 Q_D(QWorkspace);
2305 blockSignals(true);
2306 if (d->maxWindow)
2307 d->maxWindow->showNormal();
2308
2309 if (d->vbar) {
2310 d->vbar->blockSignals(true);
2311 d->vbar->setValue(0);
2312 d->vbar->blockSignals(false);
2313 d->hbar->blockSignals(true);
2314 d->hbar->setValue(0);
2315 d->hbar->blockSignals(false);
2316 d->_q_scrollBarChanged();
2317 }
2318
2319 const int xoffset = 13;
2320 const int yoffset = 20;
2321
2322 // make a list of all relevant mdi clients
2323 QList<QWorkspaceChild *> widgets;
2324 QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
2325 QWorkspaceChild* wc = 0;
2326
2327 for (it = d->focus.begin(); it != d->focus.end(); ++it) {
2328 wc = *it;
2329 if (wc->windowWidget()->isVisibleTo(this) && !(wc->titlebar && wc->titlebar->isTool()))
2330 widgets.append(wc);
2331 }
2332
2333 int x = 0;
2334 int y = 0;
2335
2336 it = widgets.begin();
2337 while (it != widgets.end()) {
2338 QWorkspaceChild *child = *it;
2339 ++it;
2340
2341 QSize prefSize = child->windowWidget()->sizeHint().expandedTo(qSmartMinSize(child->windowWidget()));
2342 if (!prefSize.isValid())
2343 prefSize = child->windowWidget()->size();
2344 prefSize = prefSize.expandedTo(qSmartMinSize(child->windowWidget()));
2345 if (prefSize.isValid())
2346 prefSize += QSize(child->baseSize().width(), child->baseSize().height());
2347
2348 int w = prefSize.width();
2349 int h = prefSize.height();
2350
2351 child->showNormal();
2352 if (y + h > height())
2353 y = 0;
2354 if (x + w > width())
2355 x = 0;
2356 child->setGeometry(x, y, w, h);
2357 x += xoffset;
2358 y += yoffset;
2359 child->internalRaise();
2360 }
2361 d->updateWorkspace();
2362 blockSignals(false);
2363 }
2364
2365 /*!
2366 Arranges all child windows in a tile pattern.
2367
2368 \sa cascade(), arrangeIcons()
2369 */
tile()2370 void QWorkspace::tile()
2371 {
2372 Q_D(QWorkspace);
2373 blockSignals(true);
2374 QWidget *oldActive = d->active ? d->active->windowWidget() : 0;
2375 if (d->maxWindow)
2376 d->maxWindow->showNormal();
2377
2378 if (d->vbar) {
2379 d->vbar->blockSignals(true);
2380 d->vbar->setValue(0);
2381 d->vbar->blockSignals(false);
2382 d->hbar->blockSignals(true);
2383 d->hbar->setValue(0);
2384 d->hbar->blockSignals(false);
2385 d->_q_scrollBarChanged();
2386 }
2387
2388 int rows = 1;
2389 int cols = 1;
2390 int n = 0;
2391 QWorkspaceChild* c;
2392
2393 QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
2394 while (it != d->windows.end()) {
2395 c = *it;
2396 ++it;
2397 if (!c->windowWidget()->isHidden()
2398 && !(c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)
2399 && !c->iconw)
2400 n++;
2401 }
2402
2403 while (rows * cols < n) {
2404 if (cols <= rows)
2405 cols++;
2406 else
2407 rows++;
2408 }
2409 int add = cols * rows - n;
2410 bool* used = new bool[cols*rows];
2411 for (int i = 0; i < rows*cols; i++)
2412 used[i] = false;
2413
2414 int row = 0;
2415 int col = 0;
2416 int w = width() / cols;
2417 int h = height() / rows;
2418
2419 it = d->windows.begin();
2420 while (it != d->windows.end()) {
2421 c = *it;
2422 ++it;
2423 if (c->iconw || c->windowWidget()->isHidden() || (c->titlebar && c->titlebar->isTool()))
2424 continue;
2425 if (!row && !col) {
2426 w -= c->baseSize().width();
2427 h -= c->baseSize().height();
2428 }
2429 if ((c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
2430 QPoint p = c->pos();
2431 if (p.x()+c->width() < 0)
2432 p.setX(0);
2433 if (p.x() > width())
2434 p.setX(width() - c->width());
2435 if (p.y() + 10 < 0)
2436 p.setY(0);
2437 if (p.y() > height())
2438 p.setY(height() - c->height());
2439
2440 if (p != c->pos())
2441 c->QWidget::move(p);
2442 } else {
2443 c->showNormal();
2444 used[row*cols+col] = true;
2445 QSize sz(w, h);
2446 QSize bsize(c->baseSize());
2447 sz = sz.expandedTo(c->windowWidget()->minimumSize()).boundedTo(c->windowWidget()->maximumSize());
2448 sz += bsize;
2449
2450 if ( add ) {
2451 if (sz.height() == h + bsize.height()) // no relevant constrains
2452 sz.rheight() *= 2;
2453 used[(row+1)*cols+col] = true;
2454 add--;
2455 }
2456
2457 c->setGeometry(col*w + col*bsize.width(), row*h + row*bsize.height(), sz.width(), sz.height());
2458
2459 while(row < rows && col < cols && used[row*cols+col]) {
2460 col++;
2461 if (col == cols) {
2462 col = 0;
2463 row++;
2464 }
2465 }
2466 }
2467 }
2468 delete [] used;
2469
2470 d->activateWindow(oldActive);
2471 d->updateWorkspace();
2472 blockSignals(false);
2473 }
2474
2475 /*!
2476 Arranges all iconified windows at the bottom of the workspace.
2477
2478 \sa cascade(), tile()
2479 */
arrangeIcons()2480 void QWorkspace::arrangeIcons()
2481 {
2482 Q_D(QWorkspace);
2483
2484 QRect cr = d->updateWorkspace();
2485 int x = 0;
2486 int y = -1;
2487
2488 QList<QWidget *>::Iterator it(d->icons.begin());
2489 while (it != d->icons.end()) {
2490 QWidget* i = *it;
2491 if (y == -1)
2492 y = cr.height() - i->height();
2493 if (x > 0 && x + i->width() > cr.width()) {
2494 x = 0;
2495 y -= i->height();
2496 }
2497 i->move(x, y);
2498 x += i->width();
2499 ++it;
2500 }
2501 d->updateWorkspace();
2502 }
2503
2504
QWorkspaceChild(QWidget * window,QWorkspace * parent,Qt::WindowFlags flags)2505 QWorkspaceChild::QWorkspaceChild(QWidget* window, QWorkspace *parent, Qt::WindowFlags flags)
2506 : QWidget(parent,
2507 Qt::FramelessWindowHint | Qt::SubWindow)
2508 {
2509 setAttribute(Qt::WA_DeleteOnClose);
2510 setAttribute(Qt::WA_NoMousePropagation);
2511 setMouseTracking(true);
2512 act = false;
2513 iconw = 0;
2514 shademode = false;
2515 titlebar = 0;
2516 setAutoFillBackground(true);
2517
2518 setBackgroundRole(QPalette::Window);
2519 if (window) {
2520 flags |= (window->windowFlags() & Qt::MSWindowsOwnDC);
2521 if (flags)
2522 window->setParent(this, flags & ~Qt::WindowType_Mask);
2523 else
2524 window->setParent(this);
2525 }
2526
2527 if (window && (flags & (Qt::WindowTitleHint
2528 | Qt::WindowSystemMenuHint
2529 | Qt::WindowMinimizeButtonHint
2530 | Qt::WindowMaximizeButtonHint
2531 | Qt::WindowContextHelpButtonHint))) {
2532 titlebar = new QWorkspaceTitleBar(window, this, flags);
2533 connect(titlebar, SIGNAL(doActivate()),
2534 this, SLOT(activate()));
2535 connect(titlebar, SIGNAL(doClose()),
2536 window, SLOT(close()));
2537 connect(titlebar, SIGNAL(doMinimize()),
2538 this, SLOT(showMinimized()));
2539 connect(titlebar, SIGNAL(doNormal()),
2540 this, SLOT(showNormal()));
2541 connect(titlebar, SIGNAL(doMaximize()),
2542 this, SLOT(showMaximized()));
2543 connect(titlebar, SIGNAL(popupOperationMenu(QPoint)),
2544 this, SIGNAL(popupOperationMenu(QPoint)));
2545 connect(titlebar, SIGNAL(showOperationMenu()),
2546 this, SIGNAL(showOperationMenu()));
2547 connect(titlebar, SIGNAL(doShade()),
2548 this, SLOT(showShaded()));
2549 connect(titlebar, SIGNAL(doubleClicked()),
2550 this, SLOT(titleBarDoubleClicked()));
2551 }
2552
2553 setMinimumSize(128, 0);
2554 int fw = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
2555 setContentsMargins(fw, fw, fw, fw);
2556
2557 childWidget = window;
2558 if (!childWidget)
2559 return;
2560
2561 setWindowTitle(childWidget->windowTitle());
2562
2563 QPoint p;
2564 QSize s;
2565 QSize cs;
2566
2567 bool hasBeenResized = childWidget->testAttribute(Qt::WA_Resized);
2568
2569 if (!hasBeenResized)
2570 cs = childWidget->sizeHint().expandedTo(childWidget->minimumSizeHint()).expandedTo(childWidget->minimumSize()).boundedTo(childWidget->maximumSize());
2571 else
2572 cs = childWidget->size();
2573
2574 windowSize = cs;
2575
2576 int th = titlebar ? titlebar->sizeHint().height() : 0;
2577 if (titlebar) {
2578 if (!childWidget->windowIcon().isNull())
2579 titlebar->setWindowIcon(childWidget->windowIcon());
2580
2581 if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
2582 th -= contentsRect().y();
2583
2584 p = QPoint(contentsRect().x(),
2585 th + contentsRect().y());
2586 s = QSize(cs.width() + 2*frameWidth(),
2587 cs.height() + 2*frameWidth() + th);
2588 } else {
2589 p = QPoint(contentsRect().x(), contentsRect().y());
2590 s = QSize(cs.width() + 2*frameWidth(),
2591 cs.height() + 2*frameWidth());
2592 }
2593
2594 childWidget->move(p);
2595 resize(s);
2596
2597 childWidget->installEventFilter(this);
2598
2599 widgetResizeHandler = new QWidgetResizeHandler(this, window);
2600 widgetResizeHandler->setSizeProtection(!parent->scrollBarsEnabled());
2601 widgetResizeHandler->setFrameWidth(frameWidth());
2602 connect(widgetResizeHandler, SIGNAL(activate()),
2603 this, SLOT(activate()));
2604 if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
2605 widgetResizeHandler->setExtraHeight(th + contentsRect().y() - 2*frameWidth());
2606 else
2607 widgetResizeHandler->setExtraHeight(th + contentsRect().y() - frameWidth());
2608 if (childWidget->minimumSize() == childWidget->maximumSize())
2609 widgetResizeHandler->setActive(QWidgetResizeHandler::Resize, false);
2610 setBaseSize(baseSize());
2611 }
2612
~QWorkspaceChild()2613 QWorkspaceChild::~QWorkspaceChild()
2614 {
2615 QWorkspace *workspace = qobject_cast<QWorkspace*>(parentWidget());
2616 if (iconw) {
2617 if (workspace)
2618 workspace->d_func()->removeIcon(iconw->parentWidget());
2619 delete iconw->parentWidget();
2620 }
2621
2622 if (workspace) {
2623 workspace->d_func()->focus.removeAll(this);
2624 if (workspace->d_func()->active == this)
2625 workspace->activatePreviousWindow();
2626 if (workspace->d_func()->active == this)
2627 workspace->d_func()->activateWindow(0);
2628 if (workspace->d_func()->maxWindow == this) {
2629 workspace->d_func()->hideMaximizeControls();
2630 workspace->d_func()->maxWindow = 0;
2631 }
2632 }
2633 }
2634
moveEvent(QMoveEvent *)2635 void QWorkspaceChild::moveEvent(QMoveEvent *)
2636 {
2637 ((QWorkspace*)parentWidget())->d_func()->updateWorkspace();
2638 }
2639
resizeEvent(QResizeEvent *)2640 void QWorkspaceChild::resizeEvent(QResizeEvent *)
2641 {
2642 bool wasMax = isMaximized();
2643 QRect r = contentsRect();
2644 QRect cr;
2645
2646 updateMask();
2647
2648 if (titlebar) {
2649 int th = titlebar->sizeHint().height();
2650 QRect tbrect(0, 0, width(), th);
2651 if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
2652 tbrect = QRect(r.x(), r.y(), r.width(), th);
2653 titlebar->setGeometry(tbrect);
2654
2655 if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
2656 th -= frameWidth();
2657 cr = QRect(r.x(), r.y() + th + (shademode ? (frameWidth() * 3) : 0),
2658 r.width(), r.height() - th);
2659 } else {
2660 cr = r;
2661 }
2662
2663 if (!childWidget)
2664 return;
2665
2666 bool doContentsResize = (windowSize == childWidget->size()
2667 || !(childWidget->testAttribute(Qt::WA_Resized) && childWidget->testAttribute(Qt::WA_PendingResizeEvent))
2668 ||childWidget->isMaximized());
2669
2670 windowSize = cr.size();
2671 childWidget->move(cr.topLeft());
2672 if (doContentsResize)
2673 childWidget->resize(cr.size());
2674 ((QWorkspace*)parentWidget())->d_func()->updateWorkspace();
2675
2676 if (wasMax) {
2677 overrideWindowState(Qt::WindowMaximized);
2678 childWidget->overrideWindowState(Qt::WindowMaximized);
2679 }
2680 }
2681
baseSize() const2682 QSize QWorkspaceChild::baseSize() const
2683 {
2684 int th = titlebar ? titlebar->sizeHint().height() : 0;
2685 if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
2686 th -= frameWidth();
2687 return QSize(2*frameWidth(), 2*frameWidth() + th);
2688 }
2689
sizeHint() const2690 QSize QWorkspaceChild::sizeHint() const
2691 {
2692 if (!childWidget)
2693 return QWidget::sizeHint() + baseSize();
2694
2695 QSize prefSize = windowWidget()->sizeHint().expandedTo(windowWidget()->minimumSizeHint());
2696 prefSize = prefSize.expandedTo(windowWidget()->minimumSize()).boundedTo(windowWidget()->maximumSize());
2697 prefSize += baseSize();
2698
2699 return prefSize;
2700 }
2701
minimumSizeHint() const2702 QSize QWorkspaceChild::minimumSizeHint() const
2703 {
2704 if (!childWidget)
2705 return QWidget::minimumSizeHint() + baseSize();
2706 QSize s = childWidget->minimumSize();
2707 if (s.isEmpty())
2708 s = childWidget->minimumSizeHint();
2709 return s + baseSize();
2710 }
2711
activate()2712 void QWorkspaceChild::activate()
2713 {
2714 ((QWorkspace*)parentWidget())->d_func()->activateWindow(windowWidget());
2715 }
2716
eventFilter(QObject * o,QEvent * e)2717 bool QWorkspaceChild::eventFilter(QObject * o, QEvent * e)
2718 {
2719 if (!isActive()
2720 && (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::FocusIn)) {
2721 if (iconw) {
2722 ((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
2723 if (iconw) {
2724 ((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
2725 delete iconw->parentWidget();
2726 iconw = 0;
2727 }
2728 }
2729 activate();
2730 }
2731
2732 // for all widgets except the window, that's the only thing we
2733 // process, and if we have no childWidget we skip totally
2734 if (o != childWidget || childWidget == 0)
2735 return false;
2736
2737 switch (e->type()) {
2738 case QEvent::ShowToParent:
2739 if (((QWorkspace*)parentWidget())->d_func()->focus.indexOf(this) < 0)
2740 ((QWorkspace*)parentWidget())->d_func()->focus.append(this);
2741
2742 if (windowWidget() && (windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
2743 internalRaise();
2744 show();
2745 }
2746 ((QWorkspace*)parentWidget())->d_func()->showWindow(windowWidget());
2747 break;
2748 case QEvent::WindowStateChange: {
2749 if (static_cast<QWindowStateChangeEvent*>(e)->isOverride())
2750 break;
2751 Qt::WindowStates state = windowWidget()->windowState();
2752
2753 if (state & Qt::WindowMinimized) {
2754 ((QWorkspace*)parentWidget())->d_func()->minimizeWindow(windowWidget());
2755 } else if (state & Qt::WindowMaximized) {
2756 if (windowWidget()->maximumSize().isValid() &&
2757 (windowWidget()->maximumWidth() < parentWidget()->width() ||
2758 windowWidget()->maximumHeight() < parentWidget()->height())) {
2759 windowWidget()->resize(windowWidget()->maximumSize());
2760 windowWidget()->overrideWindowState(Qt::WindowNoState);
2761 if (titlebar)
2762 titlebar->update();
2763 break;
2764 }
2765 if ((windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint))
2766 ((QWorkspace*)parentWidget())->d_func()->maximizeWindow(windowWidget());
2767 else
2768 ((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
2769 } else {
2770 ((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
2771 if (iconw) {
2772 ((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
2773 delete iconw->parentWidget();
2774 }
2775 }
2776 } break;
2777 case QEvent::HideToParent:
2778 {
2779 QWidget * w = iconw;
2780 if (w && (w = w->parentWidget())) {
2781 ((QWorkspace*)parentWidget())->d_func()->removeIcon(w);
2782 delete w;
2783 }
2784 ((QWorkspace*)parentWidget())->d_func()->hideChild(this);
2785 } break;
2786 case QEvent::WindowIconChange:
2787 {
2788 QWorkspace* ws = (QWorkspace*)parentWidget();
2789 if (ws->d_func()->maxtools && ws->d_func()->maxWindow == this) {
2790 int iconSize = ws->d_func()->maxtools->size().height();
2791 ws->d_func()->maxtools->setPixmap(childWidget->windowIcon().pixmap(QSize(iconSize, iconSize)));
2792 }
2793 }
2794 // fall through
2795 case QEvent::WindowTitleChange:
2796 setWindowTitle(windowWidget()->windowTitle());
2797 if (titlebar)
2798 titlebar->update();
2799 if (iconw)
2800 iconw->update();
2801 break;
2802 case QEvent::ModifiedChange:
2803 setWindowModified(windowWidget()->isWindowModified());
2804 if (titlebar)
2805 titlebar->update();
2806 if (iconw)
2807 iconw->update();
2808 break;
2809 case QEvent::Resize:
2810 {
2811 QResizeEvent* re = (QResizeEvent*)e;
2812 if (re->size() != windowSize && !shademode) {
2813 resize(re->size() + baseSize());
2814 childWidget->update(); //workaround
2815 }
2816 }
2817 break;
2818
2819 case QEvent::WindowDeactivate:
2820 if (titlebar && titlebar->isActive()) {
2821 update();
2822 }
2823 break;
2824
2825 case QEvent::WindowActivate:
2826 if (titlebar && titlebar->isActive()) {
2827 update();
2828 }
2829 break;
2830
2831 default:
2832 break;
2833 }
2834
2835 return QWidget::eventFilter(o, e);
2836 }
2837
childEvent(QChildEvent * e)2838 void QWorkspaceChild::childEvent(QChildEvent* e)
2839 {
2840 if (e->type() == QEvent::ChildRemoved && e->child() == childWidget) {
2841 childWidget = 0;
2842 if (iconw) {
2843 ((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
2844 delete iconw->parentWidget();
2845 }
2846 close();
2847 }
2848 }
2849
2850
doResize()2851 void QWorkspaceChild::doResize()
2852 {
2853 widgetResizeHandler->doResize();
2854 }
2855
doMove()2856 void QWorkspaceChild::doMove()
2857 {
2858 widgetResizeHandler->doMove();
2859 }
2860
enterEvent(QEvent *)2861 void QWorkspaceChild::enterEvent(QEvent *)
2862 {
2863 }
2864
leaveEvent(QEvent *)2865 void QWorkspaceChild::leaveEvent(QEvent *)
2866 {
2867 #ifndef QT_NO_CURSOR
2868 if (!widgetResizeHandler->isButtonDown())
2869 setCursor(Qt::ArrowCursor);
2870 #endif
2871 }
2872
paintEvent(QPaintEvent *)2873 void QWorkspaceChild::paintEvent(QPaintEvent *)
2874 {
2875 QPainter p(this);
2876 QStyleOptionFrame opt;
2877 opt.rect = rect();
2878 opt.palette = palette();
2879 opt.state = QStyle::State_None;
2880 opt.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
2881 opt.midLineWidth = 1;
2882
2883 if (titlebar && titlebar->isActive() && isActiveWindow())
2884 opt.state |= QStyle::State_Active;
2885
2886 style()->drawPrimitive(QStyle::PE_FrameWindow, &opt, &p, this);
2887 }
2888
changeEvent(QEvent * ev)2889 void QWorkspaceChild::changeEvent(QEvent *ev)
2890 {
2891 if(ev->type() == QEvent::StyleChange) {
2892 resizeEvent(0);
2893 if (iconw) {
2894 QFrame *frame = qobject_cast<QFrame*>(iconw->parentWidget());
2895 Q_ASSERT(frame);
2896 if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar)) {
2897 frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
2898 frame->resize(196+2*frame->frameWidth(), 20 + 2*frame->frameWidth());
2899 } else {
2900 frame->resize(196, 20);
2901 }
2902 }
2903 updateMask();
2904 }
2905 QWidget::changeEvent(ev);
2906 }
2907
setActive(bool b)2908 void QWorkspaceChild::setActive(bool b)
2909 {
2910 if (!childWidget)
2911 return;
2912
2913 bool hasFocus = isChildOf(window()->focusWidget(), this);
2914 if (act == b && (act == hasFocus))
2915 return;
2916
2917 act = b;
2918
2919 if (titlebar)
2920 titlebar->setActive(act);
2921 if (iconw)
2922 iconw->setActive(act);
2923 update();
2924
2925 QList<QWidget*> wl = childWidget->findChildren<QWidget*>();
2926 if (act) {
2927 for (int i = 0; i < wl.size(); ++i) {
2928 QWidget *w = wl.at(i);
2929 w->removeEventFilter(this);
2930 }
2931 if (!hasFocus) {
2932 QWidget *lastfocusw = childWidget->focusWidget();
2933 if (lastfocusw && lastfocusw->focusPolicy() != Qt::NoFocus) {
2934 lastfocusw->setFocus();
2935 } else if (childWidget->focusPolicy() != Qt::NoFocus) {
2936 childWidget->setFocus();
2937 } else {
2938 // find something, anything, that accepts focus, and use that.
2939 for (int i = 0; i < wl.size(); ++i) {
2940 QWidget *w = wl.at(i);
2941 if(w->focusPolicy() != Qt::NoFocus) {
2942 w->setFocus();
2943 hasFocus = true;
2944 break;
2945 }
2946 }
2947 if (!hasFocus)
2948 setFocus();
2949 }
2950 }
2951 } else {
2952 for (int i = 0; i < wl.size(); ++i) {
2953 QWidget *w = wl.at(i);
2954 w->removeEventFilter(this);
2955 w->installEventFilter(this);
2956 }
2957 }
2958 }
2959
isActive() const2960 bool QWorkspaceChild::isActive() const
2961 {
2962 return act;
2963 }
2964
windowWidget() const2965 QWidget* QWorkspaceChild::windowWidget() const
2966 {
2967 return childWidget;
2968 }
2969
isWindowOrIconVisible() const2970 bool QWorkspaceChild::isWindowOrIconVisible() const
2971 {
2972 return childWidget && (!isHidden() || (iconw && !iconw->isHidden()));
2973 }
2974
updateMask()2975 void QWorkspaceChild::updateMask()
2976 {
2977 QStyleOptionTitleBar titleBarOptions;
2978 titleBarOptions.rect = rect();
2979 titleBarOptions.titleBarFlags = windowFlags();
2980 titleBarOptions.titleBarState = windowState();
2981
2982 QStyleHintReturnMask frameMask;
2983 if (style()->styleHint(QStyle::SH_WindowFrame_Mask, &titleBarOptions, this, &frameMask)) {
2984 setMask(frameMask.region);
2985 } else if (!mask().isEmpty()) {
2986 clearMask();
2987 }
2988
2989 if (iconw) {
2990 QFrame *frame = qobject_cast<QFrame *>(iconw->parentWidget());
2991 Q_ASSERT(frame);
2992
2993 titleBarOptions.rect = frame->rect();
2994 titleBarOptions.titleBarFlags = frame->windowFlags();
2995 titleBarOptions.titleBarState = frame->windowState() | Qt::WindowMinimized;
2996 if (style()->styleHint(QStyle::SH_WindowFrame_Mask, &titleBarOptions, frame, &frameMask)) {
2997 frame->setMask(frameMask.region);
2998 } else if (!frame->mask().isEmpty()) {
2999 frame->clearMask();
3000 }
3001 }
3002 }
3003
iconWidget() const3004 QWidget* QWorkspaceChild::iconWidget() const
3005 {
3006 if (!iconw) {
3007 QWorkspaceChild* that = (QWorkspaceChild*) this;
3008
3009 QFrame* frame = new QFrame(that, Qt::Window);
3010 QVBoxLayout *vbox = new QVBoxLayout(frame);
3011 vbox->setMargin(0);
3012 QWorkspaceTitleBar *tb = new QWorkspaceTitleBar(windowWidget(), frame);
3013 vbox->addWidget(tb);
3014 tb->setObjectName(QLatin1String("_workspacechild_icon_"));
3015 QStyleOptionTitleBar opt;
3016 tb->initStyleOption(&opt);
3017 int th = style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, tb);
3018 int iconSize = style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, 0, this);
3019 if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar)) {
3020 frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
3021 frame->resize(iconSize+2*frame->frameWidth(), th+2*frame->frameWidth());
3022 } else {
3023 frame->resize(iconSize, th);
3024 }
3025
3026 that->iconw = tb;
3027 that->updateMask();
3028 iconw->setActive(isActive());
3029
3030 connect(iconw, SIGNAL(doActivate()),
3031 this, SLOT(activate()));
3032 connect(iconw, SIGNAL(doClose()),
3033 windowWidget(), SLOT(close()));
3034 connect(iconw, SIGNAL(doNormal()),
3035 this, SLOT(showNormal()));
3036 connect(iconw, SIGNAL(doMaximize()),
3037 this, SLOT(showMaximized()));
3038 connect(iconw, SIGNAL(popupOperationMenu(QPoint)),
3039 this, SIGNAL(popupOperationMenu(QPoint)));
3040 connect(iconw, SIGNAL(showOperationMenu()),
3041 this, SIGNAL(showOperationMenu()));
3042 connect(iconw, SIGNAL(doubleClicked()),
3043 this, SLOT(titleBarDoubleClicked()));
3044 }
3045 if (windowWidget()) {
3046 iconw->setWindowTitle(windowWidget()->windowTitle());
3047 }
3048 return iconw->parentWidget();
3049 }
3050
showMinimized()3051 void QWorkspaceChild::showMinimized()
3052 {
3053 windowWidget()->setWindowState(Qt::WindowMinimized | (windowWidget()->windowState() & ~Qt::WindowMaximized));
3054 }
3055
showMaximized()3056 void QWorkspaceChild::showMaximized()
3057 {
3058 windowWidget()->setWindowState(Qt::WindowMaximized | (windowWidget()->windowState() & ~Qt::WindowMinimized));
3059 }
3060
showNormal()3061 void QWorkspaceChild::showNormal()
3062 {
3063 windowWidget()->setWindowState(windowWidget()->windowState() & ~(Qt::WindowMinimized|Qt::WindowMaximized));
3064 }
3065
showShaded()3066 void QWorkspaceChild::showShaded()
3067 {
3068 if (!titlebar)
3069 return;
3070 ((QWorkspace*)parentWidget())->d_func()->activateWindow(windowWidget());
3071 QWidget* w = windowWidget();
3072 if (shademode) {
3073 w->overrideWindowState(Qt::WindowNoState);
3074 overrideWindowState(Qt::WindowNoState);
3075
3076 shademode = false;
3077 resize(shadeRestore.expandedTo(minimumSizeHint()));
3078 setMinimumSize(shadeRestoreMin);
3079 style()->polish(this);
3080 } else {
3081 shadeRestore = size();
3082 shadeRestoreMin = minimumSize();
3083 setMinimumHeight(0);
3084 shademode = true;
3085 w->overrideWindowState(Qt::WindowMinimized);
3086 overrideWindowState(Qt::WindowMinimized);
3087
3088 if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
3089 resize(width(), titlebar->height());
3090 else
3091 resize(width(), titlebar->height() + 2*frameWidth() + 1);
3092 style()->polish(this);
3093 }
3094 titlebar->update();
3095 }
3096
titleBarDoubleClicked()3097 void QWorkspaceChild::titleBarDoubleClicked()
3098 {
3099 if (!windowWidget())
3100 return;
3101 if (iconw)
3102 showNormal();
3103 else if (windowWidget()->windowFlags() & Qt::WindowShadeButtonHint)
3104 showShaded();
3105 else if (windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint)
3106 showMaximized();
3107 }
3108
adjustToFullscreen()3109 void QWorkspaceChild::adjustToFullscreen()
3110 {
3111 if (!childWidget)
3112 return;
3113
3114 if(!((QWorkspace*)parentWidget())->d_func()->maxmenubar || style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, this)) {
3115 setGeometry(parentWidget()->rect());
3116 } else {
3117 int fw = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
3118 bool noBorder = style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar);
3119 int th = titlebar ? titlebar->sizeHint().height() : 0;
3120 int w = parentWidget()->width() + 2*fw;
3121 int h = parentWidget()->height() + (noBorder ? fw : 2*fw) + th;
3122 w = qMax(w, childWidget->minimumWidth());
3123 h = qMax(h, childWidget->minimumHeight());
3124 setGeometry(-fw, (noBorder ? 0 : -fw) - th, w, h);
3125 }
3126 childWidget->overrideWindowState(Qt::WindowMaximized);
3127 overrideWindowState(Qt::WindowMaximized);
3128 }
3129
internalRaise()3130 void QWorkspaceChild::internalRaise()
3131 {
3132
3133 QWidget *stackUnderWidget = 0;
3134 if (!windowWidget() || (windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint) == 0) {
3135
3136 QList<QWorkspaceChild *>::Iterator it(((QWorkspace*)parent())->d_func()->windows.begin());
3137 while (it != ((QWorkspace*)parent())->d_func()->windows.end()) {
3138 QWorkspaceChild* c = *it;
3139 ++it;
3140 if (c->windowWidget() &&
3141 !c->windowWidget()->isHidden() &&
3142 (c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
3143 if (stackUnderWidget)
3144 c->stackUnder(stackUnderWidget);
3145 else
3146 c->raise();
3147 stackUnderWidget = c;
3148 }
3149 }
3150 }
3151
3152 if (stackUnderWidget) {
3153 if (iconw)
3154 iconw->parentWidget()->stackUnder(stackUnderWidget);
3155 stackUnder(stackUnderWidget);
3156 } else {
3157 if (iconw)
3158 iconw->parentWidget()->raise();
3159 raise();
3160 }
3161
3162 }
3163
show()3164 void QWorkspaceChild::show()
3165 {
3166 if (childWidget && childWidget->isHidden())
3167 childWidget->show();
3168 QWidget::show();
3169 }
3170
scrollBarsEnabled() const3171 bool QWorkspace::scrollBarsEnabled() const
3172 {
3173 Q_D(const QWorkspace);
3174 return d->vbar != 0;
3175 }
3176
3177 /*!
3178 \property QWorkspace::scrollBarsEnabled
3179 \brief whether the workspace provides scroll bars
3180
3181 If this property is true, the workspace will provide scroll bars if any
3182 of the child windows extend beyond the edges of the visible
3183 workspace. The workspace area will automatically increase to
3184 contain child windows if they are resized beyond the right or
3185 bottom edges of the visible area.
3186
3187 If this property is false (the default), resizing child windows
3188 out of the visible area of the workspace is not permitted, although
3189 it is still possible to position them partially outside the visible area.
3190 */
setScrollBarsEnabled(bool enable)3191 void QWorkspace::setScrollBarsEnabled(bool enable)
3192 {
3193 Q_D(QWorkspace);
3194 if ((d->vbar != 0) == enable)
3195 return;
3196
3197 d->xoffset = d->yoffset = 0;
3198 if (enable) {
3199 d->vbar = new QScrollBar(Qt::Vertical, this);
3200 d->vbar->setObjectName(QLatin1String("vertical scrollbar"));
3201 connect(d->vbar, SIGNAL(valueChanged(int)), this, SLOT(_q_scrollBarChanged()));
3202 d->hbar = new QScrollBar(Qt::Horizontal, this);
3203 d->hbar->setObjectName(QLatin1String("horizontal scrollbar"));
3204 connect(d->hbar, SIGNAL(valueChanged(int)), this, SLOT(_q_scrollBarChanged()));
3205 d->corner = new QWidget(this);
3206 d->corner->setBackgroundRole(QPalette::Window);
3207 d->corner->setObjectName(QLatin1String("qt_corner"));
3208 d->updateWorkspace();
3209 } else {
3210 delete d->vbar;
3211 delete d->hbar;
3212 delete d->corner;
3213 d->vbar = d->hbar = 0;
3214 d->corner = 0;
3215 }
3216
3217 QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
3218 while (it != d->windows.end()) {
3219 QWorkspaceChild *child = *it;
3220 ++it;
3221 child->widgetResizeHandler->setSizeProtection(!enable);
3222 }
3223 }
3224
updateWorkspace()3225 QRect QWorkspacePrivate::updateWorkspace()
3226 {
3227 Q_Q(QWorkspace);
3228 QRect cr(q->rect());
3229
3230 if (q->scrollBarsEnabled() && !maxWindow) {
3231 corner->raise();
3232 vbar->raise();
3233 hbar->raise();
3234 if (maxWindow)
3235 maxWindow->internalRaise();
3236
3237 QRect r(0, 0, 0, 0);
3238 QList<QWorkspaceChild *>::Iterator it(windows.begin());
3239 while (it != windows.end()) {
3240 QWorkspaceChild *child = *it;
3241 ++it;
3242 if (!child->isHidden())
3243 r = r.unite(child->geometry());
3244 }
3245 vbar->blockSignals(true);
3246 hbar->blockSignals(true);
3247
3248 int hsbExt = hbar->sizeHint().height();
3249 int vsbExt = vbar->sizeHint().width();
3250
3251
3252 bool showv = yoffset || yoffset + r.bottom() - q->height() + 1 > 0 || yoffset + r.top() < 0;
3253 bool showh = xoffset || xoffset + r.right() - q->width() + 1 > 0 || xoffset + r.left() < 0;
3254
3255 if (showh && !showv)
3256 showv = yoffset + r.bottom() - q->height() + hsbExt + 1 > 0;
3257 if (showv && !showh)
3258 showh = xoffset + r.right() - q->width() + vsbExt + 1 > 0;
3259
3260 if (!showh)
3261 hsbExt = 0;
3262 if (!showv)
3263 vsbExt = 0;
3264
3265 if (showv) {
3266 vbar->setSingleStep(qMax(q->height() / 12, 30));
3267 vbar->setPageStep(q->height() - hsbExt);
3268 vbar->setMinimum(qMin(0, yoffset + qMin(0, r.top())));
3269 vbar->setMaximum(qMax(0, yoffset + qMax(0, r.bottom() - q->height() + hsbExt + 1)));
3270 vbar->setGeometry(q->width() - vsbExt, 0, vsbExt, q->height() - hsbExt);
3271 vbar->setValue(yoffset);
3272 vbar->show();
3273 } else {
3274 vbar->hide();
3275 }
3276
3277 if (showh) {
3278 hbar->setSingleStep(qMax(q->width() / 12, 30));
3279 hbar->setPageStep(q->width() - vsbExt);
3280 hbar->setMinimum(qMin(0, xoffset + qMin(0, r.left())));
3281 hbar->setMaximum(qMax(0, xoffset + qMax(0, r.right() - q->width() + vsbExt + 1)));
3282 hbar->setGeometry(0, q->height() - hsbExt, q->width() - vsbExt, hsbExt);
3283 hbar->setValue(xoffset);
3284 hbar->show();
3285 } else {
3286 hbar->hide();
3287 }
3288
3289 if (showh && showv) {
3290 corner->setGeometry(q->width() - vsbExt, q->height() - hsbExt, vsbExt, hsbExt);
3291 corner->show();
3292 } else {
3293 corner->hide();
3294 }
3295
3296 vbar->blockSignals(false);
3297 hbar->blockSignals(false);
3298
3299 cr.setRect(0, 0, q->width() - vsbExt, q->height() - hsbExt);
3300 }
3301
3302 QList<QWidget *>::Iterator ii(icons.begin());
3303 while (ii != icons.end()) {
3304 QWidget* w = *ii;
3305 ++ii;
3306 int x = w->x();
3307 int y = w->y();
3308 bool m = false;
3309 if (x+w->width() > cr.width()) {
3310 m = true;
3311 x = cr.width() - w->width();
3312 }
3313 if (y+w->height() > cr.height()) {
3314 y = cr.height() - w->height();
3315 m = true;
3316 }
3317 if (m) {
3318 if (QWorkspaceChild *child = qobject_cast<QWorkspaceChild*>(w))
3319 child->move(x, y);
3320 else
3321 w->move(x, y);
3322 }
3323 }
3324
3325 return cr;
3326
3327 }
3328
_q_scrollBarChanged()3329 void QWorkspacePrivate::_q_scrollBarChanged()
3330 {
3331 int ver = yoffset - vbar->value();
3332 int hor = xoffset - hbar->value();
3333 yoffset = vbar->value();
3334 xoffset = hbar->value();
3335
3336 QList<QWorkspaceChild *>::Iterator it(windows.begin());
3337 while (it != windows.end()) {
3338 QWorkspaceChild *child = *it;
3339 ++it;
3340 // we do not use move() due to the reimplementation in QWorkspaceChild
3341 child->setGeometry(child->x() + hor, child->y() + ver, child->width(), child->height());
3342 }
3343 updateWorkspace();
3344 }
3345
3346 /*!
3347 \enum QWorkspace::WindowOrder
3348
3349 Specifies the order in which child windows are returned from windowList().
3350
3351 \value CreationOrder The windows are returned in the order of their creation
3352 \value StackingOrder The windows are returned in the order of their stacking
3353 */
3354
3355 /*!\reimp */
changeEvent(QEvent * ev)3356 void QWorkspace::changeEvent(QEvent *ev)
3357 {
3358 Q_D(QWorkspace);
3359 if(ev->type() == QEvent::StyleChange) {
3360 if (isVisible() && d->maxWindow && d->maxmenubar) {
3361 if(style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, this)) {
3362 d->hideMaximizeControls(); //hide any visible maximized controls
3363 d->showMaximizeControls(); //updates the modification state as well
3364 }
3365 }
3366 }
3367 QWidget::changeEvent(ev);
3368 }
3369
3370 QT_END_NAMESPACE
3371
3372 #include "moc_qworkspace.cpp"
3373
3374 #include "qworkspace.moc"
3375
3376 #endif // QT_NO_WORKSPACE
3377