2 // File : qworkspaceP.cxx
3 // Created : UI team, 21.11.02
4 // Descr : Patch for QWorkspace class (Qt 3.0.5)
6 // Modified : Mon Nov 25 09:35:34 2002
7 // Author : Vadim SANDLER
10 // Copyright : Open CASCADE 2002
13 #include "qworkspaceP.h"
15 #include <qapplication.h>
16 #include <qobjectlist.h>
18 #include <qtoolbutton.h>
23 #include <qpopupmenu.h>
25 #include <qguardedptr.h>
27 #include <qfocusdata.h>
28 #include <qdatetime.h>
32 #include <qscrollbar.h>
36 #include <qt_windows.h>
38 #include <qplatformdefs.h>
42 #include <private/qapplication_p.h>
43 #include <private/qinternal_p.h>
45 #define BUTTON_WIDTH 16
46 #define BUTTON_HEIGHT 14
50 \class QWorkspaceP qworkspace.h
51 \brief The QWorkspaceP widget provides a workspace window that can
52 contain decorated windows, e.g. for MDI.
60 An MDI (multiple document interface) application has one main
61 window with a menu bar. The central widget of this window is a
62 workspace. The workspace itself contains zero, one or more
63 document windows, each of which displays a document.
65 The workspace itself is an ordinary Qt widget. It has a standard
66 constructor that takes a parent widget and an object name. The
67 parent window is usually a QMainWindow, but it need not be.
69 Document windows (i.e. MDI windows) are also ordinary Qt widgets
70 which have the workspace as parent widget. When you call show(),
71 hide(), showMaximized(), setCaption(), etc. on a document window,
72 it is shown, hidden, etc. with a frame, caption, icon and icon
73 text, just as you'd expect. You can provide widget flags which
74 will be used for the layout of the decoration or the behaviour of
77 To change the geometry of the MDI windows it is necessary to make
78 the function calls to the parentWidget() of the widget, as this
79 will move or resize the decorated window.
81 A document window becomes active when it gets the keyboard focus.
82 You can activate it using setFocus(), and the user can activate it
83 by moving focus in the normal ways. The workspace emits a signal
84 windowActivated() when it detects the activation change, and the
85 function activeWindow() always returns a pointer to the active
88 The convenience function windowList() returns a list of all
89 document windows. This is useful to create a popup menu
90 "<u>W</u>indows" on the fly, for example.
92 QWorkspaceP provides two built-in layout strategies for child
93 windows: cascade() and tile(). Both are slots so you can easily
94 connect menu entries to them.
96 If you want your users to be able to work with document windows
97 larger than the actual workspace, set the scrollBarsEnabled
100 If the top-level window contains a menu bar and a document window
101 is maximised, QWorkspaceP moves the document window's minimize,
102 restore and close buttons from the document window's frame to the
103 workspace window's menu bar. It then inserts a window operations
104 menu at the far left of the menu bar.
107 static bool inCaptionChange = FALSE;
109 class QWorkspacePPrivate {
111 QWorkspacePChild* active;
112 QPtrList<QWorkspacePChild> windows;
113 QPtrList<QWorkspacePChild> focus;
114 QPtrList<QWidget> icons;
115 QWorkspacePChild* maxWindow;
117 QGuardedPtr<QFrame> maxcontrols;
118 QGuardedPtr<QMenuBar> maxmenubar;
122 QWidget *becomeActive;
123 QGuardedPtr<QLabel> maxtools;
125 QPopupMenu* toolPopup;
129 bool autoFocusChange;
131 QScrollBar *vbar, *hbar;
133 int yoffset, xoffset;
137 Constructs a workspace with a \a parent and a \a name.
139 QWorkspaceP::QWorkspaceP( QWidget *parent, const char *name )
140 : QWidget( parent, name, WNoMousePropagation )
142 d = new QWorkspacePPrivate;
150 d->autoFocusChange = FALSE;
151 #if defined(Q_WS_WIN)
152 d->popup = new QPopupMenu( this, "qt_internal_mdi_popup" );
153 d->toolPopup = new QPopupMenu( this, "qt_internal_mdi_popup" );
155 d->popup = new QPopupMenu( parentWidget(), "qt_internal_mdi_popup" );
156 d->toolPopup = new QPopupMenu( parentWidget(), "qt_internal_mdi_popup" );
161 connect( d->popup, SIGNAL( aboutToShow() ), this, SLOT(operationMenuAboutToShow() ));
162 connect( d->popup, SIGNAL( activated(int) ), this, SLOT( operationMenuActivated(int) ) );
163 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarNormalButton)), tr("&Restore"), 1);
164 d->popup->insertItem(tr("&Move"), 2);
165 d->popup->insertItem(tr("&Size"), 3);
166 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarMinButton)), tr("Mi&nimize"), 4);
167 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarMaxButton)), tr("Ma&ximize"), 5);
168 d->popup->insertSeparator();
169 d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarCloseButton)),
172 +"\t"+QAccel::keyToString(CTRL+Key_F4)
174 , this, SLOT( closeActiveWindow() ) );
176 connect( d->toolPopup, SIGNAL( aboutToShow() ), this, SLOT(toolMenuAboutToShow() ));
177 connect( d->toolPopup, SIGNAL( activated(int) ), this, SLOT( operationMenuActivated(int) ) );
178 d->toolPopup->insertItem(tr("&Move"), 2);
179 d->toolPopup->insertItem(tr("&Size"), 3);
180 d->toolPopup->insertItem(tr("Stay on &Top"), 7);
181 d->toolPopup->setItemChecked( 7, TRUE );
182 d->toolPopup->setCheckable( TRUE );
183 d->toolPopup->insertSeparator();
184 d->toolPopup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarShadeButton)), tr("Sh&ade"), 6);
185 d->toolPopup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarCloseButton)),
188 +"\t"+QAccel::keyToString( CTRL+Key_F4)
190 , this, SLOT( closeActiveWindow() ) );
193 QAccel* a = new QAccel( this );
194 a->connectItem( a->insertItem( ALT + Key_Minus),
195 this, SLOT( showOperationMenu() ) );
197 a->connectItem( a->insertItem( CTRL + Key_F6),
198 this, SLOT( activateNextWindow() ) );
199 a->connectItem( a->insertItem( CTRL + Key_Tab),
200 this, SLOT( activateNextWindow() ) );
202 a->connectItem( a->insertItem( CTRL + SHIFT + Key_F6),
203 this, SLOT( activatePreviousWindow() ) );
204 a->connectItem( a->insertItem( CTRL + SHIFT + Key_Tab),
205 this, SLOT( activatePreviousWindow() ) );
207 a->connectItem( a->insertItem( CTRL + Key_F4 ),
208 this, SLOT( closeActiveWindow() ) );
211 setBackgroundMode( PaletteDark );
212 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
214 #ifndef QT_NO_WIDGET_TOPEXTRA
215 d->topCaption = topLevelWidget()->caption();
218 d->hbar = d->vbar = 0;
220 d->xoffset = d->yoffset = 0;
224 topLevelWidget()->installEventFilter( this );
227 /*! Destroys the workspace and frees any allocated resources. */
229 QWorkspaceP::~QWorkspaceP()
236 QSize QWorkspaceP::sizeHint() const
238 QSize s( QApplication::desktop()->size() );
239 return QSize( s.width()*2/3, s.height()*2/3);
243 void QWorkspaceP::setPaletteBackgroundColor( const QColor & c )
250 void QWorkspaceP::setPaletteBackgroundPixmap( const QPixmap & pm )
252 setErasePixmap( pm );
256 void QWorkspaceP::childEvent( QChildEvent * e)
258 if (e->inserted() && e->child()->isWidgetType()) {
259 QWidget* w = (QWidget*) e->child();
260 if ( !w || !w->testWFlags( WStyle_Title | WStyle_NormalBorder | WStyle_DialogBorder )
261 || d->icons.contains( w ) || w == d->vbar || w == d->hbar || w == d->corner )
262 return; // nothing to do
264 bool hasBeenHidden = w->isHidden();
265 bool hasSize = w->testWState( WState_Resized );
268 bool hasPos = x != 0 || y != 0;
269 QSize s = w->size().expandedTo( w->minimumSizeHint() );
270 if ( !hasSize && w->sizeHint().isValid() )
273 QWorkspacePChild* child = new QWorkspacePChild( w, this, "qt_workspacechild" );
274 child->installEventFilter( this );
276 connect( child, SIGNAL( popupOperationMenu( const QPoint& ) ),
277 this, SLOT( popupOperationMenu( const QPoint& ) ) );
278 connect( child, SIGNAL( showOperationMenu() ),
279 this, SLOT( showOperationMenu() ) );
280 d->windows.append( child );
281 if ( child->isVisibleTo( this ) )
282 d->focus.append( child );
283 child->internalRaise();
287 else if ( !isVisible() ) // that's a case were we don't receive a showEvent in time. Tricky.
293 child->resize( s + child->baseSize() );
301 } else if (e->removed() ) {
302 if ( d->windows.contains( (QWorkspacePChild*)e->child() ) ) {
303 d->windows.removeRef( (QWorkspacePChild*)e->child() );
304 d->focus.removeRef( (QWorkspacePChild*)e->child() );
305 if (d->windows.count() <= 0) { // VSR+ 26/03/03 -->
308 hideMaximizeControls();
309 } // <-- VSR+ 26/03/03
317 #ifndef QT_NO_WHEELEVENT
318 void QWorkspaceP::wheelEvent( QWheelEvent *e )
320 if ( !scrollBarsEnabled() )
322 if ( d->vbar && d->vbar->isVisible() && !( e->state() & AltButton ) )
323 QApplication::sendEvent( d->vbar, e );
324 else if ( d->hbar && d->hbar->isVisible() )
325 QApplication::sendEvent( d->hbar, e );
329 void QWorkspaceP::activateWindow( QWidget* w, bool change_focus )
333 emit windowActivated( 0 );
336 if ( !isVisibleTo( 0 ) ) {
340 if ( d->active && d->active->windowWidget() == w )
342 QPtrListIterator<QWorkspacePChild> it( d->windows );
343 while ( it.current () ) {
344 QWorkspacePChild* c = it.current();
346 c->setActive( c->windowWidget() == w );
347 if (c->windowWidget() == w)
354 if ( d->maxWindow && d->maxWindow != d->active && d->active->windowWidget() &&
355 d->active->windowWidget()->testWFlags( WStyle_MinMax ) &&
356 !d->active->windowWidget()->testWFlags( WStyle_Tool ) ) {
357 maximizeWindow( d->active->windowWidget() );
359 #ifndef QT_NO_WIDGET_TOPEXTRA
361 QPixmap pm(*w->icon());
362 if(pm.width() != 14 || pm.height() != 14) {
365 pm = im.smoothScale( 14, 14 );
367 d->maxtools->setPixmap( pm );
373 d->maxtools->setPixmap( pm );
378 d->active->internalRaise();
380 if ( change_focus ) {
381 if ( d->focus.find( d->active ) >=0 ) {
382 d->focus.removeRef( d->active );
383 // d->focus.append( d->active ); //VSR-
385 d->focus.append( d->active ); //VSR+
389 emit windowActivated( w );
394 Returns the active window, or 0 if no window is active.
396 QWidget* QWorkspaceP::activeWindow() const
398 return d->active?d->active->windowWidget():0;
402 void QWorkspaceP::place( QWidget* w)
404 int overlap, minOverlap = 0;
407 QRect r1(0, 0, 0, 0);
408 QRect r2(0, 0, 0, 0);
409 QRect maxRect = rect();
410 int x = maxRect.left(), y = maxRect.top();
411 QPoint wpos(maxRect.left(), maxRect.top());
413 bool firstPass = TRUE;
416 if ( y + w->height() > maxRect.bottom() ) {
418 } else if( x + w->width() > maxRect.right() ) {
423 r1.setRect(x, y, w->width(), w->height());
426 QPtrListIterator<QWorkspacePChild> it( d->windows );
427 while ( it.current () ) {
430 if (! d->icons.contains(l) && ! l->isHidden() && l != w ) {
431 if ( d->maxWindow == l )
434 r2.setRect(l->x(), l->y(), l->width(), l->height());
436 if (r2.intersects(r1)) {
437 r2.setCoords(QMAX(r1.left(), r2.left()),
438 QMAX(r1.top(), r2.top()),
439 QMIN(r1.right(), r2.right()),
440 QMIN(r1.bottom(), r2.bottom())
443 overlap += (r2.right() - r2.left()) *
444 (r2.bottom() - r2.top());
457 minOverlap = overlap;
458 } else if ( overlap >= 0 && overlap < minOverlap) {
459 minOverlap = overlap;
464 possible = maxRect.right();
465 if ( possible - w->width() > x) possible -= w->width();
468 QPtrListIterator<QWorkspacePChild> it( d->windows );
469 while ( it.current () ) {
472 if (! d->icons.contains(l) && ! l->isHidden() && l != w ) {
473 if ( d->maxWindow == l )
476 r2.setRect(l->x(), l->y(), l->width(), l->height());
478 if( ( y < r2.bottom() ) && ( r2.top() < w->height() + y ) ) {
480 possible = possible < r2.right() ?
481 possible : r2.right();
483 if( r2.left() - w->width() > x )
484 possible = possible < r2.left() - w->width() ?
485 possible : r2.left() - w->width();
491 } else if ( overlap == -2 ) {
493 possible = maxRect.bottom();
495 if ( possible - w->height() > y ) possible -= w->height();
498 QPtrListIterator<QWorkspacePChild> it( d->windows );
499 while ( it.current () ) {
502 if (l != w && ! d->icons.contains(w)) {
503 if ( d->maxWindow == l )
506 r2.setRect(l->x(), l->y(), l->width(), l->height());
509 possible = possible < r2.bottom() ?
510 possible : r2.bottom();
512 if( r2.top() - w->height() > y )
513 possible = possible < r2.top() - w->height() ?
514 possible : r2.top() - w->height();
521 while( overlap != 0 && overlap != -1 );
528 void QWorkspaceP::insertIcon( QWidget* w )
530 if ( !w || d->icons.contains( w ) )
532 d->icons.append( w );
533 if (w->parentWidget() != this )
534 w->reparent( this, 0, QPoint(0,0), FALSE);
537 QRect cr = updateWorkspace();
539 int y = cr.height() - w->height();
541 QPtrListIterator<QWidget> it( d->icons );
542 while ( it.current () ) {
543 QWidget* i = it.current();
545 if ( x > 0 && x + i->width() > cr.width() ){
551 i->geometry().intersects( QRect( x, y, w->width(), w->height() ) ) )
556 if ( isVisibleTo( parentWidget() ) ) {
564 void QWorkspaceP::removeIcon( QWidget* w)
566 if ( !d->icons.contains( w ) )
568 d->icons.remove( w );
574 void QWorkspaceP::resizeEvent( QResizeEvent * )
576 if ( d->maxWindow ) {
577 d->maxWindow->adjustToFullscreen();
578 ((QWorkspaceP*)d->maxWindow->windowWidget())->setWState( WState_Maximized );
581 QRect cr = updateWorkspace();
583 QPtrListIterator<QWorkspacePChild> it( d->windows );
584 while ( it.current () ) {
585 QWorkspacePChild* c = it.current();
587 if ( c->windowWidget() && !c->windowWidget()->testWFlags( WStyle_Tool ) )
592 if ( c->snappedDown )
593 y = cr.height() - c->height();
594 if ( c->snappedRight )
595 x = cr.width() - c->width();
597 if ( x != c->x() || y != c->y() )
604 void QWorkspaceP::showEvent( QShowEvent *e )
606 if ( d->maxWindow && !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
607 showMaximizeControls();
608 QWidget::showEvent( e );
609 if ( d->becomeActive ) {
610 activateWindow( d->becomeActive );
613 else if ( d->windows.count() > 0 && !d->active )
614 activateWindow( d->windows.first()->windowWidget() );
620 void QWorkspaceP::hideEvent( QHideEvent * )
623 if ( !isVisibleTo(0) && !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
624 hideMaximizeControls();
627 void QWorkspaceP::minimizeWindow( QWidget* w)
629 QWorkspacePChild* c = findChild( w );
630 QWorkspacePChild* oldActive = d->active; //VSR+
632 if ( !w || w && (!w->testWFlags( WStyle_Minimize ) || w->testWFlags( WStyle_Tool) ) )
636 QWorkspaceP *fake = (QWorkspaceP*)w;
638 setUpdatesEnabled( FALSE );
640 if ( c == d->maxWindow ) {
643 inCaptionChange = TRUE;
644 #ifndef QT_NO_WIDGET_TOPEXTRA
645 if ( !!d->topCaption )
646 topLevelWidget()->setCaption( d->topCaption );
648 inCaptionChange = FALSE;
649 if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this) )
650 hideMaximizeControls();
651 for (QPtrListIterator<QWorkspacePChild> it( d->windows ); it.current(); ++it ) {
652 QWorkspacePChild* c = it.current();
654 c->titlebar->setMovable( TRUE );
655 c->widgetResizeHandler->setActive( TRUE );
658 insertIcon( c->iconWidget() );
659 bool wasFocused = c->titlebar->isActive();
660 blockSignals( TRUE );//VSR+
662 blockSignals( FALSE );//VSR+
663 if ( wasFocused && ( !d->active || d->active && d->active->testWState( WState_Minimized ) ) ) { //VSR+
664 // if ( wasFocused && d->active && d->active->testWState( WState_Minimized ) ) { //VSR-
665 //VSR- blockSignals( TRUE );
666 activateWindow( w, FALSE );
667 //VSR- blockSignals( FALSE );
669 else if ( oldActive != d->active ) { //VSR+
670 emit ( windowActivated( d->active ? d->active->windowWidget() : 0 ) ); //VSR+
673 c->setGeometry( d->maxRestore );
674 if ( d->focus.find( c ) < 0 ) // VSR+
675 d->focus.append( c );
677 setUpdatesEnabled( TRUE );
680 fake->clearWState( WState_Maximized );
681 fake->setWState( WState_Minimized );
682 c->clearWState( WState_Maximized );
683 c->setWState( WState_Minimized );
687 void QWorkspaceP::normalizeWindow( QWidget* w)
689 QWorkspacePChild* c = findChild( w );
693 QWorkspaceP *fake = (QWorkspaceP*)w;
694 fake->clearWState( WState_Minimized | WState_Maximized );
695 if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this) && d->maxWindow ) {
696 hideMaximizeControls();
698 c->widgetResizeHandler->setActive( TRUE );
700 c->titlebar->setMovable(TRUE);
702 fake->clearWState( WState_Minimized | WState_Maximized );
703 c->clearWState( WState_Minimized | WState_Maximized );
705 if ( c == d->maxWindow ) {
706 c->setGeometry( d->maxRestore );
708 #ifndef QT_NO_WIDGET_TOPEXTRA
709 inCaptionChange = TRUE;
710 if ( !!d->topCaption )
711 topLevelWidget()->setCaption( d->topCaption );
712 inCaptionChange = FALSE;
716 removeIcon( c->iconw->parentWidget() );
720 if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
721 hideMaximizeControls();
722 for (QPtrListIterator<QWorkspacePChild> it( d->windows ); it.current(); ++it ) {
723 QWorkspacePChild* c = it.current();
725 c->titlebar->setMovable( TRUE );
726 c->widgetResizeHandler->setActive( TRUE );
728 activateWindow( w, TRUE );
734 void QWorkspaceP::maximizeWindow( QWidget* w)
736 QWorkspacePChild* c = findChild( w );
738 if ( !w || w && (!w->testWFlags( WStyle_Maximize ) || w->testWFlags( WStyle_Tool) ) )
740 if ( w->maximumSize().isValid() && ( w->maximumWidth() < width() || w->maximumHeight() < height() ) ) {
741 w->resize( w->maximumSize() );
746 setUpdatesEnabled( FALSE );
747 if (c->iconw && d->icons.contains( c->iconw->parentWidget() ) )
748 normalizeWindow( w );
749 QWorkspaceP *fake = (QWorkspaceP*)w;
751 QRect r( c->geometry() );
752 c->adjustToFullscreen();
755 qApp->sendPostedEvents( c, QEvent::Resize );
756 qApp->sendPostedEvents( c, QEvent::Move );
757 qApp->sendPostedEvents( c, QEvent::ShowWindowRequest );
758 if ( d->maxWindow != c ) {
760 d->maxWindow->setGeometry( d->maxRestore );
766 if(!style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
767 showMaximizeControls();
769 c->widgetResizeHandler->setActive( FALSE );
771 c->titlebar->setMovable( FALSE );
773 #ifndef QT_NO_WIDGET_TOPEXTRA
774 inCaptionChange = TRUE;
775 if ( !!d->topCaption )
776 topLevelWidget()->setCaption( tr("%1 - [%2]")
777 .arg(d->topCaption).arg(c->caption()) );
778 inCaptionChange = FALSE;
780 setUpdatesEnabled( TRUE );
784 fake->clearWState( WState_Minimized );
785 fake->setWState( WState_Maximized );
786 c->clearWState( WState_Minimized );
787 c->setWState( WState_Maximized );
791 void QWorkspaceP::showWindow( QWidget* w)
793 if ( d->maxWindow && w->testWFlags( WStyle_Maximize ) && !w->testWFlags( WStyle_Tool) )
795 else if ( !w->testWFlags( WStyle_Tool ) )
796 normalizeWindow( w );
798 w->parentWidget()->show();
800 d->maxWindow->raise();
805 QWorkspacePChild* QWorkspaceP::findChild( QWidget* w)
807 QPtrListIterator<QWorkspacePChild> it( d->windows );
808 while ( it.current () ) {
809 QWorkspacePChild* c = it.current();
811 if (c->windowWidget() == w)
818 Returns a list of all windows.
820 QWidgetList QWorkspaceP::windowList() const
823 QPtrListIterator<QWorkspacePChild> it( d->windows );
824 while ( it.current () ) {
825 QWorkspacePChild* c = it.current();
827 if ( c->windowWidget() )
828 windows.append( c->windowWidget() );
834 bool QWorkspaceP::eventFilter( QObject *o, QEvent * e)
837 static QWorkspaceP* tc = 0;
838 #ifndef QT_NO_MENUBAR
839 if ( o == d->maxtools && d->menuId != -1 ) {
840 switch ( e->type() ) {
841 case QEvent::MouseButtonPress:
843 QMenuBar* b = (QMenuBar*)o->parent();
846 if ( tc != this || t->elapsed() > QApplication::doubleClickInterval() ) {
847 if ( QApplication::reverseLayout() ) {
848 QPoint p = b->mapToGlobal( QPoint( b->x() + b->width(), b->y() + b->height() ) );
849 p.rx() -= d->popup->sizeHint().width();
850 popupOperationMenu( p );
852 popupOperationMenu( b->mapToGlobal( QPoint( b->x(), b->y() + b->height() ) ) );
865 return QWidget::eventFilter( o, e );
868 switch ( e->type() ) {
870 case QEvent::HideToParent:
871 if ( !o->isA( "QWorkspacePChild" ) || !isVisible() )
873 d->focus.removeRef( (QWorkspacePChild*)o );
874 if ( d->active != o )
876 if ( d->focus.isEmpty() ) {
879 d->autoFocusChange = TRUE;
880 activatePreviousWindow();
881 QWorkspacePChild* c = d->active;
883 d->active->windowWidget() &&
884 d->active->windowWidget()->testWFlags( WStyle_Tool ) ) {
885 activatePreviousWindow();
886 if ( d->active == c )
889 d->autoFocusChange = FALSE;
891 if ( d->maxWindow == o && d->maxWindow->isHidden() ) {
892 d->maxWindow->setGeometry( d->maxRestore );
895 maximizeWindow( d->active );
897 if ( !d->maxWindow ) {
899 if ( style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
900 QWorkspacePChild *wc = (QWorkspacePChild *)o;
901 wc->widgetResizeHandler->setActive( TRUE );
903 wc->titlebar->setMovable( TRUE );
905 hideMaximizeControls();
907 #ifndef QT_NO_WIDGET_TOPEXTRA
908 inCaptionChange = TRUE;
909 if ( !!d->topCaption )
910 topLevelWidget()->setCaption( d->topCaption );
911 inCaptionChange = FALSE;
917 if ( o->isA("QWorkspacePChild") && !d->focus.containsRef( (QWorkspacePChild*)o ) )
918 d->focus.append( (QWorkspacePChild*)o );
921 case QEvent::CaptionChange:
922 if ( inCaptionChange )
925 #ifndef QT_NO_WIDGET_TOPEXTRA
926 inCaptionChange = TRUE;
927 if ( o == topLevelWidget() )
928 d->topCaption = ((QWidget*)o)->caption();
930 if ( d->maxWindow && !!d->topCaption )
931 topLevelWidget()->setCaption( tr("%1 - [%2]")
932 .arg(d->topCaption).arg(d->maxWindow->caption()));
933 inCaptionChange = FALSE;
938 if ( o == topLevelWidget() )
940 QPtrListIterator<QWorkspacePChild> it( d->windows );
941 while ( it.current () ) {
942 QWorkspacePChild* c = it.current();
947 } else if ( o->inherits("QWorkspacePChild") ) {
950 if ( d->windows.count() > 1 || d->windows.first() && d->active != d->windows.first() )
951 activatePreviousWindow();
957 return QWidget::eventFilter( o, e);
960 void QWorkspaceP::showMaximizeControls()
962 #ifndef QT_NO_MENUBAR
963 Q_ASSERT(d->maxWindow);
966 // Do a breadth-first search first on every parent,
967 QWidget* w = parentWidget();
970 l = w->queryList( "QMenuBar", 0, FALSE, FALSE );
971 w = w->parentWidget();
972 if ( l && !l->count() ) {
978 // and query recursively if nothing is found.
979 if ( !l || !l->count() ) {
982 l = topLevelWidget()->queryList( "QMenuBar", 0, 0, TRUE );
984 if ( l && l->count() )
985 b = (QMenuBar *)l->first();
991 if ( !d->maxcontrols ) {
993 d->maxcontrols = new QFrame( topLevelWidget(), "qt_maxcontrols" );
994 QHBoxLayout* l = new QHBoxLayout( d->maxcontrols,
995 d->maxcontrols->frameWidth(), 0 );
996 if ( d->maxWindow->windowWidget()->testWFlags(WStyle_Minimize) ) {
997 QToolButton* iconB = new QToolButton( d->maxcontrols, "iconify" );
998 #ifndef QT_NO_TOOLTIP
999 QToolTip::add( iconB, tr( "Minimize" ) );
1001 l->addWidget( iconB );
1002 iconB->setFocusPolicy( NoFocus );
1003 iconB->setIconSet(style().stylePixmap(QStyle::SP_TitleBarMinButton));
1004 iconB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1005 connect( iconB, SIGNAL( clicked() ),
1006 this, SLOT( minimizeActiveWindow() ) );
1009 QToolButton* restoreB = new QToolButton( d->maxcontrols, "restore" );
1010 #ifndef QT_NO_TOOLTIP
1011 QToolTip::add( restoreB, tr( "Restore Down" ) );
1013 l->addWidget( restoreB );
1014 restoreB->setFocusPolicy( NoFocus );
1015 restoreB->setIconSet( style().stylePixmap(QStyle::SP_TitleBarNormalButton));
1016 restoreB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1017 connect( restoreB, SIGNAL( clicked() ),
1018 this, SLOT( normalizeActiveWindow() ) );
1021 QToolButton* closeB = new QToolButton( d->maxcontrols, "close" );
1022 #ifndef QT_NO_TOOLTIP
1023 QToolTip::add( closeB, tr( "Close" ) );
1025 l->addWidget( closeB );
1026 closeB->setFocusPolicy( NoFocus );
1027 closeB->setIconSet( style().stylePixmap(QStyle::SP_TitleBarCloseButton) );
1028 closeB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1029 connect( closeB, SIGNAL( clicked() ),
1030 this, SLOT( closeActiveWindow() ) );
1032 d->maxcontrols->setFixedSize( d->maxcontrols->minimumSizeHint() );
1035 if ( d->controlId == -1 || b->indexOf( d->controlId ) == -1 ) {
1036 QFrame* dmaxcontrols = d->maxcontrols;
1037 d->controlId = b->insertItem( dmaxcontrols, -1, b->count() );
1039 if ( d->active && ( d->menuId == -1 || b->indexOf( d->menuId ) == -1 ) ) {
1040 if ( !d->maxtools ) {
1041 d->maxtools = new QLabel( topLevelWidget(), "qt_maxtools" );
1042 d->maxtools->installEventFilter( this );
1044 #ifndef QT_NO_WIDGET_TOPEXTRA
1045 if ( d->active->windowWidget() && d->active->windowWidget()->icon() ) {
1046 QPixmap pm(*d->active->windowWidget()->icon());
1047 if(pm.width() != 14 || pm.height() != 14) {
1050 pm = im.smoothScale( 14, 14 );
1052 d->maxtools->setPixmap( pm );
1058 d->maxtools->setPixmap( pm );
1060 d->menuId = b->insertItem( d->maxtools, -1, 0 );
1066 void QWorkspaceP::hideMaximizeControls()
1068 #ifndef QT_NO_MENUBAR
1069 if ( d->maxmenubar ) {
1072 if ( d->maxmenubar->indexOf( mi ) != -1 )
1073 d->maxmenubar->removeItem( mi );
1076 int ci = d->controlId;
1077 if ( ci != -1 && d->maxmenubar->indexOf( ci ) != -1 )
1078 d->maxmenubar->removeItem( ci );
1086 void QWorkspaceP::closeActiveWindow()
1088 setUpdatesEnabled( FALSE );
1089 if ( d->maxWindow && d->maxWindow->windowWidget() )
1090 d->maxWindow->windowWidget()->close();
1091 else if ( d->active && d->active->windowWidget() )
1092 d->active->windowWidget()->close();
1093 setUpdatesEnabled( TRUE );
1097 void QWorkspaceP::closeAllWindows()
1099 QPtrListIterator<QWorkspacePChild> it( d->windows );
1100 QWorkspacePChild *c = 0;
1101 while ( ( c = it.current() ) != 0 ) {
1103 if ( c->windowWidget() )
1104 c->windowWidget()->close();
1108 void QWorkspaceP::normalizeActiveWindow()
1111 d->maxWindow->showNormal();
1112 else if ( d->active )
1113 d->active->showNormal();
1116 void QWorkspaceP::minimizeActiveWindow()
1119 d->maxWindow->showMinimized();
1120 else if ( d->active )
1121 d->active->showMinimized();
1124 void QWorkspaceP::showOperationMenu()
1126 if ( !d->active || !d->active->windowWidget() )
1128 Q_ASSERT( d->active->windowWidget()->testWFlags( WStyle_SysMenu ) );
1130 QPopupMenu *popup = d->active->windowWidget()->testWFlags( WStyle_Tool ) ? d->toolPopup : d->popup;
1131 if ( QApplication::reverseLayout() ) {
1132 p = QPoint( d->active->windowWidget()->mapToGlobal( QPoint(d->active->windowWidget()->width(),0) ) );
1133 p.rx() -= popup->sizeHint().width();
1135 p = QPoint( d->active->windowWidget()->mapToGlobal( QPoint(0,0) ) );
1137 if ( !d->active->isVisible() ) {
1138 p = d->active->iconWidget()->mapToGlobal( QPoint(0,0) );
1139 p.ry() -= popup->sizeHint().height();
1141 popupOperationMenu( p );
1144 void QWorkspaceP::popupOperationMenu( const QPoint& p)
1146 if ( !d->active || !d->active->windowWidget() || !d->active->windowWidget()->testWFlags( WStyle_SysMenu ) )
1148 if ( d->active->windowWidget()->testWFlags( WStyle_Tool ))
1149 d->toolPopup->popup( p );
1151 d->popup->popup( p );
1154 void QWorkspaceP::operationMenuAboutToShow()
1156 for ( int i = 1; i < 6; i++ ) {
1157 bool enable = d->active != 0;
1158 d->popup->setItemEnabled( i, enable );
1161 if ( !d->active || !d->active->windowWidget() )
1164 d->popup->setItemEnabled( 4, d->active->windowWidget()->testWFlags( WStyle_Minimize ) );
1165 d->popup->setItemEnabled( 5, d->active->windowWidget()->testWFlags( WStyle_Maximize ) );
1167 if ( d->active == d->maxWindow ) {
1168 d->popup->setItemEnabled( 2, FALSE );
1169 d->popup->setItemEnabled( 3, FALSE );
1170 d->popup->setItemEnabled( 5, FALSE );
1171 } else if ( d->active->isVisible() ){
1172 d->popup->setItemEnabled( 1, FALSE );
1174 d->popup->setItemEnabled( 2, FALSE );
1175 d->popup->setItemEnabled( 3, FALSE );
1176 d->popup->setItemEnabled( 4, FALSE );
1180 void QWorkspaceP::toolMenuAboutToShow()
1182 if ( !d->active || !d->active->windowWidget() )
1185 d->toolPopup->setItemEnabled( 3, !d->active->shademode );
1186 if ( d->active->shademode )
1187 d->toolPopup->changeItem( 6,
1188 QIconSet(style().stylePixmap(QStyle::SP_TitleBarUnshadeButton)), tr("&Unshade") );
1190 d->toolPopup->changeItem( 6, QIconSet(style().stylePixmap(QStyle::SP_TitleBarShadeButton)), tr("Sh&ade") );
1191 d->toolPopup->setItemEnabled( 6, d->active->windowWidget()->testWFlags( WStyle_MinMax ) );
1192 d->toolPopup->setItemChecked( 7, d->active->windowWidget()->testWFlags( WStyle_StaysOnTop ) );
1195 void QWorkspaceP::operationMenuActivated( int a )
1201 d->active->showNormal();
1204 d->active->doMove();
1207 if ( d->active->shademode )
1208 d->active->showShaded();
1209 d->active->doResize();
1212 d->active->showMinimized();
1215 d->active->showMaximized();
1218 d->active->showShaded();
1222 QWorkspaceP* w = (QWorkspaceP*)d->active->windowWidget();
1225 if ( w->testWFlags( WStyle_StaysOnTop ) ) {
1226 w->clearWFlags( WStyle_StaysOnTop );
1228 w->setWFlags( WStyle_StaysOnTop );
1229 w->parentWidget()->raise();
1238 void QWorkspaceP::activateNextWindow()
1240 if ( d->focus.isEmpty() )
1243 if ( d->focus.first() )
1244 activateWindow( d->focus.first()->windowWidget(), FALSE );
1248 int a = d->focus.find( d->active ) + 1;
1250 a = a % d->focus.count();
1252 if ( d->focus.at( a ) )
1253 activateWindow( d->focus.at( a )->windowWidget(), FALSE );
1258 void QWorkspaceP::activatePreviousWindow()
1260 if ( d->focus.isEmpty() ) {
1261 if ( d->windows.count() > 0 ) { //VSR+
1262 activateWindow( d->windows.last()->windowWidget() ); //VSR+
1267 if ( d->focus.last() )
1268 activateWindow( d->focus.first()->windowWidget(), FALSE );
1270 activateWindow( 0 );
1275 int a = d->focus.find( d->active ) - 1;
1278 a = d->focus.count()-1;
1280 if ( d->autoFocusChange ) {
1281 QWidget *widget = 0;
1282 while ( a >= 0 && d->focus.at( a ) && ( widget = d->focus.at( a )->windowWidget() ) && !widget->isVisible() )
1285 a = d->focus.count() - 1;
1288 if ( d->focus.at( a ) )
1289 activateWindow( d->focus.at( a )->windowWidget(), FALSE );
1291 activateWindow( 0 );
1296 \fn void QWorkspaceP::windowActivated( QWidget* w )
1298 This signal is emitted when the window widget \a w becomes active.
1299 Note that \a w can be null, and that more than one signal may be
1300 fired for one activation event.
1302 \sa activeWindow(), windowList()
1308 Arranges all child windows in a cascade pattern.
1312 void QWorkspaceP::cascade()
1315 d->maxWindow->showNormal();
1318 d->vbar->blockSignals( TRUE );
1319 d->vbar->setValue( 0 );
1320 d->vbar->blockSignals( FALSE );
1321 d->hbar->blockSignals( TRUE );
1322 d->hbar->setValue( 0 );
1323 d->hbar->blockSignals( FALSE );
1327 const int xoffset = 13;
1328 const int yoffset = 20;
1330 // make a list of all relevant mdi clients
1331 QPtrList<QWorkspacePChild> widgets;
1332 QWorkspacePChild* wc = 0;
1333 for ( wc = d->windows.first(); wc; wc = d->windows.next() )
1335 normalizeWindow( wc->windowWidget() );
1336 for ( wc = d->focus.first(); wc; wc = d->focus.next() )
1337 if ( wc->windowWidget()->isVisibleTo( this ) && !wc->windowWidget()->testWFlags( WStyle_Tool ) )
1338 widgets.append( wc );
1343 setUpdatesEnabled( FALSE );
1344 QPtrListIterator<QWorkspacePChild> it( widgets );
1345 int children = d->windows.count() - 1;
1346 while ( it.current () ) {
1347 QWorkspacePChild *child = it.current();
1349 child->setUpdatesEnabled( FALSE );
1350 bool hasSizeHint = FALSE;
1351 QSize prefSize = child->windowWidget()->sizeHint().expandedTo( child->windowWidget()->minimumSizeHint() );
1353 if ( !prefSize.isValid() )
1354 prefSize = QSize( width() - children * xoffset, height() - children * yoffset );
1357 prefSize = prefSize.expandedTo( child->windowWidget()->minimumSize() ).boundedTo( child->windowWidget()->maximumSize() );
1359 prefSize += QSize( child->baseSize().width(), child->baseSize().height() );
1361 int w = prefSize.width();
1362 int h = prefSize.height();
1364 child->showNormal();
1365 qApp->sendPostedEvents( 0, QEvent::ShowNormal );
1366 if ( y + h > height() )
1368 if ( x + w > width() )
1370 child->setGeometry( x, y, w, h );
1373 child->internalRaise();
1374 child->setUpdatesEnabled( TRUE );
1376 setUpdatesEnabled( TRUE );
1381 Arranges all child windows in a tile pattern.
1385 void QWorkspaceP::tile()
1388 d->maxWindow->showNormal();
1391 d->vbar->blockSignals( TRUE );
1392 d->vbar->setValue( 0 );
1393 d->vbar->blockSignals( FALSE );
1394 d->hbar->blockSignals( TRUE );
1395 d->hbar->setValue( 0 );
1396 d->hbar->blockSignals( FALSE );
1403 QWorkspacePChild* c;
1405 QPtrListIterator<QWorkspacePChild> it( d->windows );
1406 while ( it.current () ) {
1409 if ( !c->windowWidget()->isHidden() &&
1410 !c->windowWidget()->testWFlags( WStyle_StaysOnTop ) &&
1411 !c->windowWidget()->testWFlags( WStyle_Tool ) )
1415 while ( rows * cols < n ) {
1421 int add = cols * rows - n;
1422 bool* used = new bool[ cols*rows ];
1423 for ( int i = 0; i < rows*cols; i++ )
1428 int w = width() / cols;
1429 int h = height() / rows;
1432 while ( it.current () ) {
1435 if ( c->windowWidget()->isHidden() || c->windowWidget()->testWFlags( WStyle_Tool ) )
1437 if ( c->windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
1438 QPoint p = c->pos();
1439 if ( p.x()+c->width() < 0 )
1441 if ( p.x() > width() )
1442 p.setX( width() - c->width() );
1443 if ( p.y() + 10 < 0 )
1445 if ( p.y() > height() )
1446 p.setY( height() - c->height() );
1449 if ( p != c->pos() )
1450 c->QFrame::move( p );
1453 qApp->sendPostedEvents( 0, QEvent::ShowNormal );
1454 used[row*cols+col] = TRUE;
1456 c->setGeometry( col*w, row*h, QMIN( w, c->windowWidget()->maximumWidth()+c->baseSize().width() ),
1457 QMIN( 2*h, c->windowWidget()->maximumHeight()+c->baseSize().height() ) );
1458 used[(row+1)*cols+col] = TRUE;
1461 c->setGeometry( col*w, row*h, QMIN( w, c->windowWidget()->maximumWidth()+c->baseSize().width() ),
1462 QMIN( h, c->windowWidget()->maximumHeight()+c->baseSize().height() ) );
1464 while( row < rows && col < cols && used[row*cols+col] ) {
1466 if ( col == cols ) {
1477 QWorkspacePChild::QWorkspacePChild( QWidget* window, QWorkspaceP *parent,
1479 : QFrame( parent, name,
1480 WStyle_Customize | WStyle_NoBorder | WDestructiveClose | WNoMousePropagation | WSubWindow )
1482 setMouseTracking( TRUE );
1488 snappedRight = FALSE;
1489 snappedDown = FALSE;
1492 switch (window->focusPolicy()) {
1493 case QWidget::NoFocus:
1494 window->setFocusPolicy(QWidget::ClickFocus);
1496 case QWidget::TabFocus:
1497 window->setFocusPolicy(QWidget::StrongFocus);
1504 if ( window && window->testWFlags( WStyle_Title ) ) {
1505 titlebar = new QTitleBarP( window, this, "qt_ws_titlebar" );
1506 connect( titlebar, SIGNAL( doActivate() ),
1507 this, SLOT( activate() ) );
1508 connect( titlebar, SIGNAL( doClose() ),
1509 window, SLOT( close() ) );
1510 connect( titlebar, SIGNAL( doMinimize() ),
1511 this, SLOT( showMinimized() ) );
1512 connect( titlebar, SIGNAL( doNormal() ),
1513 this, SLOT( showNormal() ) );
1514 connect( titlebar, SIGNAL( doMaximize() ),
1515 this, SLOT( showMaximized() ) );
1516 connect( titlebar, SIGNAL( popupOperationMenu( const QPoint& ) ),
1517 this, SIGNAL( popupOperationMenu( const QPoint& ) ) );
1518 connect( titlebar, SIGNAL( showOperationMenu() ),
1519 this, SIGNAL( showOperationMenu() ) );
1520 connect( titlebar, SIGNAL( doShade() ),
1521 this, SLOT( showShaded() ) );
1522 connect( titlebar, SIGNAL( doubleClicked() ),
1523 this, SLOT( titleBarDoubleClicked() ) );
1526 if ( window && window->testWFlags( WStyle_Tool ) ) {
1527 setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
1529 setMinimumSize( 128, 0 );
1531 setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
1533 setMinimumSize( 128, 0 );
1536 childWidget = window;
1540 #ifndef QT_NO_WIDGET_TOPEXTRA
1541 setCaption( childWidget->caption() );
1548 bool hasBeenResized = childWidget->testWState( WState_Resized );
1550 if ( !hasBeenResized )
1551 cs = childWidget->sizeHint().expandedTo( childWidget->minimumSizeHint() );
1553 cs = childWidget->size();
1555 int th = titlebar ? titlebar->sizeHint().height() : 0;
1557 #ifndef QT_NO_WIDGET_TOPEXTRA
1558 if( childWidget->icon() ) {
1559 QPixmap pm(*childWidget->icon());
1560 if(pm.width() != 14 || pm.height() != 14) {
1563 pm = im.smoothScale( 14, 14 );
1565 titlebar->setIcon( pm );
1568 p = QPoint( contentsRect().x(),
1569 th + contentsRect().y() );
1570 s = QSize( cs.width() + 2*frameWidth(),
1571 cs.height() + 2*frameWidth() + th + 2 );
1573 p = QPoint( contentsRect().x(), contentsRect().y() );
1574 s = QSize( cs.width() + 2*frameWidth(),
1575 cs.height() + 2*frameWidth() );
1578 childWidget->reparent( this, p);
1581 childWidget->installEventFilter( this );
1583 widgetResizeHandler = new QWidgetResizeHandlerP( this, window );
1584 widgetResizeHandler->setMovingEnabled( FALSE );
1585 widgetResizeHandler->setSizeProtection( !parent->scrollBarsEnabled() );
1586 connect( widgetResizeHandler, SIGNAL( activate() ),
1587 this, SLOT( activate() ) );
1588 widgetResizeHandler->setExtraHeight( th + 2 );
1590 setBaseSize( baseSize() );
1593 QWorkspacePChild::~QWorkspacePChild()
1596 delete iconw->parentWidget();
1599 void QWorkspacePChild::moveEvent( QMoveEvent * )
1601 ((QWorkspaceP*) parentWidget() )->updateWorkspace();
1604 void QWorkspacePChild::resizeEvent( QResizeEvent * )
1606 QRect r = contentsRect();
1610 int th = titlebar->sizeHint().height();
1611 QRect tbrect( 0, 0, width(), th );
1612 if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) )
1613 tbrect = QRect( r.x(), r.y(), r.width(), th );
1614 titlebar->setGeometry( tbrect );
1615 cr = QRect( r.x(), r.y() + titlebar->height() + (shademode ? 5 : 1),
1616 r.width(), r.height() - titlebar->height() - 2 );
1624 windowSize = cr.size();
1625 childWidget->setGeometry( cr );
1626 ((QWorkspaceP*) parentWidget() )->updateWorkspace();
1629 QSize QWorkspacePChild::baseSize() const
1631 int th = titlebar ? titlebar->sizeHint().height() : 0;
1632 return QSize( 2*frameWidth(), 2*frameWidth() + th + 2 );
1635 QSize QWorkspacePChild::sizeHint() const
1638 return QFrame::sizeHint() + baseSize();
1639 return childWidget->sizeHint().expandedTo( childWidget->minimumSizeHint() ) + baseSize();
1642 QSize QWorkspacePChild::minimumSizeHint() const
1645 return QFrame::minimumSizeHint() + baseSize();
1646 QSize s = childWidget->minimumSize();
1648 s = childWidget->minimumSizeHint();
1649 return s + baseSize();
1652 void QWorkspacePChild::activate()
1654 ((QWorkspaceP*)parentWidget())->activateWindow( windowWidget() );
1657 bool QWorkspacePChild::eventFilter( QObject * o, QEvent * e)
1659 if ( !isActive() && ( e->type() == QEvent::MouseButtonPress ||
1660 e->type() == QEvent::FocusIn ) ) {
1662 ((QWorkspaceP*)parentWidget())->normalizeWindow( windowWidget() );
1664 ((QWorkspaceP*)parentWidget())->removeIcon( iconw->parentWidget() );
1665 delete iconw->parentWidget();
1672 // for all widgets except the window, we that's the only thing we
1673 // process, and if we have no childWidget we skip totally
1674 if ( o != childWidget || childWidget == 0 )
1677 switch ( e->type() ) {
1679 if ( ((QWorkspaceP*)parentWidget())->d->focus.find( this ) < 0 )
1680 ((QWorkspaceP*)parentWidget())->d->focus.append( this );
1681 if ( isVisibleTo( parentWidget() ) )
1683 if (( (QShowEvent*)e)->spontaneous() )
1686 case QEvent::ShowToParent:
1687 if ( windowWidget() && windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
1691 ((QWorkspaceP*)parentWidget())->showWindow( windowWidget() );
1693 case QEvent::ShowMaximized:
1694 if ( windowWidget()->maximumSize().isValid() &&
1695 ( windowWidget()->maximumWidth() < parentWidget()->width() ||
1696 windowWidget()->maximumHeight() < parentWidget()->height() ) ) {
1697 windowWidget()->resize( windowWidget()->maximumSize() );
1700 if ( windowWidget()->testWFlags( WStyle_Maximize ) && !windowWidget()->testWFlags( WStyle_Tool ) )
1701 ((QWorkspaceP*)parentWidget())->maximizeWindow( windowWidget() );
1703 ((QWorkspaceP*)parentWidget())->normalizeWindow( windowWidget() );
1705 case QEvent::ShowMinimized:
1706 ((QWorkspaceP*)parentWidget())->minimizeWindow( windowWidget() );
1708 case QEvent::ShowNormal:
1709 ((QWorkspaceP*)parentWidget())->normalizeWindow( windowWidget() );
1711 ((QWorkspaceP*)parentWidget())->removeIcon( iconw->parentWidget() );
1712 delete iconw->parentWidget();
1716 case QEvent::HideToParent:
1717 if ( !childWidget->isVisibleTo( this ) ) {
1718 QWidget * w = iconw;
1719 if ( w && ( w = w->parentWidget() ) ) {
1720 ((QWorkspaceP*)parentWidget())->removeIcon( w );
1726 case QEvent::CaptionChange:
1727 #ifndef QT_NO_WIDGET_TOPEXTRA
1728 setCaption( childWidget->caption() );
1730 iconw->setCaption( childWidget->caption() );
1733 case QEvent::IconChange:
1735 QWorkspaceP* ws = (QWorkspaceP*)parentWidget();
1738 #ifndef QT_NO_WIDGET_TOPEXTRA
1739 if ( childWidget->icon() ) {
1740 titlebar->setIcon( *childWidget->icon() );
1745 titlebar->setIcon( pm );
1748 if ( ws->d->maxWindow != this )
1751 if ( ws->d->maxtools ) {
1752 #ifndef QT_NO_WIDGET_TOPEXTRA
1753 if ( childWidget->icon() ) {
1754 QPixmap pm(*childWidget->icon());
1755 if(pm.width() != 14 || pm.height() != 14) {
1758 pm = im.smoothScale( 14, 14 );
1760 ws->d->maxtools->setPixmap( pm );
1766 ws->d->maxtools->setPixmap( pm );
1771 case QEvent::Resize:
1773 QResizeEvent* re = (QResizeEvent*)e;
1774 if ( re->size() != windowSize && !shademode )
1775 resize( re->size() + baseSize() );
1779 case QEvent::WindowDeactivate:
1781 titlebar->setActive( FALSE );
1784 case QEvent::WindowActivate:
1786 titlebar->setActive( act );
1793 return QFrame::eventFilter(o, e);
1796 bool QWorkspacePChild::focusNextPrevChild( bool next )
1798 QFocusData *f = focusData();
1800 QWidget *startingPoint = f->home();
1801 QWidget *candidate = 0;
1802 QWidget *w = next ? f->next() : f->prev();
1803 while( !candidate && w != startingPoint ) {
1804 if ( w != startingPoint &&
1805 (w->focusPolicy() & TabFocus) == TabFocus
1806 && w->isEnabled() &&!w->focusProxy() && w->isVisible() )
1808 w = next ? f->next() : f->prev();
1812 QObjectList *ol = queryList();
1813 bool ischild = ol->findRef( candidate ) != -1;
1816 startingPoint = f->home();
1817 QWidget *nw = next ? f->prev() : f->next();
1818 QObjectList *ol2 = queryList();
1819 QWidget *lastValid = 0;
1820 candidate = startingPoint;
1821 while ( nw != startingPoint ) {
1822 if ( ( candidate->focusPolicy() & TabFocus ) == TabFocus
1823 && candidate->isEnabled() &&!candidate->focusProxy() && candidate->isVisible() )
1824 lastValid = candidate;
1825 if ( ol2->findRef( nw ) == -1 ) {
1826 candidate = lastValid;
1830 nw = next ? f->prev() : f->next();
1839 candidate->setFocus();
1843 void QWorkspacePChild::childEvent( QChildEvent* e)
1845 if ( e->type() == QEvent::ChildRemoved && e->child() == childWidget ) {
1848 ((QWorkspaceP*)parentWidget())->removeIcon( iconw->parentWidget() );
1849 delete iconw->parentWidget();
1856 void QWorkspacePChild::doResize()
1858 widgetResizeHandler->doResize();
1861 void QWorkspacePChild::doMove()
1863 widgetResizeHandler->doMove();
1866 void QWorkspacePChild::enterEvent( QEvent * )
1870 void QWorkspacePChild::leaveEvent( QEvent * )
1872 #ifndef QT_NO_CURSOR
1873 if ( !widgetResizeHandler->isButtonDown() )
1874 setCursor( arrowCursor );
1878 void QWorkspacePChild::drawFrame( QPainter *p )
1880 QStyle::SFlags flags = QStyle::Style_Default;
1881 QStyleOption opt(lineWidth(),midLineWidth());
1884 flags |= QStyle::Style_Active;
1886 style().drawPrimitive( QStyle::PE_WindowFrame, p, rect(), colorGroup(), flags, opt );
1889 void QWorkspacePChild::styleChange( QStyle & )
1893 QVBox *vbox = (QVBox*)iconw->parentWidget()->qt_cast( "QVBox" );
1895 if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) ) {
1896 vbox->setFrameStyle( QFrame::WinPanel | QFrame::Raised );
1897 vbox->resize( 196+2*vbox->frameWidth(), 20 + 2*vbox->frameWidth() );
1899 vbox->resize( 196, 20 );
1904 static bool isChildOf( QWidget * child, QWidget * parent )
1906 if ( !parent || !child )
1908 QWidget * w = child;
1909 while( w && w != parent )
1910 w = w->parentWidget();
1915 void QWorkspacePChild::setActive( bool b )
1927 titlebar->setActive( act );
1929 iconw->setActive( act );
1931 QObjectList* ol = childWidget->queryList( "QWidget" );
1934 for ( o = ol->first(); o; o = ol->next() )
1935 o->removeEventFilter( this );
1936 bool hasFocus = isChildOf( focusWidget(), childWidget );
1938 if ( lastfocusw && ol->contains( lastfocusw ) &&
1939 lastfocusw->focusPolicy() != NoFocus ) {
1940 // this is a bug if lastfocusw has been deleted, a new
1941 // widget has been created, and the new one is a child
1942 // of the same window as the old one. but even though
1943 // it's a bug the behaviour is reasonable
1944 lastfocusw->setFocus();
1945 } else if ( childWidget->focusPolicy() != NoFocus ) {
1946 childWidget->setFocus();
1948 // find something, anything, that accepts focus, and use that.
1950 while( o && ((QWidget*)o)->focusPolicy() == NoFocus )
1953 ((QWidget*)o)->setFocus();
1958 if ( isChildOf( focusWidget(), childWidget ) )
1959 lastfocusw = focusWidget();
1961 for ( o = ol->first(); o; o = ol->next() ) {
1962 o->removeEventFilter( this );
1963 o->installEventFilter( this );
1969 bool QWorkspacePChild::isActive() const
1974 QWidget* QWorkspacePChild::windowWidget() const
1980 QWidget* QWorkspacePChild::iconWidget() const
1983 QWorkspacePChild* that = (QWorkspacePChild*) this;
1984 QVBox* vbox = new QVBox(0, "qt_vbox" );
1985 if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) ) {
1986 vbox->setFrameStyle( QFrame::WinPanel | QFrame::Raised );
1987 vbox->resize( 196+2*vbox->frameWidth(), 20 + 2*vbox->frameWidth() );
1989 vbox->resize( 196, 20 );
1991 QTitleBarP *tb = new QTitleBarP( windowWidget(), vbox, "_workspacechild_icon_");
1992 ((QWorkspacePChild*)tb)->setWState( WState_Minimized );
1994 iconw->setActive( isActive() );
1995 connect( iconw, SIGNAL( doActivate() ),
1996 this, SLOT( activate() ) );
1997 connect( iconw, SIGNAL( doClose() ),
1998 windowWidget(), SLOT( close() ) );
1999 connect( iconw, SIGNAL( doNormal() ),
2000 this, SLOT( showNormal() ) );
2001 connect( iconw, SIGNAL( doMaximize() ),
2002 this, SLOT( showMaximized() ) );
2003 connect( iconw, SIGNAL( popupOperationMenu( const QPoint& ) ),
2004 this, SIGNAL( popupOperationMenu( const QPoint& ) ) );
2005 connect( iconw, SIGNAL( showOperationMenu() ),
2006 this, SIGNAL( showOperationMenu() ) );
2007 connect( iconw, SIGNAL( doubleClicked() ),
2008 this, SLOT( titleBarDoubleClicked() ) );
2010 #ifndef QT_NO_WIDGET_TOPEXTRA
2011 if ( windowWidget() ) {
2012 iconw->setCaption( windowWidget()->caption() );
2013 if ( windowWidget()->icon() )
2014 iconw->setIcon( *windowWidget()->icon() );
2017 return iconw->parentWidget();
2020 void QWorkspacePChild::showMinimized()
2022 QApplication::postEvent( windowWidget(), new QEvent( QEvent::ShowMinimized ) );
2025 void QWorkspacePChild::showMaximized()
2027 QApplication::postEvent( windowWidget(), new QEvent( QEvent::ShowMaximized ) );
2030 void QWorkspacePChild::showNormal()
2032 QApplication::postEvent( windowWidget(), new QEvent( QEvent::ShowNormal ) );
2035 void QWorkspacePChild::showShaded()
2039 Q_ASSERT( windowWidget()->testWFlags( WStyle_MinMax ) && windowWidget()->testWFlags( WStyle_Tool ) );
2040 ((QWorkspaceP*)parentWidget())->activateWindow( windowWidget() );
2042 QWorkspacePChild* fake = (QWorkspacePChild*)windowWidget();
2043 fake->clearWState( WState_Minimized );
2044 clearWState( WState_Minimized );
2047 resize( shadeRestore );
2048 setMinimumSize( shadeRestoreMin );
2050 shadeRestore = size();
2051 shadeRestoreMin = minimumSize();
2052 setMinimumHeight(0);
2054 QWorkspacePChild* fake = (QWorkspacePChild*)windowWidget();
2055 fake->setWState( WState_Minimized );
2056 setWState( WState_Minimized );
2058 resize( width(), titlebar->height() + 2*lineWidth() + 1 );
2063 void QWorkspacePChild::titleBarDoubleClicked()
2065 if ( !windowWidget() )
2067 if ( windowWidget()->testWFlags( WStyle_MinMax ) ) {
2068 if ( windowWidget()->testWFlags( WStyle_Tool ) )
2072 else if ( windowWidget()->testWFlags( WStyle_Maximize ) )
2077 void QWorkspacePChild::adjustToFullscreen()
2079 qApp->sendPostedEvents( this, QEvent::Resize );
2080 qApp->sendPostedEvents( childWidget, QEvent::Resize );
2081 qApp->sendPostedEvents( childWidget, QEvent::Move );
2082 if(style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
2083 setGeometry( 0, 0, parentWidget()->width(), parentWidget()->height());
2085 setGeometry( -childWidget->x(), -childWidget->y(),
2086 parentWidget()->width() + width() - childWidget->width(),
2087 parentWidget()->height() + height() - childWidget->height() );
2089 setWState( WState_Maximized );
2090 ((QWorkspacePChild*)childWidget)->setWState( WState_Maximized );
2093 void QWorkspacePChild::adjustSize()
2095 if ( !testWState(WState_Polished) )
2098 QSize prefSize = windowWidget()->sizeHint().expandedTo( windowWidget()->minimumSizeHint() );
2099 prefSize = prefSize.expandedTo( windowWidget()->minimumSize() ).boundedTo( windowWidget()->maximumSize() );
2100 prefSize += baseSize();
2105 void QWorkspacePChild::setCaption( const QString& cap )
2108 titlebar->setCaption( cap );
2109 #ifndef QT_NO_WIDGET_TOPEXTRA
2110 QWidget::setCaption( cap );
2114 void QWorkspacePChild::internalRaise()
2116 setUpdatesEnabled( FALSE );
2118 iconw->parentWidget()->raise();
2121 if ( !windowWidget() || windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
2122 setUpdatesEnabled( TRUE );
2126 QPtrListIterator<QWorkspacePChild> it( ((QWorkspaceP*)parent())->d->windows );
2127 while ( it.current () ) {
2128 QWorkspacePChild* c = it.current();
2130 if ( c->windowWidget() &&
2131 !c->windowWidget()->isHidden() &&
2132 c->windowWidget()->testWFlags( WStyle_StaysOnTop ) )
2136 setUpdatesEnabled( TRUE );
2139 void QWorkspacePChild::move( int x, int y )
2144 if ( windowWidget() && windowWidget()->testWFlags( WStyle_Tool ) ) {
2148 if ( QABS( x ) < dx )
2150 if ( QABS( y ) < dy )
2152 if ( QABS( x + width() - parentWidget()->width() ) < dx ) {
2153 nx = parentWidget()->width() - width();
2154 snappedRight = TRUE;
2156 snappedRight = FALSE;
2158 if ( QABS( y + height() - parentWidget()->height() ) < dy ) {
2159 ny = parentWidget()->height() - height();
2162 snappedDown = FALSE;
2164 QFrame::move( nx, ny );
2167 bool QWorkspaceP::scrollBarsEnabled() const
2169 return d->vbar != 0;
2172 /*! \property QWorkspaceP::scrollBarsEnabled
2173 \brief whether the workspace provides scrollbars
2175 If this property is set to TRUE, it is possible to resize child
2176 windows over the right or the bottom edge out of the visible area
2177 of the workspace. The workspace shows scrollbars to make it
2178 possible for the user to access those windows. If this property is
2179 set to FALSE (the default), resizing windows out of the visible
2180 area of the workspace is not permitted.
2182 void QWorkspaceP::setScrollBarsEnabled( bool enable )
2184 if ( (d->vbar != 0) == enable )
2187 d->xoffset = d->yoffset = 0;
2189 d->vbar = new QScrollBar( Vertical, this, "vertical scrollbar" );
2190 connect( d->vbar, SIGNAL( valueChanged(int) ), this, SLOT( scrollBarChanged() ) );
2191 d->hbar = new QScrollBar( Horizontal, this, "horizontal scrollbar" );
2192 connect( d->hbar, SIGNAL( valueChanged(int) ), this, SLOT( scrollBarChanged() ) );
2193 d->corner = new QWidget( this, "qt_corner" );
2199 d->vbar = d->hbar = 0;
2203 QPtrListIterator<QWorkspacePChild> it( d->windows );
2204 while ( it.current () ) {
2205 QWorkspacePChild *child = it.current();
2207 child->widgetResizeHandler->setSizeProtection( !enable );
2211 QRect QWorkspaceP::updateWorkspace()
2213 if ( !isUpdatesEnabled() )
2218 if ( scrollBarsEnabled() && !d->maxWindow ) {
2223 d->maxWindow->raise();
2225 QRect r( 0, 0, 0, 0 );
2226 QPtrListIterator<QWorkspacePChild> it( d->windows );
2227 while ( it.current () ) {
2228 QWorkspacePChild *child = it.current();
2230 if ( !child->isHidden() )
2231 r = r.unite( child->geometry() );
2233 d->vbar->blockSignals( TRUE );
2234 d->hbar->blockSignals( TRUE );
2236 int hsbExt = d->hbar->sizeHint().height();
2237 int vsbExt = d->vbar->sizeHint().width();
2240 bool showv = d->yoffset || d->yoffset + r.bottom() - height() + 1 > 0 || d->yoffset + r.top() < 0;
2241 bool showh = d->xoffset || d->xoffset + r.right() - width() + 1 > 0 || d->xoffset + r.left() < 0;
2243 if ( showh && !showv)
2244 showv = d->yoffset + r.bottom() - height() + hsbExt + 1 > 0;
2245 if ( showv && !showh )
2246 showh = d->xoffset + r.right() - width() + vsbExt + 1 > 0;
2254 d->vbar->setSteps( QMAX( height() / 12, 30 ), height() - hsbExt );
2255 d->vbar->setRange( QMIN( 0, d->yoffset + QMIN( 0, r.top() ) ), QMAX( 0, d->yoffset + QMAX( 0, r.bottom() - height() + hsbExt + 1) ) );
2256 d->vbar->setGeometry( width() - vsbExt, 0, vsbExt, height() - hsbExt );
2257 d->vbar->setValue( d->yoffset );
2264 d->hbar->setSteps( QMAX( width() / 12, 30 ), width() - vsbExt );
2265 d->hbar->setRange( QMIN( 0, d->xoffset + QMIN( 0, r.left() ) ), QMAX( 0, d->xoffset + QMAX( 0, r.right() - width() + vsbExt + 1) ) );
2266 d->hbar->setGeometry( 0, height() - hsbExt, width() - vsbExt, hsbExt );
2267 d->hbar->setValue( d->xoffset );
2273 if ( showh && showv ) {
2274 d->corner->setGeometry( width() - vsbExt, height() - hsbExt, vsbExt, hsbExt );
2280 d->vbar->blockSignals( FALSE );
2281 d->hbar->blockSignals( FALSE );
2283 cr.setRect( 0, 0, width() - vsbExt, height() - hsbExt );
2286 QPtrListIterator<QWidget> ii( d->icons );
2287 while ( ii.current() ) {
2288 QWorkspacePChild* w = (QWorkspacePChild*)ii.current();
2293 if ( x+w->width() > cr.width() ) {
2295 x = cr.width() - w->width();
2297 if ( y+w->height() > cr.height() ) {
2298 y = cr.height() - w->height();
2309 void QWorkspaceP::scrollBarChanged()
2311 int ver = d->yoffset - d->vbar->value();
2312 int hor = d->xoffset - d->hbar->value();
2313 d->yoffset = d->vbar->value();
2314 d->xoffset = d->hbar->value();
2316 QPtrListIterator<QWorkspacePChild> it( d->windows );
2317 while ( it.current () ) {
2318 QWorkspacePChild *child = it.current();
2320 // we do not use move() due to the reimplementation in QWorkspacePChild
2321 child->setGeometry( child->x() + hor, child->y() + ver, child->width(), child->height() );
2328 void QWorkspaceP::styleChange( QStyle &olds )
2330 int fs = style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this);
2331 if ( isVisibleTo(0) && d->maxWindow &&
2332 fs != olds.styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
2334 hideMaximizeControls();
2336 showMaximizeControls();
2338 QWidget::styleChange(olds);
2344 static bool resizeHorizontalDirectionFixed = FALSE;
2345 static bool resizeVerticalDirectionFixed = FALSE;
2347 QWidgetResizeHandlerP::QWidgetResizeHandlerP( QWidget *parent, QWidget *cw, const char *name )
2348 : QObject( parent, name ), widget( parent ), childWidget( cw ? cw : parent ),
2349 extrahei( 0 ), buttonDown( FALSE ), moveResizeMode( FALSE ), sizeprotect( TRUE ), moving( TRUE )
2352 widget->setMouseTracking( TRUE );
2353 range = widget->inherits( "QFrame" ) ? ((QFrame*)widget)->frameWidth() : RANGE;
2354 range = QMAX( RANGE, range );
2356 qApp->installEventFilter( this );
2359 static QWidget *childOf( QWidget *w, QWidget *child )
2364 child = child->parentWidget();
2369 bool QWidgetResizeHandlerP::eventFilter( QObject *o, QEvent *ee )
2371 if ( !active || !o->isWidgetType() )
2374 QWidget *w = childOf( widget, (QWidget*)o );
2375 if ( !w || o->inherits( "QSizeGrip" ) )
2378 QMouseEvent *e = (QMouseEvent*)ee;
2379 switch ( e->type() ) {
2380 case QEvent::MouseButtonPress: {
2381 if ( w->isMaximized() )
2383 if ( !widget->rect().contains( widget->mapFromGlobal( e->globalPos() ) ) )
2385 if ( e->button() == LeftButton ) {
2387 bool me = isMovingEnabled();
2388 setMovingEnabled( me && o == widget );
2389 mouseMoveEvent( e );
2390 setMovingEnabled( me );
2392 moveOffset = widget->mapFromGlobal( e->globalPos() );
2393 invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
2396 case QEvent::MouseButtonRelease:
2397 if ( w->isMaximized() )
2399 if ( e->button() == LeftButton ) {
2400 moveResizeMode = FALSE;
2402 widget->releaseMouse();
2403 widget->releaseKeyboard();
2406 case QEvent::MouseMove: {
2407 if ( w->isMaximized() )
2409 bool me = isMovingEnabled();
2410 setMovingEnabled( me && o == widget );
2411 mouseMoveEvent( e );
2412 setMovingEnabled( me );
2413 if ( buttonDown && mode != Center )
2416 case QEvent::KeyPress:
2417 keyPressEvent( (QKeyEvent*)e );
2419 case QEvent::AccelOverride:
2421 ((QKeyEvent*)ee)->accept();
2431 void QWidgetResizeHandlerP::mouseMoveEvent( QMouseEvent *e )
2433 QPoint pos = widget->mapFromGlobal( e->globalPos() );
2434 if ( !moveResizeMode && ( !buttonDown || ( e->state() & LeftButton ) == 0 ) ) {
2435 if ( pos.y() <= range && pos.x() <= range)
2437 else if ( pos.y() >= widget->height()-range && pos.x() >= widget->width()-range)
2439 else if ( pos.y() >= widget->height()-range && pos.x() <= range)
2441 else if ( pos.y() <= range && pos.x() >= widget->width()-range)
2443 else if ( pos.y() <= range )
2445 else if ( pos.y() >= widget->height()-range )
2447 else if ( pos.x() <= range )
2449 else if ( pos.x() >= widget->width()-range )
2454 if ( widget->isMinimized() )
2456 #ifndef QT_NO_CURSOR
2457 setMouseCursor( mode );
2462 if ( buttonDown && !isMovingEnabled() && mode == Center && !moveResizeMode )
2465 if ( widget->testWState( WState_ConfigPending ) )
2468 QPoint globalPos = widget->parentWidget( TRUE ) ?
2469 widget->parentWidget( TRUE )->mapFromGlobal( e->globalPos() ) : e->globalPos();
2470 if ( widget->parentWidget( TRUE ) && !widget->parentWidget( TRUE )->rect().contains( globalPos ) ) {
2471 if ( globalPos.x() < 0 )
2473 if ( globalPos.y() < 0 )
2475 if ( sizeprotect && globalPos.x() > widget->parentWidget()->width() )
2476 globalPos.rx() = widget->parentWidget()->width();
2477 if ( sizeprotect && globalPos.y() > widget->parentWidget()->height() )
2478 globalPos.ry() = widget->parentWidget()->height();
2481 QPoint p = globalPos + invertedMoveOffset;
2482 QPoint pp = globalPos - moveOffset;
2485 int mw = QMAX( childWidget->minimumSizeHint().width(),
2486 childWidget->minimumWidth() );
2487 int mh = QMAX( childWidget->minimumSizeHint().height(),
2488 childWidget->minimumHeight() );
2489 if ( childWidget != widget ) {
2490 if ( widget->inherits( "QFrame" ) )
2491 fw = ( (QFrame *) widget )->frameWidth();
2493 mh += 2 * fw + extrahei;
2496 QSize mpsize( widget->geometry().right() - pp.x() + 1,
2497 widget->geometry().bottom() - pp.y() + 1 );
2498 mpsize = mpsize.expandedTo( widget->minimumSize() ).expandedTo( QSize(mw, mh) );
2499 QPoint mp( widget->geometry().right() - mpsize.width() + 1,
2500 widget->geometry().bottom() - mpsize.height() + 1 );
2502 QRect geom = widget->geometry();
2506 geom = QRect( mp, widget->geometry().bottomRight() ) ;
2509 geom = QRect( widget->geometry().topLeft(), p ) ;
2512 geom = QRect( QPoint(mp.x(), widget->geometry().y() ), QPoint( widget->geometry().right(), p.y()) ) ;
2515 geom = QRect( QPoint( widget->geometry().x(), mp.y() ), QPoint( p.x(), widget->geometry().bottom()) ) ;
2518 geom = QRect( QPoint( widget->geometry().left(), mp.y() ), widget->geometry().bottomRight() ) ;
2521 geom = QRect( widget->geometry().topLeft(), QPoint( widget->geometry().right(), p.y() ) ) ;
2524 geom = QRect( QPoint( mp.x(), widget->geometry().top() ), widget->geometry().bottomRight() ) ;
2527 geom = QRect( widget->geometry().topLeft(), QPoint( p.x(), widget->geometry().bottom() ) ) ;
2530 if ( isMovingEnabled() || moveResizeMode )
2531 geom.moveTopLeft( pp );
2537 QSize maxsize( childWidget->maximumSize() );
2538 if ( childWidget != widget )
2539 maxsize += QSize( 2 * fw, 2 * fw + extrahei );
2541 geom = QRect( geom.topLeft(),
2542 geom.size().expandedTo( widget->minimumSize() )
2543 .expandedTo( QSize(mw, mh) )
2544 .boundedTo( maxsize ) );
2546 if ( geom != widget->geometry() &&
2547 ( widget->isTopLevel() || widget->parentWidget()->rect().intersects( geom ) ) ) {
2548 if ( widget->isMinimized() )
2549 widget->move( geom.topLeft() );
2551 widget->setGeometry( geom );
2554 #if defined(Q_WS_WIN)
2556 #if defined(UNICODE)
2558 if ( qWinVersion() & WV_NT_based ) {
2560 while(PeekMessageW( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE ))
2568 while(PeekMessageA( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE ))
2574 QApplication::syncX();
2577 void QWidgetResizeHandlerP::setMouseCursor( MousePosition m )
2579 #ifndef QT_NO_CURSOR
2583 widget->setCursor( sizeFDiagCursor );
2587 widget->setCursor( sizeBDiagCursor );
2591 widget->setCursor( sizeVerCursor );
2595 widget->setCursor( sizeHorCursor );
2598 widget->setCursor( arrowCursor );
2604 void QWidgetResizeHandlerP::keyPressEvent( QKeyEvent * e )
2606 if ( !isMove() && !isResize() )
2608 bool is_control = e->state() & ControlButton;
2609 int delta = is_control?1:8;
2610 QPoint pos = QCursor::pos();
2611 switch ( e->key() ) {
2614 if ( pos.x() <= QApplication::desktop()->geometry().left() ) {
2615 if ( mode == TopLeft || mode == BottomLeft ) {
2616 moveOffset.rx() += delta;
2617 invertedMoveOffset.rx() += delta;
2619 moveOffset.rx() -= delta;
2620 invertedMoveOffset.rx() -= delta;
2623 if ( isResize() && !resizeHorizontalDirectionFixed ) {
2624 resizeHorizontalDirectionFixed = TRUE;
2625 if ( mode == BottomRight )
2627 else if ( mode == TopRight )
2629 #ifndef QT_NO_CURSOR
2630 setMouseCursor( mode );
2631 widget->grabMouse( widget->cursor() );
2633 widget->grabMouse();
2639 if ( pos.x() >= QApplication::desktop()->geometry().right() ) {
2640 if ( mode == TopRight || mode == BottomRight ) {
2641 moveOffset.rx() += delta;
2642 invertedMoveOffset.rx() += delta;
2644 moveOffset.rx() -= delta;
2645 invertedMoveOffset.rx() -= delta;
2648 if ( isResize() && !resizeHorizontalDirectionFixed ) {
2649 resizeHorizontalDirectionFixed = TRUE;
2650 if ( mode == BottomLeft )
2652 else if ( mode == TopLeft )
2654 #ifndef QT_NO_CURSOR
2655 setMouseCursor( mode );
2656 widget->grabMouse( widget->cursor() );
2658 widget->grabMouse();
2664 if ( pos.y() <= QApplication::desktop()->geometry().top() ) {
2665 if ( mode == TopLeft || mode == TopRight ) {
2666 moveOffset.ry() += delta;
2667 invertedMoveOffset.ry() += delta;
2669 moveOffset.ry() -= delta;
2670 invertedMoveOffset.ry() -= delta;
2673 if ( isResize() && !resizeVerticalDirectionFixed ) {
2674 resizeVerticalDirectionFixed = TRUE;
2675 if ( mode == BottomLeft )
2677 else if ( mode == BottomRight )
2679 #ifndef QT_NO_CURSOR
2680 setMouseCursor( mode );
2681 widget->grabMouse( widget->cursor() );
2683 widget->grabMouse();
2689 if ( pos.y() >= QApplication::desktop()->geometry().bottom() ) {
2690 if ( mode == BottomLeft || mode == BottomRight ) {
2691 moveOffset.ry() += delta;
2692 invertedMoveOffset.ry() += delta;
2694 moveOffset.ry() -= delta;
2695 invertedMoveOffset.ry() -= delta;
2698 if ( isResize() && !resizeVerticalDirectionFixed ) {
2699 resizeVerticalDirectionFixed = TRUE;
2700 if ( mode == TopLeft )
2702 else if ( mode == TopRight )
2704 #ifndef QT_NO_CURSOR
2705 setMouseCursor( mode );
2706 widget->grabMouse( widget->cursor() );
2708 widget->grabMouse();
2716 moveResizeMode = FALSE;
2717 widget->releaseMouse();
2718 widget->releaseKeyboard();
2724 QCursor::setPos( pos );
2728 void QWidgetResizeHandlerP::doResize()
2733 moveResizeMode = TRUE;
2735 moveOffset = widget->mapFromGlobal( QCursor::pos() );
2736 if ( moveOffset.x() < widget->width()/2) {
2737 if ( moveOffset.y() < widget->height()/2)
2742 if ( moveOffset.y() < widget->height()/2)
2747 invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
2748 #ifndef QT_NO_CURSOR
2749 setMouseCursor( mode );
2750 widget->grabMouse( widget->cursor() );
2752 widget->grabMouse();
2754 widget->grabKeyboard();
2755 resizeHorizontalDirectionFixed = FALSE;
2756 resizeVerticalDirectionFixed = FALSE;
2759 void QWidgetResizeHandlerP::doMove()
2765 moveResizeMode = TRUE;
2767 moveOffset = widget->mapFromGlobal( QCursor::pos() );
2768 invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
2769 #ifndef QT_NO_CURSOR
2770 widget->grabMouse( SizeAllCursor );
2772 widget->grabMouse();
2774 widget->grabKeyboard();
2777 #ifndef QT_NO_TOOLTIP
2778 class QTitleBarPTip : public QToolTip
2781 QTitleBarPTip( QWidget * parent ) : QToolTip( parent ) { }
2783 void maybeTip( const QPoint &pos )
2785 if ( !parentWidget()->inherits( "QTitleBarP" ) )
2787 QTitleBarP *t = (QTitleBarP *)parentWidget();
2790 QStyle::SubControl ctrl = t->style().querySubControl(QStyle::CC_TitleBar, t, pos);
2791 QSize controlSize = t->style().querySubControlMetrics(QStyle::CC_TitleBar, t, ctrl).size();
2793 QWidget *window = t->window();
2796 case QStyle::SC_TitleBarSysMenu:
2797 if ( t->testWFlags( WStyle_SysMenu ) )
2798 tipstring = QTitleBarP::tr( "System Menu" );
2801 case QStyle::SC_TitleBarShadeButton:
2802 if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) )
2803 tipstring = QTitleBarP::tr( "Shade" );
2806 case QStyle::SC_TitleBarUnshadeButton:
2807 if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) )
2808 tipstring = QTitleBarP::tr( "Unshade" );
2811 case QStyle::SC_TitleBarNormalButton:
2812 case QStyle::SC_TitleBarMinButton:
2813 if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Minimize ) ) {
2814 if( window->isMinimized() )
2815 tipstring = QTitleBarP::tr( "Normalize" );
2817 tipstring = QTitleBarP::tr( "Minimize" );
2821 case QStyle::SC_TitleBarMaxButton:
2822 if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Maximize ) )
2823 tipstring = QTitleBarP::tr( "Maximize" );
2826 case QStyle::SC_TitleBarCloseButton:
2827 if ( t->testWFlags( WStyle_SysMenu ) )
2828 tipstring = QTitleBarP::tr( "Close" );
2835 #ifndef QT_NO_WIDGET_TOPEXTRA
2836 if ( tipstring.isEmpty() ) {
2837 if ( t->visibleText() != t->caption() )
2838 tipstring = t->caption();
2841 if(!tipstring.isEmpty())
2842 tip( QRect(pos, controlSize), tipstring );
2847 class QTitleBarPPrivate
2851 : toolTip( 0 ), act( 0 ), window( 0 ), movable( 1 ), pressed( 0 ), autoraise(0)
2855 QStyle::SCFlags buttonDown;
2866 QTitleBarP::QTitleBarP(QWidget* w, QWidget* parent, const char* name)
2867 : QWidget( parent, name, WStyle_Customize | WStyle_NoBorder | WResizeNoErase | WRepaintNoErase )
2869 d = new QTitleBarPPrivate();
2871 #ifndef QT_NO_TOOLTIP
2872 d->toolTip = new QTitleBarPTip( this );
2875 d->buttonDown = QStyle::SC_None;
2878 setWFlags( ((QTitleBarP*)w)->getWFlags() | WResizeNoErase | WRepaintNoErase );
2879 #ifndef QT_NO_WIDGET_TOPEXTRA
2880 setCaption( w->caption() );
2883 setWFlags( WStyle_Customize | WResizeNoErase | WRepaintNoErase );
2887 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
2888 setMouseTracking(TRUE);
2891 QTitleBarP::~QTitleBarP()
2893 #ifndef QT_NO_TOOLTIP
2902 extern QRgb qt_colorref2qrgb(COLORREF col);
2905 void QTitleBarP::readColors()
2907 QPalette pal = palette();
2909 #ifdef Q_WS_WIN // ask system properties on windows
2910 #ifndef SPI_GETGRADIENTCAPTIONS
2911 #define SPI_GETGRADIENTCAPTIONS 0x1008
2913 #ifndef COLOR_GRADIENTACTIVECAPTION
2914 #define COLOR_GRADIENTACTIVECAPTION 27
2916 #ifndef COLOR_GRADIENTINACTIVECAPTION
2917 #define COLOR_GRADIENTINACTIVECAPTION 28
2919 if ( QApplication::desktopSettingsAware() ) {
2920 pal.setColor( QPalette::Active, QColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)) );
2921 pal.setColor( QPalette::Inactive, QColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)) );
2922 pal.setColor( QPalette::Active, QColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)) );
2923 pal.setColor( QPalette::Inactive, QColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)) );
2924 if ( qt_winver != Qt::WV_95 && qt_winver != WV_NT ) {
2927 SystemParametersInfo( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 );
2929 #if defined(UNICODE)
2930 if ( qt_winver & Qt::WV_NT_based )
2931 SystemParametersInfo( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 );
2934 SystemParametersInfoA( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 );
2937 pal.setColor( QPalette::Active, QColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)) );
2938 pal.setColor( QPalette::Inactive, QColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)) );
2940 pal.setColor( QPalette::Active, QColorGroup::Base, palette().active().highlight() );
2941 pal.setColor( QPalette::Inactive, QColorGroup::Base, palette().inactive().highlight() );
2947 pal.setColor( QPalette::Active, QColorGroup::Highlight, palette().active().highlight() );
2948 pal.setColor( QPalette::Active, QColorGroup::Base, palette().active().highlight() );
2949 pal.setColor( QPalette::Inactive, QColorGroup::Highlight, palette().inactive().dark() );
2950 pal.setColor( QPalette::Inactive, QColorGroup::Base, palette().inactive().dark() );
2951 pal.setColor( QPalette::Inactive, QColorGroup::HighlightedText, palette().inactive().background() );
2955 setActive( d->act );
2958 void QTitleBarP::mousePressEvent( QMouseEvent * e)
2961 if ( e->button() == LeftButton ) {
2963 QStyle::SCFlags ctrl = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
2965 case QStyle::SC_TitleBarSysMenu:
2966 if ( testWFlags( WStyle_SysMenu ) && !testWFlags( WStyle_Tool ) ) {
2967 d->buttonDown = QStyle::SC_None;
2968 static QTime* t = 0;
2969 static QTitleBarP* tc = 0;
2972 if ( tc != this || t->elapsed() > QApplication::doubleClickInterval() ) {
2973 emit showOperationMenu();
2984 case QStyle::SC_TitleBarShadeButton:
2985 case QStyle::SC_TitleBarUnshadeButton:
2986 if ( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) )
2987 d->buttonDown = ctrl;
2990 case QStyle::SC_TitleBarNormalButton:
2991 if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) )
2992 d->buttonDown = ctrl;
2995 case QStyle::SC_TitleBarMinButton:
2996 if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) )
2997 d->buttonDown = ctrl;
3000 case QStyle::SC_TitleBarMaxButton:
3001 if ( testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) )
3002 d->buttonDown = ctrl;
3005 case QStyle::SC_TitleBarCloseButton:
3006 if ( testWFlags( WStyle_SysMenu ) )
3007 d->buttonDown = ctrl;
3010 case QStyle::SC_TitleBarLabel:
3011 d->buttonDown = ctrl;
3012 d->moveOffset = mapToParent( e->pos() );
3024 void QTitleBarP::contextMenuEvent( QContextMenuEvent *e )
3026 QStyle::SCFlags ctrl = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
3027 if( ctrl == QStyle::SC_TitleBarLabel || ctrl == QStyle::SC_TitleBarSysMenu ) {
3028 emit popupOperationMenu(e->globalPos());
3033 void QTitleBarP::mouseReleaseEvent( QMouseEvent * e)
3035 if ( e->button() == LeftButton && d->pressed) {
3036 QStyle::SCFlags ctrl = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
3038 if (ctrl == d->buttonDown) {
3040 case QStyle::SC_TitleBarShadeButton:
3041 case QStyle::SC_TitleBarUnshadeButton:
3042 if( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) )
3046 case QStyle::SC_TitleBarNormalButton:
3047 if( testWFlags( WStyle_MinMax ) && !testWFlags( WStyle_Tool ) )
3051 case QStyle::SC_TitleBarMinButton:
3052 if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) )
3056 case QStyle::SC_TitleBarMaxButton:
3057 if( d->window && testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) ) {
3058 if(d->window->isMaximized())
3065 case QStyle::SC_TitleBarCloseButton:
3066 if( testWFlags( WStyle_SysMenu ) ) {
3067 d->buttonDown = QStyle::SC_None;
3078 d->buttonDown = QStyle::SC_None;
3084 void QTitleBarP::mouseMoveEvent( QMouseEvent * e)
3086 switch (d->buttonDown) {
3087 case QStyle::SC_None:
3091 case QStyle::SC_TitleBarSysMenu:
3093 case QStyle::SC_TitleBarShadeButton:
3094 case QStyle::SC_TitleBarUnshadeButton:
3095 case QStyle::SC_TitleBarNormalButton:
3096 case QStyle::SC_TitleBarMinButton:
3097 case QStyle::SC_TitleBarMaxButton:
3098 case QStyle::SC_TitleBarCloseButton:
3100 QStyle::SCFlags last_ctrl = d->buttonDown;
3101 d->buttonDown = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
3102 if( d->buttonDown != last_ctrl)
3103 d->buttonDown = QStyle::SC_None;
3105 d->buttonDown = last_ctrl;
3109 case QStyle::SC_TitleBarLabel:
3110 if ( d->buttonDown == QStyle::SC_TitleBarLabel && d->movable && d->pressed ) {
3111 if ( (d->moveOffset - mapToParent( e->pos() ) ).manhattanLength() >= 4 ) {
3112 QPoint p = mapFromGlobal(e->globalPos());
3113 #ifndef QT_NO_WORKSPACE
3114 if(d->window && d->window->parentWidget()->inherits("QWorkspacePChild")) {
3115 QWidget *w = d->window->parentWidget()->parentWidget();
3116 if(w && w->inherits("QWorkspaceP")) {
3117 QWorkspaceP *workspace = (QWorkspaceP*)w;
3118 p = workspace->mapFromGlobal( e->globalPos() );
3119 if ( !workspace->rect().contains(p) ) {
3124 if ( p.x() > workspace->width() )
3125 p.rx() = workspace->width();
3126 if ( p.y() > workspace->height() )
3127 p.ry() = workspace->height();
3132 QPoint pp = p - d->moveOffset;
3133 parentWidget()->move( pp );
3136 QStyle::SCFlags last_ctrl = d->buttonDown;
3137 d->buttonDown = QStyle::SC_None;
3138 if( d->buttonDown != last_ctrl)
3145 void QTitleBarP::resizeEvent( QResizeEvent *r)
3147 QWidget::resizeEvent(r);
3151 void QTitleBarP::paintEvent(QPaintEvent *)
3153 QStyle::SCFlags ctrls = QStyle::SC_TitleBarLabel;
3154 if ( testWFlags( WStyle_SysMenu) ) {
3155 if ( testWFlags( WStyle_Tool ) ) {
3156 ctrls |= QStyle::SC_TitleBarCloseButton;
3157 if ( d->window && testWFlags( WStyle_MinMax ) ) {
3158 if ( d->window->isMinimized() )
3159 ctrls |= QStyle::SC_TitleBarUnshadeButton;
3161 ctrls |= QStyle::SC_TitleBarShadeButton;
3164 ctrls |= QStyle::SC_TitleBarSysMenu | QStyle::SC_TitleBarCloseButton;
3165 if ( d->window && testWFlags( WStyle_Minimize ) ) {
3166 if( d->window && d->window->isMinimized() )
3167 ctrls |= QStyle::SC_TitleBarNormalButton;
3169 ctrls |= QStyle::SC_TitleBarMinButton;
3171 if ( d->window && testWFlags( WStyle_Maximize ) && !d->window->isMaximized() )
3172 ctrls |= QStyle::SC_TitleBarMaxButton;
3176 QStyle::SCFlags under_mouse = QStyle::SC_None;
3177 if( autoRaise() && hasMouse() ) {
3178 QPoint p(mapFromGlobal(QCursor::pos()));
3179 under_mouse = style().querySubControl(QStyle::CC_TitleBar, this, p);
3180 ctrls ^= under_mouse;
3183 QSharedDoubleBuffer buffer( (bool)FALSE, (bool)FALSE );
3184 buffer.begin( this, rect() );
3185 style().drawComplexControl(QStyle::CC_TitleBar, buffer.painter(), this, rect(),
3187 isEnabled() ? QStyle::Style_Enabled :
3188 QStyle::Style_Default, ctrls, d->buttonDown);
3189 if(under_mouse != QStyle::SC_None)
3190 style().drawComplexControl(QStyle::CC_TitleBar, buffer.painter(), this, rect(),
3192 QStyle::Style_MouseOver |
3193 (isEnabled() ? QStyle::Style_Enabled : 0),
3194 under_mouse, d->buttonDown);
3197 void QTitleBarP::mouseDoubleClickEvent( QMouseEvent *e )
3199 if ( e->button() != LeftButton )
3202 switch(style().querySubControl(QStyle::CC_TitleBar, this, e->pos())) {
3203 case QStyle::SC_TitleBarLabel:
3204 emit doubleClicked();
3207 case QStyle::SC_TitleBarSysMenu:
3208 if ( testWFlags( WStyle_SysMenu ) )
3217 void QTitleBarP::cutText()
3219 #ifndef QT_NO_WIDGET_TOPEXTRA
3220 QFontMetrics fm( font() );
3222 int maxw = style().querySubControlMetrics(QStyle::CC_TitleBar, this,
3223 QStyle::SC_TitleBarLabel).width();
3225 maxw = width() - 20;
3226 const QString txt = caption();
3228 if ( fm.width( txt + "m" ) > maxw ) {
3229 int i = txt.length();
3230 int dotlength = fm.width( "..." );
3231 while ( i>0 && fm.width(txt.left( i )) + dotlength > maxw )
3233 if(i != (int)txt.length())
3234 d->cuttext = txt.left( i ) + "...";
3239 void QTitleBarP::setCaption( const QString& title )
3241 #ifndef QT_NO_WIDGET_TOPEXTRA
3242 if( caption() == title)
3244 QWidget::setCaption( title );
3252 void QTitleBarP::setIcon( const QPixmap& icon )
3254 #ifndef QT_NO_WIDGET_TOPEXTRA
3255 #ifndef QT_NO_IMAGE_SMOOTHSCALE
3256 QRect menur = style().querySubControlMetrics(QStyle::CC_TitleBar, this,
3257 QStyle::SC_TitleBarSysMenu);
3260 if (icon.width() > menur.width()) {
3261 // try to keep something close to the same aspect
3262 int aspect = (icon.height() * 100) / icon.width();
3263 int newh = (aspect * menur.width()) / 100;
3264 theIcon.convertFromImage( icon.convertToImage().smoothScale(menur.width(),
3266 } else if (icon.height() > menur.height()) {
3267 // try to keep something close to the same aspect
3268 int aspect = (icon.width() * 100) / icon.height();
3269 int neww = (aspect * menur.height()) / 100;
3270 theIcon.convertFromImage( icon.convertToImage().smoothScale(neww,
3275 QWidget::setIcon( theIcon );
3277 QWidget::setIcon( icon );
3284 void QTitleBarP::leaveEvent( QEvent * )
3286 if(autoRaise() && !d->pressed)
3290 void QTitleBarP::enterEvent( QEvent * )
3292 if(autoRaise() && !d->pressed)
3294 QEvent e( QEvent::Leave );
3295 QApplication::sendEvent( parentWidget(), &e );
3298 void QTitleBarP::setActive( bool active )
3300 if ( d->act == active )
3307 bool QTitleBarP::isActive() const
3312 bool QTitleBarP::usesActiveColor() const
3314 return ( isActive() && isActiveWindow() ) ||
3315 ( !window() && topLevelWidget()->isActiveWindow() );
3318 QString QTitleBarP::visibleText() const
3323 QWidget *QTitleBarP::window() const
3328 bool QTitleBarP::event( QEvent* e )
3330 if ( e->type() == QEvent::ApplicationPaletteChange ) {
3333 } else if ( e->type() == QEvent::WindowActivate ) {
3334 setActive( d->act );
3335 } else if ( e->type() == QEvent::WindowDeactivate ) {
3336 bool wasActive = d->act;
3341 return QWidget::event( e );
3344 void QTitleBarP::setMovable(bool b)
3349 bool QTitleBarP::isMovable() const
3354 void QTitleBarP::setAutoRaise(bool b)
3359 bool QTitleBarP::autoRaise() const
3361 return d->autoraise;
3364 QSize QTitleBarP::sizeHint() const
3367 QRect menur = style().querySubControlMetrics(QStyle::CC_TitleBar, this,
3368 QStyle::SC_TitleBarSysMenu);
3369 return QSize( menur.width(), style().pixelMetric( QStyle::PM_TitleBarHeight, this ) );