source: trunk/src/workspace/qworkspace.cpp

Last change on this file was 55, checked in by dmik, 20 years ago

Fixed [Qt misbehavior]: QWorkspaceChild is now created with the WNoAutoErase flag set, to get rid of the MDI window frame's flicker when resizing. Note that in order to apply this fix to another platform, the QWindowsStyle::drawPrimitive(PE_WindowFrame) fix (see changeset:54) should be also applied.

  • Property svn:keywords set to Id
File size: 83.4 KB
Line 
1/****************************************************************************
2** $Id: qworkspace.cpp 55 2006-01-15 22:24:33Z dmik $
3**
4** Implementation of the QWorkspace class
5**
6** Created : 931107
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the workspace module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qworkspace.h"
39#ifndef QT_NO_WORKSPACE
40#include "qapplication.h"
41#include "../widgets/qtitlebar_p.h"
42#include "qobjectlist.h"
43#include "qlayout.h"
44#include "qtoolbutton.h"
45#include "qlabel.h"
46#include "qvbox.h"
47#include "qaccel.h"
48#include "qcursor.h"
49#include "qpopupmenu.h"
50#include "qmenubar.h"
51#include "qguardedptr.h"
52#include "qiconset.h"
53#include "../widgets/qwidgetresizehandler_p.h"
54#include "qfocusdata.h"
55#include "qdatetime.h"
56#include "qtooltip.h"
57#include "qwmatrix.h"
58#include "qimage.h"
59#include "qscrollbar.h"
60#include "qstyle.h"
61#include "qbitmap.h"
62
63// magic non-mdi things
64#include "qtimer.h"
65#include "qdockarea.h"
66#include "qstatusbar.h"
67#include "qmainwindow.h"
68#include "qdockwindow.h"
69#include "qtoolbar.h"
70
71#define BUTTON_WIDTH 16
72#define BUTTON_HEIGHT 14
73
74/*!
75 \class QWorkspace qworkspace.h
76 \brief The QWorkspace widget provides a workspace window that can
77 contain decorated windows, e.g. for MDI.
78
79 \module workspace
80
81 \ingroup application
82 \ingroup organizers
83 \mainclass
84
85 MDI (multiple document interface) applications typically have one
86 main window with a menu bar and toolbar, and a central widget that
87 is a QWorkspace. The workspace itself contains zero, one or more
88 document windows, each of which is a widget.
89
90 The workspace itself is an ordinary Qt widget. It has a standard
91 constructor that takes a parent widget and an object name. The
92 parent window is usually a QMainWindow, but it need not be.
93
94 Document windows (i.e. MDI windows) are also ordinary Qt widgets
95 which have the workspace as their parent widget. When you call
96 show(), hide(), showMaximized(), setCaption(), etc. on a document
97 window, it is shown, hidden, etc. with a frame, caption, icon and
98 icon text, just as you'd expect. You can provide widget flags
99 which will be used for the layout of the decoration or the
100 behaviour of the widget itself.
101
102 To change or retrieve the geometry of MDI windows you must operate
103 on the MDI widget's parentWidget(). (The parentWidget() provides
104 access to the decorated window in which the MDI window's widget is
105 shown.)
106
107 A document window becomes active when it gets the keyboard focus.
108 You can also activate a window in code using setFocus(). The user
109 can activate a window by moving focus in the usual ways, for
110 example by clicking a window or by pressing Tab. The workspace
111 emits a signal windowActivated() when it detects the activation
112 change, and the function activeWindow() always returns a pointer
113 to the active document window.
114
115 The convenience function windowList() returns a list of all
116 document windows. This is useful to create a popup menu
117 "<u>W</u>indows" on the fly, for example.
118
119 QWorkspace provides two built-in layout strategies for child
120 windows: cascade() and tile(). Both are slots so you can easily
121 connect menu entries to them.
122
123 If you want your users to be able to work with document windows
124 larger than the actual workspace, set the scrollBarsEnabled
125 property to TRUE.
126
127 If the top-level window contains a menu bar and a document window
128 is maximised, QWorkspace moves the document window's minimize,
129 restore and close buttons from the document window's frame to the
130 workspace window's menu bar. It then inserts a window operations
131 menu at the far left of the menu bar.
132*/
133
134static bool inCaptionChange = FALSE;
135
136class QWorkspaceChild : public QFrame
137{
138 Q_OBJECT
139
140 friend class QWorkspace;
141 friend class QTitleBar;
142
143public:
144 QWorkspaceChild( QWidget* window,
145 QWorkspace* parent=0, const char* name=0 );
146 ~QWorkspaceChild();
147
148 void setActive( bool );
149 bool isActive() const;
150
151 void adjustToFullscreen();
152
153 void setStatusBar(QStatusBar *);
154 QWidget* windowWidget() const;
155 QWidget* iconWidget() const;
156
157 void doResize();
158 void doMove();
159
160 QSize sizeHint() const;
161 QSize minimumSizeHint() const;
162
163 QSize baseSize() const;
164
165signals:
166 void showOperationMenu();
167 void popupOperationMenu( const QPoint& );
168
169public slots:
170 void activate();
171 void showMinimized();
172 void showMaximized();
173 void showNormal();
174 void showShaded();
175 void setCaption( const QString& );
176 void internalRaise();
177 void titleBarDoubleClicked();
178
179 void move( int x, int y );
180
181protected:
182 bool event(QEvent * );
183 void enterEvent( QEvent * );
184 void leaveEvent( QEvent * );
185 void childEvent( QChildEvent* );
186 void resizeEvent( QResizeEvent * );
187 void moveEvent( QMoveEvent * );
188 bool eventFilter( QObject *, QEvent * );
189
190 bool focusNextPrevChild( bool );
191
192 void drawFrame( QPainter * );
193 void styleChange( QStyle & );
194
195private:
196 QWidget* childWidget;
197 QGuardedPtr<QWidget> lastfocusw;
198 QWidgetResizeHandler *widgetResizeHandler;
199 QTitleBar* titlebar;
200 QGuardedPtr<QStatusBar> statusbar;
201 QGuardedPtr<QTitleBar> iconw;
202 QSize windowSize;
203 QSize shadeRestore;
204 QSize shadeRestoreMin;
205 bool act :1;
206 bool shademode :1;
207 bool snappedRight :1;
208 bool snappedDown :1;
209#if defined(Q_DISABLE_COPY) // Disabled copy constructor and operator=
210 QWorkspaceChild( const QWorkspaceChild & );
211 QWorkspaceChild &operator=( const QWorkspaceChild & );
212#endif
213};
214
215class QMainWindow;
216
217class QWorkspacePrivate {
218public:
219 QWorkspaceChild* active;
220 QPtrList<QWorkspaceChild> windows;
221 QPtrList<QWorkspaceChild> focus;
222 QPtrList<QWidget> icons;
223 QWorkspaceChild* maxWindow;
224 QRect maxRestore;
225 QGuardedPtr<QFrame> maxcontrols;
226 QGuardedPtr<QMenuBar> maxmenubar;
227
228 int px;
229 int py;
230 QWidget *becomeActive;
231 QGuardedPtr<QLabel> maxtools;
232 QPopupMenu* popup;
233 QPopupMenu* toolPopup;
234 int menuId;
235 int controlId;
236 QString topCaption;
237
238 QScrollBar *vbar, *hbar;
239 QWidget *corner;
240 int yoffset, xoffset;
241
242 // toplevel mdi fu
243 QWorkspace::WindowMode wmode;
244 QGuardedPtr<QMainWindow> mainwindow;
245 QPtrList<QDockWindow> dockwindows, newdocks;
246};
247
248static bool isChildOf( QWidget * child, QWidget * parent )
249{
250 if ( !parent || !child )
251 return FALSE;
252 QWidget * w = child;
253 while( w && w != parent )
254 w = w->parentWidget();
255 return w != 0;
256}
257
258/*!
259 Constructs a workspace with a \a parent and a \a name.
260*/
261QWorkspace::QWorkspace( QWidget *parent, const char *name )
262 : QWidget( parent, name )
263{
264 init();
265}
266
267#ifdef QT_WORKSPACE_WINDOWMODE
268/*!
269 Constructs a workspace with a \a parent and a \a name. This
270 constructor will also set the WindowMode to \a mode.
271
272 \sa windowMode()
273*/
274QWorkspace::QWorkspace( QWorkspace::WindowMode mode, QWidget *parent, const char *name )
275 : QWidget( parent, name )
276{
277 init();
278 d->wmode = mode;
279}
280#endif
281
282
283/*!
284 \internal
285*/
286void
287QWorkspace::init()
288{
289 d = new QWorkspacePrivate;
290 d->maxcontrols = 0;
291 d->active = 0;
292 d->maxWindow = 0;
293 d->maxtools = 0;
294 d->px = 0;
295 d->py = 0;
296 d->becomeActive = 0;
297#if defined( QT_WORKSPACE_WINDOWMODE ) && defined( Q_WS_MAC )
298 d->wmode = AutoDetect;
299#else
300 d->wmode = MDI;
301#endif
302 d->mainwindow = 0;
303#if defined(Q_WS_WIN)
304 d->popup = new QPopupMenu( this, "qt_internal_mdi_popup" );
305 d->toolPopup = new QPopupMenu( this, "qt_internal_mdi_popup" );
306#else
307 d->popup = new QPopupMenu( parentWidget(), "qt_internal_mdi_popup" );
308 d->toolPopup = new QPopupMenu( parentWidget(), "qt_internal_mdi_popup" );
309#endif
310
311 d->menuId = -1;
312 d->controlId = -1;
313 connect( d->popup, SIGNAL( aboutToShow() ), this, SLOT(operationMenuAboutToShow() ));
314 connect( d->popup, SIGNAL( activated(int) ), this, SLOT( operationMenuActivated(int) ) );
315 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarNormalButton)), tr("&Restore"), 1);
316 d->popup->insertItem(tr("&Move"), 2);
317 d->popup->insertItem(tr("&Size"), 3);
318 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarMinButton)), tr("Mi&nimize"), 4);
319 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarMaxButton)), tr("Ma&ximize"), 5);
320 d->popup->insertSeparator();
321 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarCloseButton)),
322 tr("&Close")
323#ifndef QT_NO_ACCEL
324 +"\t"+QAccel::keyToString(CTRL+Key_F4)
325#endif
326 , this, SLOT( closeActiveWindow() ) );
327
328 connect( d->toolPopup, SIGNAL( aboutToShow() ), this, SLOT(toolMenuAboutToShow() ));
329 connect( d->toolPopup, SIGNAL( activated(int) ), this, SLOT( operationMenuActivated(int) ) );
330 d->toolPopup->insertItem(tr("&Move"), 2);
331 d->toolPopup->insertItem(tr("&Size"), 3);
332 d->toolPopup->insertItem(tr("Stay on &Top"), 7);
333 d->toolPopup->setItemChecked( 7, TRUE );
334 d->toolPopup->setCheckable( TRUE );
335 d->toolPopup->insertSeparator();
336 d->toolPopup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarShadeButton)), tr("Sh&ade"), 6);
337 d->toolPopup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarCloseButton)),
338 tr("&Close")
339#ifndef QT_NO_ACCEL
340 +"\t"+QAccel::keyToString( CTRL+Key_F4)
341#endif
342 , this, SLOT( closeActiveWindow() ) );
343
344#ifndef QT_NO_ACCEL
345 QAccel* a = new QAccel( this );
346 a->connectItem( a->insertItem( ALT + Key_Minus),
347 this, SLOT( showOperationMenu() ) );
348
349 a->connectItem( a->insertItem( CTRL + Key_F6),
350 this, SLOT( activateNextWindow() ) );
351 a->connectItem( a->insertItem( CTRL + Key_Tab),
352 this, SLOT( activateNextWindow() ) );
353 a->connectItem( a->insertItem( Key_Forward ),
354 this, SLOT( activateNextWindow() ) );
355
356 a->connectItem( a->insertItem( CTRL + SHIFT + Key_F6),
357 this, SLOT( activatePreviousWindow() ) );
358 a->connectItem( a->insertItem( CTRL + SHIFT + Key_Tab),
359 this, SLOT( activatePreviousWindow() ) );
360 a->connectItem( a->insertItem( Key_Back ),
361 this, SLOT( activatePreviousWindow() ) );
362
363 a->connectItem( a->insertItem( CTRL + Key_F4 ),
364 this, SLOT( closeActiveWindow() ) );
365#endif
366
367 setBackgroundMode( PaletteDark );
368 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
369
370#ifndef QT_NO_WIDGET_TOPEXTRA
371 d->topCaption = topLevelWidget()->caption();
372#endif
373
374 d->hbar = d->vbar = 0;
375 d->corner = 0;
376 d->xoffset = d->yoffset = 0;
377
378 updateWorkspace();
379
380 topLevelWidget()->installEventFilter( this );
381}
382
383/*! Destroys the workspace and frees any allocated resources. */
384
385QWorkspace::~QWorkspace()
386{
387 delete d;
388 d = 0;
389}
390
391/*!\reimp */
392QSize QWorkspace::sizeHint() const
393{
394 QSize s( QApplication::desktop()->size() );
395 return QSize( s.width()*2/3, s.height()*2/3);
396}
397
398/*! \reimp */
399void QWorkspace::setPaletteBackgroundColor( const QColor & c )
400{
401 setEraseColor( c );
402}
403
404
405/*! \reimp */
406void QWorkspace::setPaletteBackgroundPixmap( const QPixmap & pm )
407{
408 setErasePixmap( pm );
409}
410
411/*! \reimp */
412void QWorkspace::childEvent( QChildEvent * e)
413{
414 if (e->inserted() && e->child()->isWidgetType()) {
415 QWidget* w = (QWidget*) e->child();
416 if ( !w || !w->testWFlags( WStyle_Title | WStyle_NormalBorder | WStyle_DialogBorder )
417 || d->icons.contains( w ) || w == d->vbar || w == d->hbar || w == d->corner )
418 return; // nothing to do
419
420 bool wasMaximized = w->isMaximized();
421 bool wasMinimized = w->isMinimized();
422 bool hasBeenHidden = w->isHidden();
423 bool hasSize = w->testWState( WState_Resized );
424 int x = w->x();
425 int y = w->y();
426 bool hasPos = x != 0 || y != 0;
427 QSize s = w->size().expandedTo( w->minimumSizeHint() );
428 if ( !hasSize && w->sizeHint().isValid() )
429 w->adjustSize();
430
431 QWorkspaceChild* child = new QWorkspaceChild( w, this, "qt_workspacechild" );
432 child->installEventFilter( this );
433
434 connect( child, SIGNAL( popupOperationMenu(const QPoint&) ),
435 this, SLOT( popupOperationMenu(const QPoint&) ) );
436 connect( child, SIGNAL( showOperationMenu() ),
437 this, SLOT( showOperationMenu() ) );
438 d->windows.append( child );
439 if ( child->isVisibleTo( this ) )
440 d->focus.append( child );
441 child->internalRaise();
442
443 if ( !hasPos )
444 place( child );
445 if ( hasSize )
446 child->resize( s + child->baseSize() );
447 else
448 child->adjustSize();
449 if ( hasPos )
450 child->move( x, y );
451
452 if ( hasBeenHidden )
453 w->hide();
454 else if ( !isVisible() ) // that's a case were we don't receive a showEvent in time. Tricky.
455 child->show();
456
457 if ( wasMaximized )
458 w->showMaximized();
459 else if ( wasMinimized )
460 w->showMinimized();
461 else
462 activateWindow( w );
463
464 updateWorkspace();
465 } else if (e->removed() ) {
466 if ( d->windows.contains( (QWorkspaceChild*)e->child() ) ) {
467 d->windows.removeRef( (QWorkspaceChild*)e->child() );
468 d->focus.removeRef( (QWorkspaceChild*)e->child() );
469 if (d->maxWindow == e->child())
470 d->maxWindow = 0;
471 updateWorkspace();
472 }
473 }
474}
475
476/*! \reimp
477*/
478#ifndef QT_NO_WHEELEVENT
479void QWorkspace::wheelEvent( QWheelEvent *e )
480{
481 if ( !scrollBarsEnabled() )
482 return;
483 if ( d->vbar && d->vbar->isVisible() && !( e->state() & AltButton ) )
484 QApplication::sendEvent( d->vbar, e );
485 else if ( d->hbar && d->hbar->isVisible() )
486 QApplication::sendEvent( d->hbar, e );
487}
488#endif
489
490void QWorkspace::activateWindow( QWidget* w, bool change_focus )
491{
492 if ( !w ) {
493 d->active = 0;
494 emit windowActivated( 0 );
495 return;
496 }
497 if ( d->wmode == MDI && !isVisibleTo( 0 ) ) {
498 d->becomeActive = w;
499 return;
500 }
501
502 if ( d->active && d->active->windowWidget() == w ) {
503 if ( !isChildOf( focusWidget(), w ) ) // child window does not have focus
504 d->active->setActive( TRUE );
505 return;
506 }
507
508 d->active = 0;
509 // First deactivate all other workspace clients
510 QPtrListIterator<QWorkspaceChild> it( d->windows );
511 while ( it.current () ) {
512 QWorkspaceChild* c = it.current();
513 ++it;
514 if(windowMode() == QWorkspace::TopLevel && c->isTopLevel() &&
515 c->windowWidget() == w && !c->isActive())
516 c->setActiveWindow();
517 if (c->windowWidget() == w)
518 d->active = c;
519 else
520 c->setActive( FALSE );
521 }
522
523 if (!d->active)
524 return;
525
526 // Then activate the new one, so the focus is stored correctly
527 d->active->setActive( TRUE );
528
529 if (!d->active)
530 return;
531
532 if ( d->maxWindow && d->maxWindow != d->active && d->active->windowWidget() &&
533 d->active->windowWidget()->testWFlags( WStyle_MinMax ) &&
534 !d->active->windowWidget()->testWFlags( WStyle_Tool ) ) {
535 d->active->windowWidget()->showMaximized();
536 if ( d->maxtools ) {
537#ifndef QT_NO_WIDGET_TOPEXTRA
538 if ( w->icon() ) {
539 QPixmap pm(*w->icon());
540 int iconSize = d->maxtools->size().height();
541 if(pm.width() > iconSize || pm.height() > iconSize) {
542 QImage im;
543 im = pm;
544 pm = im.smoothScale( QMIN(iconSize, pm.width()), QMIN(iconSize, pm.height()) );
545 }
546 d->maxtools->setPixmap( pm );
547 } else
548#endif
549 {
550 QPixmap pm(14,14);
551 pm.fill( color1 );
552 pm.setMask(pm.createHeuristicMask());
553 d->maxtools->setPixmap( pm );
554 }
555 }
556 }
557
558 d->active->internalRaise();
559
560 if ( change_focus ) {
561 if ( d->focus.find( d->active ) >=0 ) {
562 d->focus.removeRef( d->active );
563 d->focus.append( d->active );
564 }
565 }
566
567 updateWorkspace();
568 emit windowActivated( w );
569}
570
571
572/*!
573 Returns the active window, or 0 if no window is active.
574*/
575QWidget* QWorkspace::activeWindow() const
576{
577 return d->active?d->active->windowWidget():0;
578}
579
580
581void QWorkspace::place( QWidget* w)
582{
583 QPtrList<QWidget> widgets;
584 for(QPtrListIterator<QWorkspaceChild> it( d->windows ); it.current(); ++it)
585 if ((*it) != w)
586 widgets.append((*it));
587
588 if(d->wmode == TopLevel) {
589 for(QPtrListIterator<QDockWindow> it( d->dockwindows ); it.current(); ++it)
590 if ((*it) != w)
591 widgets.append((*it));
592 }
593
594 int overlap, minOverlap = 0;
595 int possible;
596
597 QRect r1(0, 0, 0, 0);
598 QRect r2(0, 0, 0, 0);
599 QRect maxRect = rect();
600 if(d->wmode == TopLevel) {
601 const QDesktopWidget *dw = qApp->desktop();
602 maxRect = dw->availableGeometry(dw->screenNumber(topLevelWidget()));
603 }
604 int x = maxRect.left(), y = maxRect.top();
605 QPoint wpos(maxRect.left(), maxRect.top());
606
607 bool firstPass = TRUE;
608
609 do {
610 if ( y + w->height() > maxRect.bottom() ) {
611 overlap = -1;
612 } else if( x + w->width() > maxRect.right() ) {
613 overlap = -2;
614 } else {
615 overlap = 0;
616
617 r1.setRect(x, y, w->width(), w->height());
618
619 QWidget *l;
620 QPtrListIterator<QWidget> it( widgets );
621 while ( it.current () ) {
622 l = it.current();
623 ++it;
624
625 if ( d->maxWindow == l )
626 r2 = d->maxRestore;
627 else
628 r2.setRect(l->x(), l->y(), l->width(), l->height());
629
630 if (r2.intersects(r1)) {
631 r2.setCoords(QMAX(r1.left(), r2.left()),
632 QMAX(r1.top(), r2.top()),
633 QMIN(r1.right(), r2.right()),
634 QMIN(r1.bottom(), r2.bottom())
635 );
636
637 overlap += (r2.right() - r2.left()) *
638 (r2.bottom() - r2.top());
639 }
640 }
641 }
642
643 if (overlap == 0) {
644 wpos = QPoint(x, y);
645 break;
646 }
647
648 if (firstPass) {
649 firstPass = FALSE;
650 minOverlap = overlap;
651 } else if ( overlap >= 0 && overlap < minOverlap) {
652 minOverlap = overlap;
653 wpos = QPoint(x, y);
654 }
655
656 if ( overlap > 0 ) {
657 possible = maxRect.right();
658 if ( possible - w->width() > x) possible -= w->width();
659
660 QWidget *l;
661 QPtrListIterator<QWidget> it( widgets );
662 while ( it.current () ) {
663 l = it.current();
664 ++it;
665 if ( d->maxWindow == l )
666 r2 = d->maxRestore;
667 else
668 r2.setRect(l->x(), l->y(), l->width(), l->height());
669
670 if( ( y < r2.bottom() ) && ( r2.top() < w->height() + y ) ) {
671 if( r2.right() > x )
672 possible = possible < r2.right() ?
673 possible : r2.right();
674
675 if( r2.left() - w->width() > x )
676 possible = possible < r2.left() - w->width() ?
677 possible : r2.left() - w->width();
678 }
679 }
680
681 x = possible;
682 } else if ( overlap == -2 ) {
683 x = maxRect.left();
684 possible = maxRect.bottom();
685
686 if ( possible - w->height() > y ) possible -= w->height();
687
688 QWidget *l;
689 QPtrListIterator<QWidget> it( widgets );
690 while ( it.current () ) {
691 l = it.current();
692 ++it;
693 if ( d->maxWindow == l )
694 r2 = d->maxRestore;
695 else
696 r2.setRect(l->x(), l->y(), l->width(), l->height());
697
698 if( r2.bottom() > y)
699 possible = possible < r2.bottom() ?
700 possible : r2.bottom();
701
702 if( r2.top() - w->height() > y )
703 possible = possible < r2.top() - w->height() ?
704 possible : r2.top() - w->height();
705 }
706
707 y = possible;
708 }
709 }
710 while( overlap != 0 && overlap != -1 );
711
712#if 0
713 if(windowMode() == QWorkspace::TopLevel && wpos.y()) {
714 QPoint fr = w->topLevelWidget()->frameGeometry().topLeft(),
715 r = w->topLevelWidget()->geometry().topLeft();
716 wpos += QPoint(r.x() - fr.x(), r.y() - fr.y());
717 }
718#endif
719 w->move(wpos);
720 updateWorkspace();
721}
722
723
724void QWorkspace::insertIcon( QWidget* w )
725{
726 if ( !w || d->icons.contains( w ) )
727 return;
728 d->icons.append( w );
729 if (w->parentWidget() != this )
730 w->reparent( this, 0, QPoint(0,0), FALSE);
731 QRect cr = updateWorkspace();
732 int x = 0;
733 int y = cr.height() - w->height();
734
735 QPtrListIterator<QWidget> it( d->icons );
736 while ( it.current () ) {
737 QWidget* i = it.current();
738 ++it;
739 if ( x > 0 && x + i->width() > cr.width() ){
740 x = 0;
741 y -= i->height();
742 }
743
744 if ( i != w &&
745 i->geometry().intersects( QRect( x, y, w->width(), w->height() ) ) )
746 x += i->width();
747 }
748 w->move( x, y );
749
750 if ( isVisibleTo( parentWidget() ) ) {
751 w->show();
752 w->lower();
753 }
754 updateWorkspace();
755}
756
757
758void QWorkspace::removeIcon( QWidget* w)
759{
760 if ( !d->icons.contains( w ) )
761 return;
762 d->icons.remove( w );
763 w->hide();
764}
765
766
767/*! \reimp */
768void QWorkspace::resizeEvent( QResizeEvent * )
769{
770 if ( d->maxWindow ) {
771 d->maxWindow->adjustToFullscreen();
772 if (d->maxWindow->windowWidget())
773 ((QWorkspace*)d->maxWindow->windowWidget())->setWState( WState_Maximized );
774 }
775
776 QRect cr = updateWorkspace();
777
778 QPtrListIterator<QWorkspaceChild> it( d->windows );
779 while ( it.current () ) {
780 QWorkspaceChild* c = it.current();
781 ++it;
782 if ( c->windowWidget() && !c->windowWidget()->testWFlags( WStyle_Tool ) )
783 continue;
784
785 int x = c->x();
786 int y = c->y();
787 if ( c->snappedDown )
788 y = cr.height() - c->height();
789 if ( c->snappedRight )
790 x = cr.width() - c->width();
791
792 if ( x != c->x() || y != c->y() )
793 c->move( x, y );
794 }
795
796}
797
798void QWorkspace::handleUndock(QDockWindow *w)
799{
800 const QDesktopWidget *dw = qApp->desktop();
801 QRect maxRect = dw->availableGeometry(dw->screenNumber(d->mainwindow));
802 QPoint wpos(maxRect.left(), maxRect.top());
803 int possible = 0;
804 if(!::qt_cast<QToolBar*>(w)) {
805 struct place_score { int o, x, y; } score = {0, 0, 0};
806 int left = 1, x = wpos.x(), y = wpos.y();
807 QPtrListIterator<QDockWindow> it( d->dockwindows );
808 while(1) {
809 if(y + w->height() > maxRect.bottom()) {
810 if(left) {
811 x = maxRect.right() - w->width();
812 y = maxRect.top();
813 left = 0;
814 } else {
815 break;
816 }
817 }
818
819 QDockWindow *l, *nearest = NULL, *furthest;
820 for ( it.toFirst(); it.current(); ++it ) {
821 l = it.current();
822 if ( l != w && y == l->y() ) {
823 if(!nearest) {
824 nearest = l;
825 } else if(l->x() == x) {
826 nearest = l;
827 break;
828 } else if(left && (l->x() - x) < (nearest->x() - x)) {
829 nearest = l;
830 } else if(!left && (x - l->x()) < (x - nearest->x())) {
831 nearest = l;
832 }
833 }
834 }
835 QRect r2(x, y, w->width(), w->height());
836 if(!nearest || !nearest->geometry().intersects(r2)) {
837 wpos = QPoint(x, y); //best possible outcome
838 possible = 2;
839 break;
840 }
841
842 QDockWindow *o = NULL;
843 int overlap = 0;
844 for( it.toFirst(); it.current(); ++it ) {
845 l = it.current();
846 if ( l != w && l->geometry().intersects(QRect(QPoint(x, y), w->size()))) {
847 overlap++;
848 o = l;
849 }
850 }
851 if(o && overlap == 1 && w->isVisible() && !o->isVisible()) {
852 wpos = QPoint(x, y);
853 possible = 2;
854 while(d->dockwindows.remove(o));
855 d->newdocks.append(o);
856 if(d->newdocks.count() == 1)
857 QTimer::singleShot(0, this, SLOT(dockWindowsShow()));
858 break;
859 }
860
861 for ( furthest = nearest, it.toFirst(); it.current(); ++it ) {
862 l = it.current();
863 if ( l != w && l->y() == nearest->y() &&
864 ((left && (l->x() == nearest->x() + nearest->width())) ||
865 (!left && (l->x() + l->width() == nearest->x()) )))
866 furthest = l;
867 }
868 if(left)
869 x = furthest->x() + furthest->width();
870 else
871 x = furthest->x() - w->width();
872
873 QPoint sc_pt(x, y);
874 place_score sc;
875 if(left)
876 sc.x = (x + w->width()) * 2;
877 else
878 sc.x = ((maxRect.width() - x) * 2) + 1;
879 sc.y = sc_pt.y();
880 for( sc.o = 0, it.toFirst(); it.current(); ++it ) {
881 l = it.current();
882 if ( l != w && l->geometry().intersects(QRect(sc_pt, w->size())))
883 sc.o++;
884 }
885 if(maxRect.contains(QRect(sc_pt, w->size())) &&
886 (!possible || (sc.o < score.o) ||
887 ((score.o || sc.o == score.o) && score.x < sc.x))) {
888 wpos = sc_pt;
889 score = sc;
890 possible = 1;
891 }
892 y += nearest->height();
893 if(left)
894 x = maxRect.x();
895 else
896 x = maxRect.right() - w->width();
897 }
898 if(!possible || (possible == 1 && score.o)) { //fallback to less knowledgeable function
899 place(w);
900 wpos = w->pos();
901 }
902 }
903
904 bool ishidden = w->isHidden();
905 QSize olds(w->size());
906 if(w->place() == QDockWindow::InDock)
907 w->undock();
908 w->move(wpos);
909 w->resize(olds);
910 if(!ishidden)
911 w->show();
912 else
913 w->hide();
914}
915
916void QWorkspace::dockWindowsShow()
917{
918 QPtrList<QDockWindow> lst = d->newdocks;
919 d->newdocks.clear();
920 for(QPtrListIterator<QDockWindow> dw_it(lst); (*dw_it); ++dw_it) {
921 if(d->dockwindows.find((*dw_it)) != -1)
922 continue;
923 handleUndock((*dw_it));
924 d->dockwindows.append((*dw_it));
925 }
926}
927
928/*! \reimp */
929void QWorkspace::showEvent( QShowEvent *e )
930{
931 /* This is all magic, be carefull when playing with this code - this tries to allow people to
932 use QWorkspace as a high level abstraction for window management, but removes enforcement that
933 QWorkspace be used as an MDI. */
934 if(d->wmode == AutoDetect) {
935 d->wmode = MDI;
936 QWidget *o = topLevelWidget();
937 if(::qt_cast<QMainWindow*>(o)) {
938 d->wmode = TopLevel;
939 const QObjectList *c = o->children();
940 for(QObjectListIt it(*c); it; ++it) {
941 if((*it)->isWidgetType() && !((QWidget *)(*it))->isTopLevel() &&
942 !::qt_cast<QHBox*>(*it) && !::qt_cast<QVBox*>(*it) &&
943 !::qt_cast<QWorkspaceChild*>(*it) && !(*it)->inherits("QHideDock") &&
944 !::qt_cast<QDockArea*>(*it) && !::qt_cast<QWorkspace*>(*it) &&
945 !::qt_cast<QMenuBar*>(*it) && !::qt_cast<QStatusBar*>(*it)) {
946 d->wmode = MDI;
947 break;
948 }
949 }
950 }
951 }
952 if(d->wmode == TopLevel) {
953 QWidget *o = topLevelWidget();
954 d->mainwindow = ::qt_cast<QMainWindow*>(o);
955 const QObjectList children = *o->children();
956 for(QObjectListIt it(children); it; ++it) {
957 if(!(*it)->isWidgetType())
958 continue;
959 QWidget *w = (QWidget *)(*it);
960 if(w->isTopLevel())
961 continue;
962 if(::qt_cast<QDockArea*>(w)) {
963 const QObjectList *dock_c = w->children();
964 if(dock_c) {
965 QPtrList<QToolBar> tb_list;
966 for(QObjectListIt dock_it(*dock_c); dock_it; ++dock_it) {
967 if(!(*dock_it)->isWidgetType())
968 continue;
969 if(::qt_cast<QToolBar*>(*dock_it)) {
970 tb_list.append((QToolBar *)(*dock_it));
971 } else if (::qt_cast<QDockWindow*>(*dock_it)) {
972 QDockWindow *dw = (QDockWindow*)(*dock_it);
973 dw->move(dw->mapToGlobal(QPoint(0, 0)));
974 d->newdocks.append(dw);
975 } else {
976 qDebug("not sure what to do with %s %s", (*dock_it)->className(),
977 (*dock_it)->name());
978 }
979 }
980 if(tb_list.count() == 1) {
981 QToolBar *tb = tb_list.first();
982 tb->move(0, 0);
983 d->newdocks.prepend(tb);
984 } else if(tb_list.count()) {
985 QDockWindow *dw = new QDockWindow(QDockWindow::OutsideDock,
986 w->parentWidget(),
987 QString("QMagicDock_") + w->name());
988 dw->installEventFilter(this);
989 dw->setResizeEnabled(TRUE);
990 dw->setCloseMode( QDockWindow::Always );
991 dw->setResizeEnabled(FALSE);
992#ifndef QT_NO_WIDGET_TOPEXTRA
993 dw->setCaption(o->caption());
994#endif
995 QSize os(w->size());
996 if(w->layout() && w->layout()->hasHeightForWidth()) {
997 w->layout()->invalidate();
998 os.setHeight(w->layout()->heightForWidth(os.width()));
999 }
1000 if(!w->isHidden())
1001 dw->show();
1002 w->reparent(dw, QPoint(0, 0));
1003 dw->setWidget(w);
1004 dw->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
1005 dw->setGeometry(0, 0, os.width(), os.height() + dw->sizeHint().height());
1006 d->newdocks.prepend(dw);
1007 ((QDockArea*)w)->setAcceptDockWindow(dw, FALSE);
1008 w->show();
1009 }
1010 }
1011 w->installEventFilter(this);
1012 } else if(::qt_cast<QStatusBar*>(w)) {
1013 if(activeWindow()) {
1014 QWorkspaceChild *c;
1015 if ( ( c = findChild(activeWindow()) ) )
1016 c->setStatusBar((QStatusBar*)w);
1017 }
1018 } else if(::qt_cast<QWorkspaceChild*>(w)) {
1019 w->reparent(this, w->testWFlags(~(0)) | WType_TopLevel, w->pos());
1020 }
1021 }
1022 dockWindowsShow(); //now place and undock windows discovered
1023
1024 QWidget *w = new QWidget(NULL, "QDoesNotExist",
1025 WType_Dialog | WStyle_Customize | WStyle_NoBorder);
1026// if(qApp->mainWidget() == o)
1027// QObject::connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
1028 QDesktopWidget *dw = QApplication::desktop();
1029 w->setGeometry(dw->availableGeometry(dw->screenNumber(o)));
1030 o->reparent(w, QPoint(0, 0), TRUE);
1031 {
1032 QMenuBar *mb = 0;
1033 if(::qt_cast<QMainWindow*>(o))
1034 mb = ((QMainWindow *)o)->menuBar();
1035 if(!mb)
1036 mb = (QMenuBar*)o->child(NULL, "QMenuBar");
1037 if(mb)
1038 mb->reparent(w, QPoint(0, 0));
1039 }
1040 reparent(w, QPoint(0,0));
1041 setGeometry(0, 0, w->width(), w->height());
1042#if 0
1043 /* Hide really isn't acceptable because I need to make the rest of Qt
1044 think it is visible, so instead I set it to an empty mask. I'm not
1045 sure what problems this is going to create, hopefully everything will
1046 be happy (or not even notice since this is mostly intended for Qt/Mac) */
1047// w->setMask(QRegion());
1048// w->show();
1049#else
1050 w->hide();
1051#endif
1052 }
1053
1054 //done with that nastiness, on with your regularly schedueled programming..
1055 if ( d->maxWindow && !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
1056 showMaximizeControls();
1057 QWidget::showEvent( e );
1058 if ( d->becomeActive ) {
1059 activateWindow( d->becomeActive );
1060 d->becomeActive = 0;
1061 }
1062 else if ( d->windows.count() > 0 && !d->active )
1063 activateWindow( d->windows.first()->windowWidget() );
1064
1065 updateWorkspace();
1066}
1067
1068/*! \reimp */
1069void QWorkspace::hideEvent( QHideEvent * )
1070{
1071 if ( !isVisibleTo(0) && !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
1072 hideMaximizeControls();
1073}
1074
1075void QWorkspace::minimizeWindow( QWidget* w)
1076{
1077 QWorkspaceChild* c = findChild( w );
1078
1079 if ( !w || w && (!w->testWFlags( WStyle_Minimize ) || w->testWFlags( WStyle_Tool) ) )
1080 return;
1081
1082 if ( c ) {
1083 QWorkspace *fake = (QWorkspace*)w;
1084
1085 setUpdatesEnabled( FALSE );
1086 bool wasMax = FALSE;
1087 if ( c == d->maxWindow ) {
1088 wasMax = TRUE;
1089 d->maxWindow = 0;
1090 inCaptionChange = TRUE;
1091#ifndef QT_NO_WIDGET_TOPEXTRA
1092 if ( !!d->topCaption )
1093 topLevelWidget()->setCaption( d->topCaption );
1094#endif
1095 inCaptionChange = FALSE;
1096 if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this) )
1097 hideMaximizeControls();
1098 for (QPtrListIterator<QWorkspaceChild> it( d->windows ); it.current(); ++it ) {
1099 QWorkspaceChild* c = it.current();
1100 if ( c->titlebar )
1101 c->titlebar->setMovable( TRUE );
1102 c->widgetResizeHandler->setActive( TRUE );
1103 }
1104 }
1105 insertIcon( c->iconWidget() );
1106 c->hide();
1107 if ( wasMax )
1108 c->setGeometry( d->maxRestore );
1109 d->focus.append( c );
1110
1111 setUpdatesEnabled( TRUE );
1112 updateWorkspace();
1113
1114 fake->clearWState( WState_Maximized );
1115 fake->setWState( WState_Minimized );
1116 c->clearWState( WState_Maximized );
1117 c->setWState( WState_Minimized );
1118 }
1119}
1120
1121void QWorkspace::normalizeWindow( QWidget* w)
1122{
1123 QWorkspaceChild* c = findChild( w );
1124 if ( !w )
1125 return;
1126 if ( c ) {
1127 QWorkspace *fake = (QWorkspace*)w;
1128 fake->clearWState( WState_Minimized | WState_Maximized );
1129 if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this) && d->maxWindow ) {
1130 hideMaximizeControls();
1131 } else {
1132 if ( w->minimumSize() != w->maximumSize() )
1133 c->widgetResizeHandler->setActive( TRUE );
1134 if ( c->titlebar )
1135 c->titlebar->setMovable(TRUE);
1136 }
1137 fake->clearWState( WState_Minimized | WState_Maximized );
1138 c->clearWState( WState_Minimized | WState_Maximized );
1139
1140 if ( c == d->maxWindow ) {
1141 c->setGeometry( d->maxRestore );
1142 d->maxWindow = 0;
1143#ifndef QT_NO_WIDGET_TOPEXTRA
1144 inCaptionChange = TRUE;
1145 if ( !!d->topCaption )
1146 topLevelWidget()->setCaption( d->topCaption );
1147 inCaptionChange = FALSE;
1148#endif
1149 } else {
1150 if ( c->iconw )
1151 removeIcon( c->iconw->parentWidget() );
1152 c->show();
1153 }
1154
1155 if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
1156 hideMaximizeControls();
1157 for (QPtrListIterator<QWorkspaceChild> it( d->windows ); it.current(); ++it ) {
1158 QWorkspaceChild* c = it.current();
1159 if ( c->titlebar )
1160 c->titlebar->setMovable( TRUE );
1161 if ( c->childWidget && c->childWidget->minimumSize() != c->childWidget->maximumSize() )
1162 c->widgetResizeHandler->setActive( TRUE );
1163 }
1164 activateWindow( w, TRUE );
1165 updateWorkspace();
1166 }
1167}
1168
1169void QWorkspace::maximizeWindow( QWidget* w)
1170{
1171 QWorkspaceChild* c = findChild( w );
1172
1173 if ( !w || w && (!w->testWFlags( WStyle_Maximize ) || w->testWFlags( WStyle_Tool) ) )
1174 return;
1175
1176 if ( c ) {
1177 setUpdatesEnabled( FALSE );
1178 if (c->iconw && d->icons.contains( c->iconw->parentWidget() ) )
1179 normalizeWindow( w );
1180 QWorkspace *fake = (QWorkspace*)w;
1181
1182 QRect r( c->geometry() );
1183 c->adjustToFullscreen();
1184 c->show();
1185 c->internalRaise();
1186 qApp->sendPostedEvents( c, QEvent::Resize );
1187 qApp->sendPostedEvents( c, QEvent::Move );
1188 qApp->sendPostedEvents( c, QEvent::ShowWindowRequest );
1189 if ( d->maxWindow != c ) {
1190 if ( d->maxWindow )
1191 d->maxWindow->setGeometry( d->maxRestore );
1192 d->maxWindow = c;
1193 d->maxRestore = r;
1194 }
1195
1196 activateWindow( w );
1197 if(!style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
1198 showMaximizeControls();
1199 } else {
1200 c->widgetResizeHandler->setActive( FALSE );
1201 if ( c->titlebar )
1202 c->titlebar->setMovable( FALSE );
1203 }
1204#ifndef QT_NO_WIDGET_TOPEXTRA
1205 inCaptionChange = TRUE;
1206 if ( !!d->topCaption )
1207 topLevelWidget()->setCaption( tr("%1 - [%2]")
1208 .arg(d->topCaption).arg(c->caption()) );
1209 inCaptionChange = FALSE;
1210#endif
1211 setUpdatesEnabled( TRUE );
1212
1213 updateWorkspace();
1214
1215 fake->clearWState( WState_Minimized );
1216 fake->setWState( WState_Maximized );
1217 c->clearWState( WState_Minimized );
1218 c->setWState( WState_Maximized );
1219 }
1220}
1221
1222void QWorkspace::showWindow( QWidget* w)
1223{
1224 if ( d->maxWindow && w->testWFlags( WStyle_Maximize ) && !w->testWFlags( WStyle_Tool) )
1225 maximizeWindow( w );
1226 else if ( !w->testWFlags( WStyle_Tool ) )
1227 normalizeWindow( w );
1228 else
1229 w->parentWidget()->show();
1230 if ( d->maxWindow )
1231 d->maxWindow->internalRaise();
1232 updateWorkspace();
1233}
1234
1235
1236QWorkspaceChild* QWorkspace::findChild( QWidget* w)
1237{
1238 QPtrListIterator<QWorkspaceChild> it( d->windows );
1239 while ( it.current () ) {
1240 QWorkspaceChild* c = it.current();
1241 ++it;
1242 if (c->windowWidget() == w)
1243 return c;
1244 }
1245 return 0;
1246}
1247
1248/*!
1249 \obsolete
1250 \overload
1251 */
1252QWidgetList QWorkspace::windowList() const
1253{
1254 return windowList( CreationOrder );
1255}
1256
1257/*!
1258 Returns a list of all windows. If \a order is CreationOrder
1259 (the default) the windows are listed in the order in which they
1260 had been inserted into the workspace. If \a order is StackingOrder
1261 the windows are listed in their stacking order, with the topmost window
1262 being the last window in the list.
1263*/
1264QWidgetList QWorkspace::windowList( WindowOrder order ) const
1265{
1266 QWidgetList windows;
1267 if ( order == StackingOrder ) {
1268 const QObjectList *cl = children();
1269 if ( cl ) {
1270 QObjectListIt it( *cl );
1271 while (it.current()) {
1272 QObject *o = it.current();
1273 ++it;
1274 QWorkspaceChild *c = ::qt_cast<QWorkspaceChild*>(o);
1275 if (c && c->windowWidget())
1276 windows.append(c->windowWidget());
1277 }
1278 }
1279 } else {
1280 QPtrListIterator<QWorkspaceChild> it( d->windows );
1281 while (it.current()) {
1282 QWorkspaceChild* c = it.current();
1283 ++it;
1284 if ( c->windowWidget() )
1285 windows.append( c->windowWidget() );
1286 }
1287 }
1288 return windows;
1289}
1290
1291/*!\reimp*/
1292bool QWorkspace::eventFilter( QObject *o, QEvent * e)
1293{
1294 if(d->wmode == TopLevel && d->mainwindow && o->parent() == d->mainwindow) {
1295 if((e->type() == QEvent::ChildInserted || e->type() == QEvent::Reparent) &&
1296 ::qt_cast<QDockArea*>(o) && !((QWidget*)o)->isVisible()) {
1297 QChildEvent *ce = (QChildEvent*)e;
1298 if(!::qt_cast<QDockWindow*>(ce->child())) {
1299 qDebug("No idea what to do..");
1300 return FALSE;
1301 }
1302 QDockWindow *w = (QDockWindow*)ce->child();
1303 if(d->newdocks.find(w) == -1 && d->dockwindows.find(w) == -1) {
1304 if(::qt_cast<QToolBar*>(w))
1305 d->newdocks.prepend(w);
1306 else
1307 d->newdocks.append(w);
1308 if(d->newdocks.count() == 1)
1309 QTimer::singleShot(0, this, SLOT(dockWindowsShow()));
1310 }
1311 } else if(e->type() == QEvent::Hide && !e->spontaneous() && !qstrncmp(o->name(), "QMagicDock_", 11)) {
1312// d->mainwindow->close();
1313 }
1314 return QWidget::eventFilter(o, e);
1315 }
1316
1317 static QTime* t = 0;
1318 static QWorkspace* tc = 0;
1319#ifndef QT_NO_MENUBAR
1320 if ( o == d->maxtools && d->menuId != -1 ) {
1321 switch ( e->type() ) {
1322 case QEvent::MouseButtonPress:
1323 {
1324 QMenuBar* b = (QMenuBar*)o->parent();
1325 if ( !t )
1326 t = new QTime;
1327 if ( tc != this || t->elapsed() > QApplication::doubleClickInterval() ) {
1328 if ( QApplication::reverseLayout() ) {
1329 QPoint p = b->mapToGlobal( QPoint( b->x() + b->width(), b->y() + b->height() ) );
1330 p.rx() -= d->popup->sizeHint().width();
1331 popupOperationMenu( p );
1332 } else {
1333 popupOperationMenu( b->mapToGlobal( QPoint( b->x(), b->y() + b->height() ) ) );
1334 }
1335 t->start();
1336 tc = this;
1337 } else {
1338 tc = 0;
1339 closeActiveWindow();
1340 }
1341 return TRUE;
1342 }
1343 default:
1344 break;
1345 }
1346 return QWidget::eventFilter( o, e );
1347 }
1348#endif
1349 switch ( e->type() ) {
1350 case QEvent::Hide:
1351 case QEvent::HideToParent:
1352 if ( !o->isA( "QWorkspaceChild" ) || !isVisible() || e->spontaneous() )
1353 break;
1354 if ( d->active == o ) {
1355 int a = d->focus.find( d->active );
1356 for ( ;; ) {
1357 if ( --a < 0 )
1358 a = d->focus.count()-1;
1359 QWorkspaceChild* c = d->focus.at( a );
1360 if ( !c || c == o ) {
1361 if ( c && c->iconw && d->icons.contains( c->iconw->parentWidget() ) )
1362 break;
1363 activateWindow( 0 );
1364 break;
1365 }
1366 if ( c->isShown() ) {
1367 activateWindow( c->windowWidget(), FALSE );
1368 break;
1369 }
1370 }
1371 }
1372 d->focus.removeRef( (QWorkspaceChild*)o );
1373 if ( d->maxWindow == o && d->maxWindow->isHidden() ) {
1374 d->maxWindow->setGeometry( d->maxRestore );
1375 d->maxWindow = 0;
1376 if ( d->active )
1377 maximizeWindow( d->active );
1378
1379 if ( !d->maxWindow ) {
1380
1381 if ( style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
1382 QWorkspaceChild *wc = (QWorkspaceChild *)o;
1383 wc->widgetResizeHandler->setActive( TRUE );
1384 if ( wc->titlebar )
1385 wc->titlebar->setMovable( TRUE );
1386 } else {
1387 hideMaximizeControls();
1388 }
1389#ifndef QT_NO_WIDGET_TOPEXTRA
1390 inCaptionChange = TRUE;
1391 if ( !!d->topCaption )
1392 topLevelWidget()->setCaption( d->topCaption );
1393 inCaptionChange = FALSE;
1394#endif
1395 }
1396 }
1397 updateWorkspace();
1398 break;
1399 case QEvent::Show:
1400 if ( o->isA("QWorkspaceChild") && !d->focus.containsRef( (QWorkspaceChild*)o ) )
1401 d->focus.append( (QWorkspaceChild*)o );
1402 updateWorkspace();
1403 break;
1404 case QEvent::CaptionChange:
1405 if ( inCaptionChange )
1406 break;
1407
1408#ifndef QT_NO_WIDGET_TOPEXTRA
1409 inCaptionChange = TRUE;
1410 if ( o == topLevelWidget() ) {
1411 QWidget *tlw = (QWidget*)o;
1412 if ( !d->maxWindow
1413 || tlw->caption() != tr("%1 - [%2]").arg(d->topCaption).arg(d->maxWindow->caption()) )
1414 d->topCaption = tlw->caption();
1415 }
1416
1417 if ( d->maxWindow && !!d->topCaption )
1418 topLevelWidget()->setCaption( tr("%1 - [%2]")
1419 .arg(d->topCaption).arg(d->maxWindow->caption()));
1420 inCaptionChange = FALSE;
1421#endif
1422
1423 break;
1424 case QEvent::Close:
1425 if ( o == topLevelWidget() )
1426 {
1427 QPtrListIterator<QWorkspaceChild> it( d->windows );
1428 while ( it.current () ) {
1429 QWorkspaceChild* c = it.current();
1430 ++it;
1431 if ( c->shademode )
1432 c->showShaded();
1433 }
1434 } else if ( ::qt_cast<QWorkspaceChild*>(o) ) {
1435 d->popup->hide();
1436 }
1437 updateWorkspace();
1438 break;
1439 default:
1440 break;
1441 }
1442 return QWidget::eventFilter( o, e);
1443}
1444
1445void QWorkspace::showMaximizeControls()
1446{
1447#ifndef QT_NO_MENUBAR
1448 Q_ASSERT(d->maxWindow);
1449 QMenuBar* b = 0;
1450
1451 // Do a breadth-first search first on every parent,
1452 QWidget* w = parentWidget();
1453 QObjectList * l = 0;
1454 while ( !l && w ) {
1455 l = w->queryList( "QMenuBar", 0, FALSE, FALSE );
1456 w = w->parentWidget();
1457 if ( l && !l->count() ) {
1458 delete l;
1459 l = 0;
1460 }
1461 }
1462
1463 // and query recursively if nothing is found.
1464 if ( !l || !l->count() ) {
1465 if ( l )
1466 delete l;
1467 l = topLevelWidget()->queryList( "QMenuBar", 0, 0, TRUE );
1468 }
1469 if ( l && l->count() )
1470 b = (QMenuBar *)l->first();
1471 delete l;
1472
1473 if ( !b )
1474 return;
1475
1476 if ( !d->maxcontrols ) {
1477 d->maxmenubar = b;
1478 d->maxcontrols = new QFrame( topLevelWidget(), "qt_maxcontrols" );
1479 QHBoxLayout* l = new QHBoxLayout( d->maxcontrols,
1480 d->maxcontrols->frameWidth(), 0 );
1481 if ( d->maxWindow->windowWidget() &&
1482 d->maxWindow->windowWidget()->testWFlags(WStyle_Minimize) ) {
1483 QToolButton* iconB = new QToolButton( d->maxcontrols, "iconify" );
1484#ifndef QT_NO_TOOLTIP
1485 QToolTip::add( iconB, tr( "Minimize" ) );
1486#endif
1487 l->addWidget( iconB );
1488 iconB->setFocusPolicy( NoFocus );
1489 iconB->setIconSet(style().stylePixmap(QStyle::SP_TitleBarMinButton));
1490 iconB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1491 connect( iconB, SIGNAL( clicked() ),
1492 this, SLOT( minimizeActiveWindow() ) );
1493 }
1494
1495 QToolButton* restoreB = new QToolButton( d->maxcontrols, "restore" );
1496#ifndef QT_NO_TOOLTIP
1497 QToolTip::add( restoreB, tr( "Restore Down" ) );
1498#endif
1499 l->addWidget( restoreB );
1500 restoreB->setFocusPolicy( NoFocus );
1501 restoreB->setIconSet( style().stylePixmap(QStyle::SP_TitleBarNormalButton));
1502 restoreB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1503 connect( restoreB, SIGNAL( clicked() ),
1504 this, SLOT( normalizeActiveWindow() ) );
1505
1506 l->addSpacing( 2 );
1507 QToolButton* closeB = new QToolButton( d->maxcontrols, "close" );
1508#ifndef QT_NO_TOOLTIP
1509 QToolTip::add( closeB, tr( "Close" ) );
1510#endif
1511 l->addWidget( closeB );
1512 closeB->setFocusPolicy( NoFocus );
1513 closeB->setIconSet( style().stylePixmap(QStyle::SP_TitleBarCloseButton) );
1514 closeB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1515 connect( closeB, SIGNAL( clicked() ),
1516 this, SLOT( closeActiveWindow() ) );
1517
1518 d->maxcontrols->setFixedSize( d->maxcontrols->minimumSizeHint() );
1519 }
1520
1521 if ( d->controlId == -1 || b->indexOf( d->controlId ) == -1 ) {
1522 QFrame* dmaxcontrols = d->maxcontrols;
1523 d->controlId = b->insertItem( dmaxcontrols, -1, b->count() );
1524 }
1525 if ( !d->active && d->becomeActive ) {
1526 d->active = (QWorkspaceChild*)d->becomeActive->parentWidget();
1527 d->active->setActive( TRUE );
1528 d->becomeActive = 0;
1529 emit windowActivated( d->active->windowWidget() );
1530 }
1531 if ( d->active && ( d->menuId == -1 || b->indexOf( d->menuId ) == -1 ) ) {
1532 if ( !d->maxtools ) {
1533 d->maxtools = new QLabel( topLevelWidget(), "qt_maxtools" );
1534 d->maxtools->installEventFilter( this );
1535 }
1536#ifndef QT_NO_WIDGET_TOPEXTRA
1537 if ( d->active->windowWidget() && d->active->windowWidget()->icon() ) {
1538 QPixmap pm(*d->active->windowWidget()->icon());
1539 int iconSize = d->maxtools->size().height();
1540 if(pm.width() > iconSize || pm.height() > iconSize) {
1541 QImage im;
1542 im = pm;
1543 pm = im.smoothScale( QMIN(iconSize, pm.width()), QMIN(iconSize, pm.height()) );
1544 }
1545 d->maxtools->setPixmap( pm );
1546 } else
1547#endif
1548 {
1549 QPixmap pm(14,14);
1550 pm.fill( color1 );
1551 pm.setMask(pm.createHeuristicMask());
1552 d->maxtools->setPixmap( pm );
1553 }
1554 d->menuId = b->insertItem( d->maxtools, -1, 0 );
1555 }
1556#endif
1557}
1558
1559
1560void QWorkspace::hideMaximizeControls()
1561{
1562#ifndef QT_NO_MENUBAR
1563 if ( d->maxmenubar ) {
1564 int mi = d->menuId;
1565 if ( mi != -1 ) {
1566 if ( d->maxmenubar->indexOf( mi ) != -1 )
1567 d->maxmenubar->removeItem( mi );
1568 d->maxtools = 0;
1569 }
1570 int ci = d->controlId;
1571 if ( ci != -1 && d->maxmenubar->indexOf( ci ) != -1 )
1572 d->maxmenubar->removeItem( ci );
1573 }
1574 d->maxcontrols = 0;
1575 d->menuId = -1;
1576 d->controlId = -1;
1577#endif
1578}
1579
1580/*!
1581 Closes the child window that is currently active.
1582
1583 \sa closeAllWindows()
1584*/
1585void QWorkspace::closeActiveWindow()
1586{
1587 setUpdatesEnabled( FALSE );
1588 if ( d->maxWindow && d->maxWindow->windowWidget() )
1589 d->maxWindow->windowWidget()->close();
1590 else if ( d->active && d->active->windowWidget() )
1591 d->active->windowWidget()->close();
1592 setUpdatesEnabled( TRUE );
1593 updateWorkspace();
1594}
1595
1596/*!
1597 Closes all child windows.
1598
1599 The windows are closed in random order. The operation stops if a
1600 window does not accept the close event.
1601
1602 \sa closeActiveWindow()
1603*/
1604void QWorkspace::closeAllWindows()
1605{
1606 bool did_close = TRUE;
1607 QPtrListIterator<QWorkspaceChild> it( d->windows );
1608 QWorkspaceChild *c = 0;
1609 while ( ( c = it.current() ) && did_close ) {
1610 ++it;
1611 if ( c->windowWidget() )
1612 did_close = c->windowWidget()->close();
1613 }
1614}
1615
1616void QWorkspace::normalizeActiveWindow()
1617{
1618 if ( d->maxWindow )
1619 d->maxWindow->showNormal();
1620 else if ( d->active )
1621 d->active->showNormal();
1622}
1623
1624void QWorkspace::minimizeActiveWindow()
1625{
1626 if ( d->maxWindow )
1627 d->maxWindow->showMinimized();
1628 else if ( d->active )
1629 d->active->showMinimized();
1630}
1631
1632void QWorkspace::showOperationMenu()
1633{
1634 if ( !d->active || !d->active->windowWidget() )
1635 return;
1636 Q_ASSERT( d->active->windowWidget()->testWFlags( WStyle_SysMenu ) );
1637 QPoint p;
1638 QPopupMenu *popup = d->active->windowWidget()->testWFlags( WStyle_Tool ) ? d->toolPopup : d->popup;
1639 if ( QApplication::reverseLayout() ) {
1640 p = QPoint( d->active->windowWidget()->mapToGlobal( QPoint(d->active->windowWidget()->width(),0) ) );
1641 p.rx() -= popup->sizeHint().width();
1642 } else {
1643 p = QPoint( d->active->windowWidget()->mapToGlobal( QPoint(0,0) ) );
1644 }
1645 if ( !d->active->isVisible() ) {
1646 p = d->active->iconWidget()->mapToGlobal( QPoint(0,0) );
1647 p.ry() -= popup->sizeHint().height();
1648 }
1649 popupOperationMenu( p );
1650}
1651
1652void QWorkspace::popupOperationMenu( const QPoint& p)
1653{
1654 if ( !d->active || !d->active->windowWidget() || !d->active->windowWidget()->testWFlags( WStyle_SysMenu ) )
1655 return;
1656 if ( d->active->windowWidget()->testWFlags( WStyle_Tool ))
1657 d->toolPopup->popup( p );
1658 else
1659 d->popup->popup( p );
1660}
1661
1662void QWorkspace::operationMenuAboutToShow()
1663{
1664 for ( int i = 1; i < 6; i++ ) {
1665 bool enable = d->active != 0;
1666 d->popup->setItemEnabled( i, enable );
1667 }
1668
1669 if ( !d->active || !d->active->windowWidget() )
1670 return;
1671
1672 QWidget *windowWidget = d->active->windowWidget();
1673 bool canResize = windowWidget->maximumSize() != windowWidget->minimumSize();
1674 d->popup->setItemEnabled( 3, canResize );
1675 d->popup->setItemEnabled( 4, windowWidget->testWFlags( WStyle_Minimize ) );
1676 d->popup->setItemEnabled( 5, windowWidget->testWFlags( WStyle_Maximize ) && canResize );
1677
1678 if ( d->active == d->maxWindow ) {
1679 d->popup->setItemEnabled( 2, FALSE );
1680 d->popup->setItemEnabled( 3, FALSE );
1681 d->popup->setItemEnabled( 5, FALSE );
1682 } else if ( d->active->isVisible() ){
1683 d->popup->setItemEnabled( 1, FALSE );
1684 } else {
1685 d->popup->setItemEnabled( 2, FALSE );
1686 d->popup->setItemEnabled( 3, FALSE );
1687 d->popup->setItemEnabled( 4, FALSE );
1688 }
1689}
1690
1691void QWorkspace::toolMenuAboutToShow()
1692{
1693 if ( !d->active || !d->active->windowWidget() )
1694 return;
1695
1696 QWidget *windowWidget = d->active->windowWidget();
1697 bool canResize = windowWidget->maximumSize() != windowWidget->minimumSize();
1698
1699 d->toolPopup->setItemEnabled( 3, !d->active->shademode && canResize );
1700 if ( d->active->shademode )
1701 d->toolPopup->changeItem( 6,
1702 QIconSet(style().stylePixmap(QStyle::SP_TitleBarUnshadeButton)), tr("&Unshade") );
1703 else
1704 d->toolPopup->changeItem( 6, QIconSet(style().stylePixmap(QStyle::SP_TitleBarShadeButton)), tr("Sh&ade") );
1705 d->toolPopup->setItemEnabled( 6, d->active->windowWidget()->testWFlags( WStyle_MinMax ) );
1706 d->toolPopup->setItemChecked( 7, d->active->windowWidget()->testWFlags( WStyle_StaysOnTop ) );
1707}
1708
1709void QWorkspace::operationMenuActivated( int a )
1710{
1711 if ( !d->active )
1712 return;
1713 switch ( a ) {
1714 case 1:
1715 d->active->showNormal();
1716 break;
1717 case 2:
1718 d->active->doMove();
1719 break;
1720 case 3:
1721 if ( d->active->shademode )
1722 d->active->showShaded();
1723 d->active->doResize();
1724 break;
1725 case 4:
1726 d->active->showMinimized();
1727 break;
1728 case 5:
1729 d->active->showMaximized();
1730 break;
1731 case 6:
1732 d->active->showShaded();
1733 break;
1734 case 7:
1735 {
1736 QWorkspace* w = (QWorkspace*)d->active->windowWidget();
1737 if ( !w )
1738 break;
1739 if ( w->testWFlags( WStyle_StaysOnTop ) ) {
1740 w->clearWFlags( WStyle_StaysOnTop );
1741 } else {
1742 w->setWFlags( WStyle_StaysOnTop );
1743 w->parentWidget()->raise();
1744 }
1745 }
1746 break;
1747 default:
1748 break;
1749 }
1750}
1751
1752/*!
1753 Activates the next window in the child window chain.
1754
1755 \sa activatePrevWindow()
1756*/
1757void QWorkspace::activateNextWindow()
1758{
1759 if ( d->focus.isEmpty() )
1760 return;
1761 if ( !d->active ) {
1762 if ( d->focus.first() )
1763 activateWindow( d->focus.first()->windowWidget(), FALSE );
1764 return;
1765 }
1766
1767 int a = d->focus.find( d->active ) + 1;
1768
1769 a = a % d->focus.count();
1770
1771 if ( d->focus.at( a ) )
1772 activateWindow( d->focus.at( a )->windowWidget(), FALSE );
1773 else
1774 d->active = 0;
1775}
1776
1777void QWorkspace::activatePreviousWindow()
1778{
1779 activatePrevWindow();
1780}
1781
1782/*!
1783 Activates the previous window in the child window chain.
1784
1785 \sa activateNextWindow()
1786*/
1787void QWorkspace::activatePrevWindow()
1788{
1789 if ( d->focus.isEmpty() )
1790 return;
1791 if ( !d->active ) {
1792 if ( d->focus.last() )
1793 activateWindow( d->focus.first()->windowWidget(), FALSE );
1794 else
1795 activateWindow( 0 );
1796
1797 return;
1798 }
1799
1800 int a = d->focus.find( d->active ) - 1;
1801 if ( a < 0 )
1802 a = d->focus.count()-1;
1803
1804 if ( d->focus.at( a ) )
1805 activateWindow( d->focus.at( a )->windowWidget(), FALSE );
1806 else
1807 activateWindow( 0 );
1808}
1809
1810
1811/*!
1812 \fn void QWorkspace::windowActivated( QWidget* w )
1813
1814 This signal is emitted when the window widget \a w becomes active.
1815 Note that \a w can be null, and that more than one signal may be
1816 emitted for a single activation event.
1817
1818 \sa activeWindow(), windowList()
1819*/
1820
1821
1822
1823/*!
1824 Arranges all the child windows in a cascade pattern.
1825
1826 \sa tile()
1827*/
1828void QWorkspace::cascade()
1829{
1830 blockSignals(TRUE);
1831 if ( d->maxWindow )
1832 d->maxWindow->showNormal();
1833
1834 if ( d->vbar ) {
1835 d->vbar->blockSignals( TRUE );
1836 d->vbar->setValue( 0 );
1837 d->vbar->blockSignals( FALSE );
1838 d->hbar->blockSignals( TRUE );
1839 d->hbar->setValue( 0 );
1840 d->hbar->blockSignals( FALSE );
1841 scrollBarChanged();
1842 }
1843
1844 const int xoffset = 13;
1845 const int yoffset = 20;
1846
1847 // make a list of all relevant mdi clients
1848 QPtrList<QWorkspaceChild> widgets;
1849 QWorkspaceChild* wc = 0;
1850 for ( wc = d->windows.first(); wc; wc = d->windows.next() )
1851 if ( wc->iconw )
1852 normalizeWindow( wc->windowWidget() );
1853 for ( wc = d->focus.first(); wc; wc = d->focus.next() )
1854 if ( wc->windowWidget()->isVisibleTo( this ) && !wc->windowWidget()->testWFlags( WStyle_Tool ) )
1855 widgets.append( wc );
1856
1857 int x = 0;
1858 int y = 0;
1859
1860 setUpdatesEnabled( FALSE );
1861 QPtrListIterator<QWorkspaceChild> it( widgets );
1862 int children = d->windows.count() - 1;
1863 while ( it.current () ) {
1864 QWorkspaceChild *child = it.current();
1865 ++it;
1866 child->setUpdatesEnabled( FALSE );
1867 bool hasSizeHint = FALSE;
1868 QSize prefSize = child->windowWidget()->sizeHint().expandedTo( child->windowWidget()->minimumSizeHint() );
1869
1870 if ( !prefSize.isValid() )
1871 prefSize = QSize( width() - children * xoffset, height() - children * yoffset );
1872 else
1873 hasSizeHint = TRUE;
1874 prefSize = prefSize.expandedTo( child->windowWidget()->minimumSize() ).boundedTo( child->windowWidget()->maximumSize() );
1875 if ( hasSizeHint )
1876 prefSize += QSize( child->baseSize().width(), child->baseSize().height() );
1877
1878 int w = prefSize.width();
1879 int h = prefSize.height();
1880
1881 child->showNormal();
1882 qApp->sendPostedEvents( 0, QEvent::ShowNormal );
1883 if ( y + h > height() )
1884 y = 0;
1885 if ( x + w > width() )
1886 x = 0;
1887 child->setGeometry( x, y, w, h );
1888 x += xoffset;
1889 y += yoffset;
1890 child->internalRaise();
1891 child->setUpdatesEnabled( TRUE );
1892 }
1893 setUpdatesEnabled( TRUE );
1894 updateWorkspace();
1895 blockSignals(FALSE);
1896}
1897
1898/*!
1899 Arranges all child windows in a tile pattern.
1900
1901 \sa cascade()
1902*/
1903void QWorkspace::tile()
1904{
1905 blockSignals(TRUE);
1906 QWidget *oldActive = d->active ? d->active->windowWidget() : 0;
1907 if ( d->maxWindow )
1908 d->maxWindow->showNormal();
1909
1910 if ( d->vbar ) {
1911 d->vbar->blockSignals( TRUE );
1912 d->vbar->setValue( 0 );
1913 d->vbar->blockSignals( FALSE );
1914 d->hbar->blockSignals( TRUE );
1915 d->hbar->setValue( 0 );
1916 d->hbar->blockSignals( FALSE );
1917 scrollBarChanged();
1918 }
1919
1920 int rows = 1;
1921 int cols = 1;
1922 int n = 0;
1923 QWorkspaceChild* c;
1924
1925 QPtrListIterator<QWorkspaceChild> it( d->windows );
1926 while ( it.current () ) {
1927 c = it.current();
1928 ++it;
1929 if ( !c->windowWidget()->isHidden() &&
1930 !c->windowWidget()->testWFlags( WStyle_StaysOnTop ) &&
1931 !c->windowWidget()->testWFlags( WStyle_Tool ) )
1932 n++;
1933 }
1934
1935 while ( rows * cols < n ) {
1936 if ( cols <= rows )
1937 cols++;
1938 else
1939 rows++;
1940 }
1941 int add = cols * rows - n;
1942 bool* used = new bool[ cols*rows ];
1943 for ( int i = 0; i < rows*cols; i++ )
1944 used[i] = FALSE;
1945
1946 int row = 0;
1947 int col = 0;
1948 int w = width() / cols;
1949 int h = height() / rows;
1950
1951 it.toFirst();
1952 while ( it.current () ) {
1953 c = it.current();
1954 ++it;
1955 if ( c->windowWidget()->isHidden() || c->windowWidget()->testWFlags( WStyle_Tool ) )
1956 continue;
1957 if ( c->windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
1958 QPoint p = c->pos();
1959 if ( p.x()+c->width() < 0 )
1960 p.setX( 0 );
1961 if ( p.x() > width() )
1962 p.setX( width() - c->width() );
1963 if ( p.y() + 10 < 0 )
1964 p.setY( 0 );
1965 if ( p.y() > height() )
1966 p.setY( height() - c->height() );
1967
1968
1969 if ( p != c->pos() )
1970 c->QFrame::move( p );
1971 } else {
1972 c->showNormal();
1973 qApp->sendPostedEvents( 0, QEvent::ShowNormal );
1974 used[row*cols+col] = TRUE;
1975 if ( add ) {
1976 c->setGeometry( col*w, row*h, QMIN( w, c->windowWidget()->maximumWidth()+c->baseSize().width() ),
1977 QMIN( 2*h, c->windowWidget()->maximumHeight()+c->baseSize().height() ) );
1978 used[(row+1)*cols+col] = TRUE;
1979 add--;
1980 } else {
1981 c->setGeometry( col*w, row*h, QMIN( w, c->windowWidget()->maximumWidth()+c->baseSize().width() ),
1982 QMIN( h, c->windowWidget()->maximumHeight()+c->baseSize().height() ) );
1983 }
1984 while( row < rows && col < cols && used[row*cols+col] ) {
1985 col++;
1986 if ( col == cols ) {
1987 col = 0;
1988 row++;
1989 }
1990 }
1991 }
1992 }
1993 delete [] used;
1994
1995 activateWindow( oldActive );
1996 updateWorkspace();
1997 blockSignals(FALSE);
1998}
1999
2000QWorkspaceChild::QWorkspaceChild( QWidget* window, QWorkspace *parent,
2001 const char *name )
2002 : QFrame( parent, name,
2003 (parent->windowMode() == QWorkspace::TopLevel ? (WStyle_MinMax | WStyle_SysMenu | WType_TopLevel) :
2004 WStyle_NoBorder ) | WStyle_Customize | WDestructiveClose | WNoMousePropagation | WSubWindow |
2005 WNoAutoErase )
2006{
2007 statusbar = 0;
2008 setMouseTracking( TRUE );
2009 act = FALSE;
2010 iconw = 0;
2011 lastfocusw = 0;
2012 shademode = FALSE;
2013 titlebar = 0;
2014 snappedRight = FALSE;
2015 snappedDown = FALSE;
2016
2017 if (window) {
2018 switch (window->focusPolicy()) {
2019 case QWidget::NoFocus:
2020 window->setFocusPolicy(QWidget::ClickFocus);
2021 break;
2022 case QWidget::TabFocus:
2023 window->setFocusPolicy(QWidget::StrongFocus);
2024 break;
2025 default:
2026 break;
2027 }
2028 }
2029
2030 if ( window && window->testWFlags( WStyle_Title ) && parent->windowMode() != QWorkspace::TopLevel ) {
2031 titlebar = new QTitleBar( window, this, "qt_ws_titlebar" );
2032 connect( titlebar, SIGNAL( doActivate() ),
2033 this, SLOT( activate() ) );
2034 connect( titlebar, SIGNAL( doClose() ),
2035 window, SLOT( close() ) );
2036 connect( titlebar, SIGNAL( doMinimize() ),
2037 this, SLOT( showMinimized() ) );
2038 connect( titlebar, SIGNAL( doNormal() ),
2039 this, SLOT( showNormal() ) );
2040 connect( titlebar, SIGNAL( doMaximize() ),
2041 this, SLOT( showMaximized() ) );
2042 connect( titlebar, SIGNAL( popupOperationMenu(const QPoint&) ),
2043 this, SIGNAL( popupOperationMenu(const QPoint&) ) );
2044 connect( titlebar, SIGNAL( showOperationMenu() ),
2045 this, SIGNAL( showOperationMenu() ) );
2046 connect( titlebar, SIGNAL( doShade() ),
2047 this, SLOT( showShaded() ) );
2048 connect( titlebar, SIGNAL( doubleClicked() ),
2049 this, SLOT( titleBarDoubleClicked() ) );
2050 }
2051
2052 setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
2053 setLineWidth( style().pixelMetric(QStyle::PM_MDIFrameWidth, this) );
2054 setMinimumSize( 128, 0 );
2055
2056 childWidget = window;
2057 if (!childWidget)
2058 return;
2059
2060#ifndef QT_NO_WIDGET_TOPEXTRA
2061 setCaption( childWidget->caption() );
2062#endif
2063
2064 QPoint p;
2065 QSize s;
2066 QSize cs;
2067
2068 bool hasBeenResized = childWidget->testWState( WState_Resized );
2069
2070 if ( !hasBeenResized )
2071 cs = childWidget->sizeHint().expandedTo( childWidget->minimumSizeHint() );
2072 else
2073 cs = childWidget->size();
2074
2075 int th = titlebar ? titlebar->sizeHint().height() : 0;
2076 if ( titlebar ) {
2077#ifndef QT_NO_WIDGET_TOPEXTRA
2078 int iconSize = th;
2079 if( childWidget->icon() ) {
2080 QPixmap pm(*childWidget->icon());
2081 if(pm.width() > iconSize || pm.height() > iconSize) {
2082 QImage im;
2083 im = pm;
2084 pm = im.smoothScale( QMIN(iconSize, pm.width()), QMIN(iconSize, pm.height()) );
2085 }
2086 titlebar->setIcon( pm );
2087 }
2088#endif
2089 if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder, titlebar ) )
2090 th += frameWidth();
2091 else
2092 th -= contentsRect().y();
2093
2094 p = QPoint( contentsRect().x(),
2095 th + contentsRect().y() );
2096 s = QSize( cs.width() + 2*frameWidth(),
2097 cs.height() + 2*frameWidth() + th );
2098 } else {
2099 p = QPoint( contentsRect().x(), contentsRect().y() );
2100 s = QSize( cs.width() + 2*frameWidth(),
2101 cs.height() + 2*frameWidth() );
2102 }
2103
2104 childWidget->reparent( this, p);
2105 resize( s );
2106
2107 childWidget->installEventFilter( this );
2108
2109 widgetResizeHandler = new QWidgetResizeHandler( this, window );
2110 widgetResizeHandler->setSizeProtection( !parent->scrollBarsEnabled() );
2111 connect( widgetResizeHandler, SIGNAL( activate() ),
2112 this, SLOT( activate() ) );
2113 widgetResizeHandler->setExtraHeight( th + contentsRect().y() );
2114 if(parent->windowMode() == QWorkspace::TopLevel && isTopLevel()) {
2115 move(0, 0);
2116 widgetResizeHandler->setActive( FALSE );
2117 }
2118 if ( childWidget->minimumSize() == childWidget->maximumSize() )
2119 widgetResizeHandler->setActive( QWidgetResizeHandler::Resize, FALSE );
2120 setBaseSize( baseSize() );
2121}
2122
2123QWorkspaceChild::~QWorkspaceChild()
2124{
2125 if ( iconw )
2126 delete iconw->parentWidget();
2127 QWorkspace *workspace = ::qt_cast<QWorkspace*>(parentWidget());
2128 if ( workspace ) {
2129 if ( workspace->d->active == this )
2130 workspace->activatePrevWindow();
2131 if ( workspace->d->maxWindow == this ) {
2132 workspace->hideMaximizeControls();
2133 workspace->d->maxWindow = 0;
2134 }
2135 }
2136}
2137
2138bool QWorkspaceChild::event( QEvent *e )
2139{
2140 if(((QWorkspace*)parentWidget())->windowMode() == QWorkspace::TopLevel) {
2141 switch(e->type()) {
2142 case QEvent::Close:
2143 if(windowWidget()) {
2144 if(!windowWidget()->close()) {
2145 if(((QWorkspace*) parentWidget() )->d->active == this)
2146 ((QWorkspace*) parentWidget() )->activatePrevWindow();
2147 return TRUE;
2148 }
2149 }
2150 break;
2151#if 0
2152 case QEvent::WindowDeactivate:
2153 if(statusbar) {
2154 QSize newsize(width(), height() - statusbar->height());
2155 if(statusbar->parentWidget() == this)
2156 statusbar->hide();
2157 statusbar = 0;
2158 resize(newsize);
2159 }
2160 break;
2161#endif
2162 case QEvent::WindowActivate:
2163 if(((QWorkspace*)parentWidget())->activeWindow() == windowWidget())
2164 activate();
2165 if(statusbar)
2166 statusbar->show();
2167 else if(((QWorkspace*) parentWidget() )->d->mainwindow)
2168 setStatusBar(((QWorkspace*) parentWidget() )->d->mainwindow->statusBar());
2169 break;
2170 default:
2171 break;
2172 }
2173 }
2174 return QWidget::event(e);
2175}
2176
2177void QWorkspaceChild::setStatusBar( QStatusBar *sb )
2178{
2179 if(((QWorkspace*) parentWidget() )->windowMode() == QWorkspace::TopLevel) {
2180 QSize newsize;
2181 if(sb) {
2182 sb->show();
2183 if(sb != statusbar) {
2184 sb->reparent(this, QPoint(0, height()), TRUE);
2185 newsize = QSize(width(), height() + sb->height());
2186 }
2187 }
2188 statusbar = sb;
2189 if(!newsize.isNull())
2190 resize(newsize);
2191 }
2192}
2193
2194void QWorkspaceChild::moveEvent( QMoveEvent *e )
2195{
2196 if(((QWorkspace*) parentWidget() )->windowMode() == QWorkspace::TopLevel && !e->spontaneous()) {
2197 QPoint p = parentWidget()->topLevelWidget()->pos();
2198 if(x() < p.x() || y() < p.y())
2199 move(QMAX(x(), p.x()), QMAX(y(), p.y()));
2200 }
2201 ((QWorkspace*) parentWidget() )->updateWorkspace();
2202}
2203
2204void QWorkspaceChild::resizeEvent( QResizeEvent * )
2205{
2206 QRect r = contentsRect();
2207 QRect cr;
2208
2209 if ( titlebar ) {
2210 int th = titlebar->sizeHint().height();
2211 QRect tbrect( 0, 0, width(), th );
2212 if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) )
2213 tbrect = QRect( r.x(), r.y(), r.width(), th );
2214 titlebar->setGeometry( tbrect );
2215
2216 if ( style().styleHint( QStyle::SH_TitleBar_NoBorder, titlebar ) )
2217 th -= frameWidth();
2218 cr = QRect( r.x(), r.y() + th + (shademode ? (frameWidth() * 3) : 0),
2219 r.width(), r.height() - th );
2220 } else {
2221 cr = r;
2222 }
2223
2224 if(statusbar && statusbar->isVisible()) {
2225 int sh = statusbar->height();
2226 statusbar->setGeometry(r.x(), r.bottom() - sh, r.width(), sh);
2227 cr.setBottom(cr.bottom() - sh);
2228 }
2229
2230 if (!childWidget)
2231 return;
2232
2233 windowSize = cr.size();
2234 childWidget->setGeometry( cr );
2235 ((QWorkspace*) parentWidget() )->updateWorkspace();
2236}
2237
2238QSize QWorkspaceChild::baseSize() const
2239{
2240 int th = titlebar ? titlebar->sizeHint().height() : 0;
2241 if ( style().styleHint( QStyle::SH_TitleBar_NoBorder, titlebar ) )
2242 th -= frameWidth();
2243 return QSize( 2*frameWidth(), 2*frameWidth() + th );
2244}
2245
2246QSize QWorkspaceChild::sizeHint() const
2247{
2248 if ( !childWidget )
2249 return QFrame::sizeHint() + baseSize();
2250
2251 QSize prefSize = windowWidget()->sizeHint().expandedTo( windowWidget()->minimumSizeHint() );
2252 prefSize = prefSize.expandedTo( windowWidget()->minimumSize() ).boundedTo( windowWidget()->maximumSize() );
2253 prefSize += baseSize();
2254
2255 return prefSize;
2256}
2257
2258QSize QWorkspaceChild::minimumSizeHint() const
2259{
2260 if ( !childWidget )
2261 return QFrame::minimumSizeHint() + baseSize();
2262 QSize s = childWidget->minimumSize();
2263 if ( s.isEmpty() )
2264 s = childWidget->minimumSizeHint();
2265 return s + baseSize();
2266}
2267
2268void QWorkspaceChild::activate()
2269{
2270 ((QWorkspace*)parentWidget())->activateWindow( windowWidget() );
2271}
2272
2273bool QWorkspaceChild::eventFilter( QObject * o, QEvent * e)
2274{
2275 if ( !isActive() && ( e->type() == QEvent::MouseButtonPress ||
2276 e->type() == QEvent::FocusIn ) ) {
2277 if ( iconw ) {
2278 ((QWorkspace*)parentWidget())->normalizeWindow( windowWidget() );
2279 if ( iconw ) {
2280 ((QWorkspace*)parentWidget())->removeIcon( iconw->parentWidget() );
2281 delete iconw->parentWidget();
2282 iconw = 0;
2283 }
2284 }
2285 activate();
2286 }
2287
2288 // for all widgets except the window, that's the only thing we
2289 // process, and if we have no childWidget we skip totally
2290 if ( o != childWidget || childWidget == 0 )
2291 return FALSE;
2292
2293 switch ( e->type() ) {
2294 case QEvent::Show:
2295 if ( ((QWorkspace*)parentWidget())->d->focus.find( this ) < 0 )
2296 ((QWorkspace*)parentWidget())->d->focus.append( this );
2297 if ( isVisibleTo( parentWidget() ) )
2298 break;
2299 if (( (QShowEvent*)e)->spontaneous() )
2300 break;
2301 // fall through
2302 case QEvent::ShowToParent:
2303 if ( windowWidget() && windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
2304 internalRaise();
2305 show();
2306 }
2307 ((QWorkspace*)parentWidget())->showWindow( windowWidget() );
2308 break;
2309 case QEvent::ShowMaximized:
2310 if ( windowWidget()->maximumSize().isValid() &&
2311 ( windowWidget()->maximumWidth() < parentWidget()->width() ||
2312 windowWidget()->maximumHeight() < parentWidget()->height() ) ) {
2313 windowWidget()->resize( windowWidget()->maximumSize() );
2314 break;
2315 }
2316 if ( windowWidget()->testWFlags( WStyle_Maximize ) && !windowWidget()->testWFlags( WStyle_Tool ) )
2317 ((QWorkspace*)parentWidget())->maximizeWindow( windowWidget() );
2318 else
2319 ((QWorkspace*)parentWidget())->normalizeWindow( windowWidget() );
2320 break;
2321 case QEvent::ShowMinimized:
2322 ((QWorkspace*)parentWidget())->minimizeWindow( windowWidget() );
2323 break;
2324 case QEvent::ShowNormal:
2325 ((QWorkspace*)parentWidget())->normalizeWindow( windowWidget() );
2326 if (iconw) {
2327 ((QWorkspace*)parentWidget())->removeIcon( iconw->parentWidget() );
2328 delete iconw->parentWidget();
2329 }
2330 break;
2331 case QEvent::Hide:
2332 case QEvent::HideToParent:
2333 if ( !childWidget->isVisibleTo( this ) ) {
2334 QWidget * w = iconw;
2335 if ( w && ( w = w->parentWidget() ) ) {
2336 ((QWorkspace*)parentWidget())->removeIcon( w );
2337 delete w;
2338 }
2339 hide();
2340 }
2341 break;
2342 case QEvent::CaptionChange:
2343#ifndef QT_NO_WIDGET_TOPEXTRA
2344 setCaption( childWidget->caption() );
2345 if ( iconw )
2346 iconw->setCaption( childWidget->caption() );
2347#endif
2348 break;
2349 case QEvent::IconChange:
2350 {
2351 QWorkspace* ws = (QWorkspace*)parentWidget();
2352 if ( !titlebar )
2353 break;
2354
2355 QPixmap pm;
2356 int iconSize = titlebar->size().height();
2357#ifndef QT_NO_WIDGET_TOPEXTRA
2358 if ( childWidget->icon() ) {
2359 pm = *childWidget->icon();
2360 if(pm.width() > iconSize || pm.height() > iconSize) {
2361 QImage im;
2362 im = pm;
2363 pm = im.smoothScale( QMIN(iconSize, pm.width()), QMIN(iconSize, pm.height()) );
2364 }
2365 } else
2366#endif
2367 {
2368 pm.resize( iconSize, iconSize );
2369 pm.fill( color1 );
2370 pm.setMask(pm.createHeuristicMask());
2371 }
2372 titlebar->setIcon( pm );
2373 if ( iconw )
2374 iconw->setIcon( pm );
2375
2376 if ( ws->d->maxWindow != this )
2377 break;
2378
2379 if ( ws->d->maxtools )
2380 ws->d->maxtools->setPixmap( pm );
2381 }
2382 break;
2383 case QEvent::Resize:
2384 {
2385 QResizeEvent* re = (QResizeEvent*)e;
2386 if ( re->size() != windowSize && !shademode )
2387 resize( re->size() + baseSize() );
2388 }
2389 break;
2390
2391 case QEvent::WindowDeactivate:
2392 if ( titlebar )
2393 titlebar->setActive( FALSE );
2394 repaint( FALSE );
2395 break;
2396
2397 case QEvent::WindowActivate:
2398 if ( titlebar )
2399 titlebar->setActive( act );
2400 repaint( FALSE );
2401 break;
2402
2403 default:
2404 break;
2405 }
2406
2407 return QFrame::eventFilter(o, e);
2408}
2409
2410bool QWorkspaceChild::focusNextPrevChild( bool next )
2411{
2412 QFocusData *f = focusData();
2413
2414 QWidget *startingPoint = f->home();
2415 QWidget *candidate = 0;
2416 QWidget *w = next ? f->next() : f->prev();
2417 while( !candidate && w != startingPoint ) {
2418 if ( w != startingPoint &&
2419 (w->focusPolicy() & TabFocus) == TabFocus
2420 && w->isEnabled() &&!w->focusProxy() && w->isVisible() )
2421 candidate = w;
2422 w = next ? f->next() : f->prev();
2423 }
2424
2425 if ( candidate ) {
2426 QObjectList *ol = queryList();
2427 bool ischild = ol->findRef( candidate ) != -1;
2428 delete ol;
2429 if ( !ischild ) {
2430 startingPoint = f->home();
2431 QWidget *nw = next ? f->prev() : f->next();
2432 QObjectList *ol2 = queryList();
2433 QWidget *lastValid = 0;
2434 candidate = startingPoint;
2435 while ( nw != startingPoint ) {
2436 if ( ( candidate->focusPolicy() & TabFocus ) == TabFocus
2437 && candidate->isEnabled() &&!candidate->focusProxy() && candidate->isVisible() )
2438 lastValid = candidate;
2439 if ( ol2->findRef( nw ) == -1 ) {
2440 candidate = lastValid;
2441 break;
2442 }
2443 candidate = nw;
2444 nw = next ? f->prev() : f->next();
2445 }
2446 delete ol2;
2447 }
2448 }
2449
2450 if ( !candidate )
2451 return FALSE;
2452
2453 candidate->setFocus();
2454 return TRUE;
2455}
2456
2457void QWorkspaceChild::childEvent( QChildEvent* e)
2458{
2459 if ( e->type() == QEvent::ChildRemoved && e->child() == childWidget ) {
2460 childWidget = 0;
2461 if ( iconw ) {
2462 ((QWorkspace*)parentWidget())->removeIcon( iconw->parentWidget() );
2463 delete iconw->parentWidget();
2464 }
2465 close();
2466 }
2467}
2468
2469
2470void QWorkspaceChild::doResize()
2471{
2472 widgetResizeHandler->doResize();
2473}
2474
2475void QWorkspaceChild::doMove()
2476{
2477 widgetResizeHandler->doMove();
2478}
2479
2480void QWorkspaceChild::enterEvent( QEvent * )
2481{
2482}
2483
2484void QWorkspaceChild::leaveEvent( QEvent * )
2485{
2486#ifndef QT_NO_CURSOR
2487 if ( !widgetResizeHandler->isButtonDown() )
2488 setCursor( arrowCursor );
2489#endif
2490}
2491
2492void QWorkspaceChild::drawFrame( QPainter *p )
2493{
2494 QStyle::SFlags flags = QStyle::Style_Default;
2495 QStyleOption opt(lineWidth(),midLineWidth());
2496
2497 if ( titlebar && titlebar->isActive() )
2498 flags |= QStyle::Style_Active;
2499
2500 style().drawPrimitive( QStyle::PE_WindowFrame, p, rect(), colorGroup(), flags, opt );
2501}
2502
2503void QWorkspaceChild::styleChange( QStyle & )
2504{
2505 resizeEvent( 0 );
2506 if ( iconw ) {
2507 QVBox *vbox = (QVBox*)iconw->parentWidget()->qt_cast( "QVBox" );
2508 Q_ASSERT(vbox);
2509 if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) ) {
2510 vbox->setFrameStyle( QFrame::WinPanel | QFrame::Raised );
2511 vbox->resize( 196+2*vbox->frameWidth(), 20 + 2*vbox->frameWidth() );
2512 } else {
2513 vbox->resize( 196, 20 );
2514 }
2515 }
2516}
2517
2518void QWorkspaceChild::setActive( bool b )
2519{
2520 if ( !childWidget )
2521 return;
2522
2523 bool hasFocus = isChildOf( focusWidget(), childWidget );
2524 if ( act == b && hasFocus )
2525 return;
2526
2527 act = b;
2528
2529 if ( titlebar )
2530 titlebar->setActive( act );
2531 if ( iconw )
2532 iconw->setActive( act );
2533 repaint( FALSE );
2534
2535 QObjectList* ol = childWidget->queryList( "QWidget" );
2536 if ( act ) {
2537 QObject *o;
2538 for ( o = ol->first(); o; o = ol->next() )
2539 o->removeEventFilter( this );
2540 if ( !hasFocus ) {
2541 if ( lastfocusw && ol->contains( lastfocusw ) &&
2542 lastfocusw->focusPolicy() != NoFocus ) {
2543 // this is a bug if lastfocusw has been deleted, a new
2544 // widget has been created, and the new one is a child
2545 // of the same window as the old one. but even though
2546 // it's a bug the behaviour is reasonable
2547 lastfocusw->setFocus();
2548 } else if ( childWidget->focusPolicy() != NoFocus ) {
2549 childWidget->setFocus();
2550 } else {
2551 // find something, anything, that accepts focus, and use that.
2552 o = ol->first();
2553 while( o && ((QWidget*)o)->focusPolicy() == NoFocus )
2554 o = ol->next();
2555 if ( o )
2556 ((QWidget*)o)->setFocus();
2557 }
2558 }
2559 } else {
2560 if ( isChildOf( focusWidget(), childWidget ) )
2561 lastfocusw = focusWidget();
2562 QObject * o;
2563 for ( o = ol->first(); o; o = ol->next() ) {
2564 o->removeEventFilter( this );
2565 o->installEventFilter( this );
2566 }
2567 }
2568 delete ol;
2569}
2570
2571bool QWorkspaceChild::isActive() const
2572{
2573 return act;
2574}
2575
2576QWidget* QWorkspaceChild::windowWidget() const
2577{
2578 return childWidget;
2579}
2580
2581
2582QWidget* QWorkspaceChild::iconWidget() const
2583{
2584 if ( !iconw ) {
2585 QWorkspaceChild* that = (QWorkspaceChild*) this;
2586
2587 // ### why do we even need the vbox? -Brad
2588 QVBox* vbox = new QVBox(that, "qt_vbox", WType_TopLevel );
2589 QTitleBar *tb = new QTitleBar( windowWidget(), vbox, "_workspacechild_icon_");
2590 int th = style().pixelMetric( QStyle::PM_TitleBarHeight, tb );
2591 int iconSize = style().pixelMetric( QStyle::PM_MDIMinimizedWidth, this );
2592 if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) ) {
2593 vbox->setFrameStyle( QFrame::WinPanel | QFrame::Raised );
2594 vbox->resize( iconSize+2*vbox->frameWidth(), th+2*vbox->frameWidth() );
2595 } else {
2596 vbox->resize( iconSize, th );
2597 }
2598 that->iconw = tb;
2599 iconw->setActive( isActive() );
2600
2601 connect( iconw, SIGNAL( doActivate() ),
2602 this, SLOT( activate() ) );
2603 connect( iconw, SIGNAL( doClose() ),
2604 windowWidget(), SLOT( close() ) );
2605 connect( iconw, SIGNAL( doNormal() ),
2606 this, SLOT( showNormal() ) );
2607 connect( iconw, SIGNAL( doMaximize() ),
2608 this, SLOT( showMaximized() ) );
2609 connect( iconw, SIGNAL( popupOperationMenu(const QPoint&) ),
2610 this, SIGNAL( popupOperationMenu(const QPoint&) ) );
2611 connect( iconw, SIGNAL( showOperationMenu() ),
2612 this, SIGNAL( showOperationMenu() ) );
2613 connect( iconw, SIGNAL( doubleClicked() ),
2614 this, SLOT( titleBarDoubleClicked() ) );
2615 }
2616#ifndef QT_NO_WIDGET_TOPEXTRA
2617 if ( windowWidget() ) {
2618 iconw->setCaption( windowWidget()->caption() );
2619 if ( windowWidget()->icon() ) {
2620 int iconSize = iconw->sizeHint().height();
2621
2622 QPixmap pm(*childWidget->icon());
2623 if(pm.width() > iconSize || pm.height() > iconSize) {
2624 QImage im;
2625 im = pm;
2626 pm = im.smoothScale( QMIN(iconSize, pm.width()), QMIN(iconSize, pm.height()) );
2627 }
2628 iconw->setIcon( pm );
2629 }
2630 }
2631#endif
2632 return iconw->parentWidget();
2633}
2634
2635void QWorkspaceChild::showMinimized()
2636{
2637 windowWidget()->setWindowState(WindowMinimized | windowWidget()->windowState());
2638}
2639
2640void QWorkspaceChild::showMaximized()
2641{
2642 windowWidget()->setWindowState(WindowMaximized | (windowWidget()->windowState() & ~WindowMinimized));
2643}
2644
2645void QWorkspaceChild::showNormal()
2646{
2647 windowWidget()->setWindowState(windowWidget()->windowState() & ~(WindowMinimized|WindowMaximized));
2648}
2649
2650void QWorkspaceChild::showShaded()
2651{
2652 if ( !titlebar)
2653 return;
2654 Q_ASSERT( windowWidget()->testWFlags( WStyle_MinMax ) && windowWidget()->testWFlags( WStyle_Tool ) );
2655 ((QWorkspace*)parentWidget())->activateWindow( windowWidget() );
2656 if ( shademode ) {
2657 QWorkspaceChild* fake = (QWorkspaceChild*)windowWidget();
2658 fake->clearWState( WState_Minimized );
2659 clearWState( WState_Minimized );
2660
2661 shademode = FALSE;
2662 resize( shadeRestore );
2663 setMinimumSize( shadeRestoreMin );
2664 style().polish(this);
2665 } else {
2666 shadeRestore = size();
2667 shadeRestoreMin = minimumSize();
2668 setMinimumHeight(0);
2669 shademode = TRUE;
2670 QWorkspaceChild* fake = (QWorkspaceChild*)windowWidget();
2671 fake->setWState( WState_Minimized );
2672 setWState( WState_Minimized );
2673
2674 if ( style().styleHint( QStyle::SH_TitleBar_NoBorder ) )
2675 resize( width(), titlebar->height() );
2676 else
2677 resize( width(), titlebar->height() + 2*lineWidth() + 1 );
2678 style().polish(this);
2679 }
2680 titlebar->update();
2681}
2682
2683void QWorkspaceChild::titleBarDoubleClicked()
2684{
2685 if ( !windowWidget() )
2686 return;
2687 if ( windowWidget()->testWFlags( WStyle_MinMax ) ) {
2688 if ( windowWidget()->testWFlags( WStyle_Tool ) )
2689 showShaded();
2690 else if ( iconw )
2691 showNormal();
2692 else if ( windowWidget()->testWFlags( WStyle_Maximize ) )
2693 showMaximized();
2694 }
2695}
2696
2697void QWorkspaceChild::adjustToFullscreen()
2698{
2699 if ( !childWidget )
2700 return;
2701
2702 qApp->sendPostedEvents( this, QEvent::Resize );
2703 qApp->sendPostedEvents( childWidget, QEvent::Resize );
2704 qApp->sendPostedEvents( childWidget, QEvent::Move );
2705 if( style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this) ) {
2706 setGeometry( 0, 0, parentWidget()->width(), parentWidget()->height());
2707 } else {
2708 int w = parentWidget()->width() + width() - childWidget->width();
2709 int h = parentWidget()->height() + height() - childWidget->height();
2710 w = QMAX( w, childWidget->minimumWidth() );
2711 h = QMAX( h, childWidget->minimumHeight() );
2712 setGeometry( -childWidget->x(), -childWidget->y(), w, h );
2713 }
2714 setWState( WState_Maximized );
2715 ((QWorkspaceChild*)childWidget)->setWState( WState_Maximized );
2716}
2717
2718void QWorkspaceChild::setCaption( const QString& cap )
2719{
2720 if ( titlebar )
2721 titlebar->setCaption( cap );
2722#ifndef QT_NO_WIDGET_TOPEXTRA
2723 QWidget::setCaption( cap );
2724#endif
2725}
2726
2727void QWorkspaceChild::internalRaise()
2728{
2729 setUpdatesEnabled( FALSE );
2730 if ( iconw )
2731 iconw->parentWidget()->raise();
2732 raise();
2733
2734 if ( !windowWidget() || windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
2735 setUpdatesEnabled( TRUE );
2736 return;
2737 }
2738
2739 QPtrListIterator<QWorkspaceChild> it( ((QWorkspace*)parent())->d->windows );
2740 while ( it.current () ) {
2741 QWorkspaceChild* c = it.current();
2742 ++it;
2743 if ( c->windowWidget() &&
2744 !c->windowWidget()->isHidden() &&
2745 c->windowWidget()->testWFlags( WStyle_StaysOnTop ) )
2746 c->raise();
2747 }
2748 setUpdatesEnabled( TRUE );
2749}
2750
2751void QWorkspaceChild::move( int x, int y )
2752{
2753 int nx = x;
2754 int ny = y;
2755
2756 if ( windowWidget() && windowWidget()->testWFlags( WStyle_Tool ) ) {
2757 int dx = 10;
2758 int dy = 10;
2759
2760 if ( QABS( x ) < dx )
2761 nx = 0;
2762 if ( QABS( y ) < dy )
2763 ny = 0;
2764 if ( QABS( x + width() - parentWidget()->width() ) < dx ) {
2765 nx = parentWidget()->width() - width();
2766 snappedRight = TRUE;
2767 } else
2768 snappedRight = FALSE;
2769
2770 if ( QABS( y + height() - parentWidget()->height() ) < dy ) {
2771 ny = parentWidget()->height() - height();
2772 snappedDown = TRUE;
2773 } else
2774 snappedDown = FALSE;
2775 }
2776 QFrame::move( nx, ny );
2777}
2778
2779bool QWorkspace::scrollBarsEnabled() const
2780{
2781 return d->vbar != 0;
2782}
2783
2784/*!
2785 \property QWorkspace::scrollBarsEnabled
2786 \brief whether the workspace provides scrollbars
2787
2788 If this property is set to TRUE, it is possible to resize child
2789 windows over the right or the bottom edge out of the visible area
2790 of the workspace. The workspace shows scrollbars to make it
2791 possible for the user to access those windows. If this property is
2792 set to FALSE (the default), resizing windows out of the visible
2793 area of the workspace is not permitted.
2794*/
2795void QWorkspace::setScrollBarsEnabled( bool enable )
2796{
2797 if ( (d->vbar != 0) == enable )
2798 return;
2799
2800 d->xoffset = d->yoffset = 0;
2801 if ( enable ) {
2802 d->vbar = new QScrollBar( Vertical, this, "vertical scrollbar" );
2803 connect( d->vbar, SIGNAL( valueChanged(int) ), this, SLOT( scrollBarChanged() ) );
2804 d->hbar = new QScrollBar( Horizontal, this, "horizontal scrollbar" );
2805 connect( d->hbar, SIGNAL( valueChanged(int) ), this, SLOT( scrollBarChanged() ) );
2806 d->corner = new QWidget( this, "qt_corner" );
2807 updateWorkspace();
2808 } else {
2809 delete d->vbar;
2810 delete d->hbar;
2811 delete d->corner;
2812 d->vbar = d->hbar = 0;
2813 d->corner = 0;
2814 }
2815
2816 QPtrListIterator<QWorkspaceChild> it( d->windows );
2817 while ( it.current () ) {
2818 QWorkspaceChild *child = it.current();
2819 ++it;
2820 child->widgetResizeHandler->setSizeProtection( !enable );
2821 }
2822}
2823
2824QRect QWorkspace::updateWorkspace()
2825{
2826 if ( !isUpdatesEnabled() )
2827 return rect();
2828
2829 QRect cr( rect() );
2830
2831 if ( scrollBarsEnabled() && !d->maxWindow ) {
2832 d->corner->raise();
2833 d->vbar->raise();
2834 d->hbar->raise();
2835 if ( d->maxWindow )
2836 d->maxWindow->internalRaise();
2837
2838 QRect r( 0, 0, 0, 0 );
2839 QPtrListIterator<QWorkspaceChild> it( d->windows );
2840 while ( it.current () ) {
2841 QWorkspaceChild *child = it.current();
2842 ++it;
2843 if ( !child->isHidden() )
2844 r = r.unite( child->geometry() );
2845 }
2846 d->vbar->blockSignals( TRUE );
2847 d->hbar->blockSignals( TRUE );
2848
2849 int hsbExt = d->hbar->sizeHint().height();
2850 int vsbExt = d->vbar->sizeHint().width();
2851
2852
2853 bool showv = d->yoffset || d->yoffset + r.bottom() - height() + 1 > 0 || d->yoffset + r.top() < 0;
2854 bool showh = d->xoffset || d->xoffset + r.right() - width() + 1 > 0 || d->xoffset + r.left() < 0;
2855
2856 if ( showh && !showv)
2857 showv = d->yoffset + r.bottom() - height() + hsbExt + 1 > 0;
2858 if ( showv && !showh )
2859 showh = d->xoffset + r.right() - width() + vsbExt + 1 > 0;
2860
2861 if ( !showh )
2862 hsbExt = 0;
2863 if ( !showv )
2864 vsbExt = 0;
2865
2866 if ( showv ) {
2867 d->vbar->setSteps( QMAX( height() / 12, 30 ), height() - hsbExt );
2868 d->vbar->setRange( QMIN( 0, d->yoffset + QMIN( 0, r.top() ) ), QMAX( 0, d->yoffset + QMAX( 0, r.bottom() - height() + hsbExt + 1) ) );
2869 d->vbar->setGeometry( width() - vsbExt, 0, vsbExt, height() - hsbExt );
2870 d->vbar->setValue( d->yoffset );
2871 d->vbar->show();
2872 } else {
2873 d->vbar->hide();
2874 }
2875
2876 if ( showh ) {
2877 d->hbar->setSteps( QMAX( width() / 12, 30 ), width() - vsbExt );
2878 d->hbar->setRange( QMIN( 0, d->xoffset + QMIN( 0, r.left() ) ), QMAX( 0, d->xoffset + QMAX( 0, r.right() - width() + vsbExt + 1) ) );
2879 d->hbar->setGeometry( 0, height() - hsbExt, width() - vsbExt, hsbExt );
2880 d->hbar->setValue( d->xoffset );
2881 d->hbar->show();
2882 } else {
2883 d->hbar->hide();
2884 }
2885
2886 if ( showh && showv ) {
2887 d->corner->setGeometry( width() - vsbExt, height() - hsbExt, vsbExt, hsbExt );
2888 d->corner->show();
2889 } else {
2890 d->corner->hide();
2891 }
2892
2893 d->vbar->blockSignals( FALSE );
2894 d->hbar->blockSignals( FALSE );
2895
2896 cr.setRect( 0, 0, width() - vsbExt, height() - hsbExt );
2897 }
2898
2899 QPtrListIterator<QWidget> ii( d->icons );
2900 while ( ii.current() ) {
2901 QWorkspaceChild* w = (QWorkspaceChild*)ii.current();
2902 ++ii;
2903 int x = w->x();
2904 int y = w->y();
2905 bool m = FALSE;
2906 if ( x+w->width() > cr.width() ) {
2907 m = TRUE;
2908 x = cr.width() - w->width();
2909 }
2910 if ( y+w->height() > cr.height() ) {
2911 y = cr.height() - w->height();
2912 m = TRUE;
2913 }
2914 if ( m )
2915 w->move( x, y );
2916 }
2917
2918 return cr;
2919
2920}
2921
2922void QWorkspace::scrollBarChanged()
2923{
2924 int ver = d->yoffset - d->vbar->value();
2925 int hor = d->xoffset - d->hbar->value();
2926 d->yoffset = d->vbar->value();
2927 d->xoffset = d->hbar->value();
2928
2929 QPtrListIterator<QWorkspaceChild> it( d->windows );
2930 while ( it.current () ) {
2931 QWorkspaceChild *child = it.current();
2932 ++it;
2933 // we do not use move() due to the reimplementation in QWorkspaceChild
2934 child->setGeometry( child->x() + hor, child->y() + ver, child->width(), child->height() );
2935 }
2936 updateWorkspace();
2937}
2938
2939/*!
2940 \enum QWorkspace::WindowOrder
2941
2942 Specifies the order in which windows are returned from windowList().
2943
2944 \value CreationOrder The windows are returned in the order of their creation
2945 \value StackingOrder The windows are returned in the order of their stacking
2946*/
2947
2948#ifdef QT_WORKSPACE_WINDOWMODE
2949/*!
2950 \enum QWorkspace::WindowMode
2951
2952 Determines the Windowing Model QWorkspace will use for sub-windows.
2953
2954 \value TopLevel Subwindows are treated as toplevel windows
2955 \value MDI Subwindows are organized in an MDI interface
2956 \value AutoDetect QWorkspace will detect whether TopLevel or MDI
2957 is appropriate
2958*/
2959
2960/*!
2961 The windowing model influences how the subwindows are actually
2962 created. For most platforms the default behavior of a workspace is
2963 to operate in MDI mode, with Qt/Mac the default mode is
2964 AutoDetect.
2965*/
2966#else
2967/*! \internal */
2968#endif
2969QWorkspace::WindowMode QWorkspace::windowMode() const
2970{
2971 return d->wmode;
2972}
2973
2974#ifndef QT_NO_STYLE
2975/*!\reimp */
2976void QWorkspace::styleChange( QStyle &olds )
2977{
2978 int fs = style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this);
2979 if ( isVisibleTo(0) && d->maxWindow &&
2980 fs != olds.styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
2981 if( fs )
2982 hideMaximizeControls();
2983 else
2984 showMaximizeControls();
2985 }
2986 QWidget::styleChange(olds);
2987}
2988#endif
2989
2990
2991
2992
2993#include "qworkspace.moc"
2994#endif // QT_NO_WORKSPACE
Note: See TracBrowser for help on using the repository browser.