source: trunk/src/widgets/qmainwindow.cpp

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

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 73.4 KB
Line 
1/****************************************************************************
2** $Id: qmainwindow.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QMainWindow class
5**
6** Created : 980312
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the widgets 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 or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided 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 "qmainwindow.h"
39#ifndef QT_NO_MAINWINDOW
40
41#include "qtimer.h"
42#include "qlayout.h"
43#include "qobjectlist.h"
44#include "qintdict.h"
45#include "qapplication.h"
46#include "qptrlist.h"
47#include "qmap.h"
48#include "qcursor.h"
49#include "qpainter.h"
50#include "qmenubar.h"
51#include "qpopupmenu.h"
52#include "qtoolbar.h"
53#include "qstatusbar.h"
54#include "qscrollview.h"
55#include "qtooltip.h"
56#include "qdatetime.h"
57#include "qwhatsthis.h"
58#include "qbitmap.h"
59#include "qdockarea.h"
60#include "qstringlist.h"
61#include "qstyle.h"
62#ifdef Q_WS_MACX
63# include "qt_mac.h"
64#endif
65
66class QHideDock;
67class QMainWindowLayout;
68
69class QMainWindowPrivate
70{
71public:
72 QMainWindowPrivate()
73 : mb(0), sb(0), ttg(0), mc(0), tll(0), mwl(0), ubp( FALSE ), utl( FALSE ),
74 justify( FALSE ), movable( TRUE ), opaque( FALSE ), dockMenu( TRUE )
75 {
76 docks.insert( Qt::DockTop, TRUE );
77 docks.insert( Qt::DockBottom, TRUE );
78 docks.insert( Qt::DockLeft, TRUE );
79 docks.insert( Qt::DockRight, TRUE );
80 docks.insert( Qt::DockMinimized, FALSE );
81 docks.insert( Qt::DockTornOff, TRUE );
82 }
83
84 ~QMainWindowPrivate()
85 {
86 }
87
88#ifndef QT_NO_MENUBAR
89 QMenuBar * mb;
90#else
91 QWidget * mb;
92#endif
93 QStatusBar * sb;
94 QToolTipGroup * ttg;
95
96 QWidget * mc;
97
98 QBoxLayout * tll;
99 QMainWindowLayout * mwl;
100
101 uint ubp :1;
102 uint utl :1;
103 uint justify :1;
104 uint movable :1;
105 uint opaque :1;
106 uint dockMenu :1;
107
108 QDockArea *topDock, *bottomDock, *leftDock, *rightDock;
109
110 QPtrList<QDockWindow> dockWindows;
111 QMap<Qt::Dock, bool> docks;
112 QStringList disabledDocks;
113 QHideDock *hideDock;
114
115 QGuardedPtr<QPopupMenu> rmbMenu, tbMenu, dwMenu;
116 QMap<QDockWindow*, bool> appropriate;
117 QMap<QPopupMenu*, QMainWindow::DockWindows> dockWindowModes;
118
119};
120
121
122/* QMainWindowLayout, respects widthForHeight layouts (like the left
123 and right docks are)
124*/
125
126class QMainWindowLayout : public QLayout
127{
128 Q_OBJECT
129
130public:
131 QMainWindowLayout( QMainWindow *mw, QLayout* parent = 0 );
132 ~QMainWindowLayout() {}
133
134 void addItem( QLayoutItem * );
135 void setLeftDock( QDockArea *l );
136 void setRightDock( QDockArea *r );
137 void setCentralWidget( QWidget *w );
138 bool hasHeightForWidth() const { return FALSE; }
139 QSize sizeHint() const;
140 QSize minimumSize() const;
141 QLayoutIterator iterator();
142 QSizePolicy::ExpandData expanding() const { return QSizePolicy::BothDirections; }
143 void invalidate() {}
144
145protected:
146 void setGeometry( const QRect &r ) {
147 QLayout::setGeometry( r );
148 layoutItems( r );
149 }
150
151private:
152 int layoutItems( const QRect&, bool testonly = FALSE );
153 int extraPixels() const;
154
155 QDockArea *left, *right;
156 QWidget *central;
157 QMainWindow *mainWindow;
158
159};
160
161QSize QMainWindowLayout::sizeHint() const
162{
163 int w = 0;
164 int h = 0;
165
166 if ( left ) {
167 w += left->sizeHint().width();
168 h = QMAX( h, left->sizeHint().height() );
169 }
170 if ( right ) {
171 w += right->sizeHint().width();
172 h = QMAX( h, right->sizeHint().height() );
173 }
174 if ( central ) {
175 w += central->sizeHint().width();
176 int diff = extraPixels();
177 h = QMAX( h, central->sizeHint().height() + diff );
178 }
179 return QSize( w, h );
180}
181
182QSize QMainWindowLayout::minimumSize() const
183{
184 int w = 0;
185 int h = 0;
186
187 if ( left ) {
188 QSize ms = left->minimumSizeHint().expandedTo( left->minimumSize() );
189 w += ms.width();
190 h = QMAX( h, ms.height() );
191 }
192 if ( right ) {
193 QSize ms = right->minimumSizeHint().expandedTo( right->minimumSize() );
194 w += ms.width();
195 h = QMAX( h, ms.height() );
196 }
197 if ( central ) {
198 QSize min = central->minimumSize().isNull() ?
199 central->minimumSizeHint() : central->minimumSize();
200 w += min.width();
201 int diff = extraPixels();
202 h = QMAX( h, min.height() + diff );
203 }
204 return QSize( w, h );
205}
206
207QMainWindowLayout::QMainWindowLayout( QMainWindow *mw, QLayout* parent )
208 : QLayout( parent ), left( 0 ), right( 0 ), central( 0 )
209{
210 mainWindow = mw;
211}
212
213void QMainWindowLayout::setLeftDock( QDockArea *l )
214{
215 left = l;
216}
217
218void QMainWindowLayout::setRightDock( QDockArea *r )
219{
220 right = r;
221}
222
223void QMainWindowLayout::setCentralWidget( QWidget *w )
224{
225 central = w;
226}
227
228int QMainWindowLayout::layoutItems( const QRect &r, bool testonly )
229{
230 if ( !left && !central && !right )
231 return 0;
232
233 int wl = 0, wr = 0;
234 if ( left )
235 wl = ( (QDockAreaLayout*)left->QWidget::layout() )->widthForHeight( r.height() );
236 if ( right )
237 wr = ( (QDockAreaLayout*)right->QWidget::layout() )->widthForHeight( r.height() );
238 int w = r.width() - wr - wl;
239 if ( w < 0 )
240 w = 0;
241
242 int diff = extraPixels();
243 if ( !testonly ) {
244 QRect g( geometry() );
245 if ( left )
246 left->setGeometry( QRect( g.x(), g.y() + diff, wl, r.height() - diff ) );
247 if ( right )
248 right->setGeometry( QRect( g.x() + g.width() - wr, g.y() + diff, wr, r.height() - diff ) );
249 if ( central )
250 central->setGeometry( g.x() + wl, g.y() + diff, w, r.height() - diff );
251 }
252
253 w = wl + wr;
254 if ( central )
255 w += central->minimumSize().width();
256 return w;
257}
258
259int QMainWindowLayout::extraPixels() const
260{
261 if ( mainWindow->d->topDock->isEmpty() &&
262 !(mainWindow->d->leftDock->isEmpty() &&
263 mainWindow->d->rightDock->isEmpty()) ) {
264 return 2;
265 } else {
266 return 0;
267 }
268}
269
270void QMainWindowLayout::addItem( QLayoutItem * /* item */ )
271{
272}
273
274
275QLayoutIterator QMainWindowLayout::iterator()
276{
277 return 0;
278}
279
280
281/*
282 QHideToolTip and QHideDock - minimized dock
283*/
284
285#ifndef QT_NO_TOOLTIP
286class QHideToolTip : public QToolTip
287{
288public:
289 QHideToolTip( QWidget *parent ) : QToolTip( parent ) {}
290
291 void maybeTip( const QPoint &pos );
292};
293#endif
294
295
296class QHideDock : public QWidget
297{
298 Q_OBJECT
299
300public:
301 QHideDock( QMainWindow *parent ) : QWidget( parent, "qt_hide_dock" ) {
302 hide();
303 setFixedHeight( style().pixelMetric( QStyle::PM_DockWindowHandleExtent,
304 this ) + 3 );
305 pressedHandle = -1;
306 pressed = FALSE;
307 setMouseTracking( TRUE );
308 win = parent;
309#ifndef QT_NO_TOOLTIP
310 tip = new QHideToolTip( this );
311#endif
312 }
313 ~QHideDock()
314 {
315#ifndef QT_NO_TOOLTIP
316 delete tip;
317#endif
318 }
319
320protected:
321 void paintEvent( QPaintEvent *e ) {
322 if ( !children() || children()->isEmpty() )
323 return;
324 QPainter p( this );
325 p.setClipRegion( e->rect() );
326 p.fillRect( e->rect(), colorGroup().brush( QColorGroup::Background ) );
327 int x = 0;
328 int i = -1;
329 QObjectListIt it( *children() );
330 QObject *o;
331 while ( ( o = it.current() ) ) {
332 ++it;
333 ++i;
334 QDockWindow *dw = ::qt_cast<QDockWindow*>(o);
335 if ( !dw || !dw->isVisible() )
336 continue;
337
338 QStyle::SFlags flags = QStyle::Style_Default;
339 if ( i == pressedHandle )
340 flags |= QStyle::Style_On;
341
342 style().drawPrimitive( QStyle::PE_DockWindowHandle, &p,
343 QRect( x, 0, 30, 10 ), colorGroup(),
344 flags );
345 x += 30;
346 }
347 }
348
349 void mousePressEvent( QMouseEvent *e ) {
350 pressed = TRUE;
351 if ( !children() || children()->isEmpty() )
352 return;
353 mouseMoveEvent( e );
354 pressedHandle = -1;
355
356 if ( e->button() == RightButton && win->isDockMenuEnabled() ) {
357 // ### TODO: HideDock menu
358 } else {
359 mouseMoveEvent( e );
360 }
361 }
362
363 void mouseMoveEvent( QMouseEvent *e ) {
364 if ( !children() || children()->isEmpty() )
365 return;
366 if ( !pressed )
367 return;
368 int x = 0;
369 int i = -1;
370 if ( e->y() >= 0 && e->y() <= height() ) {
371 QObjectListIt it( *children() );
372 QObject *o;
373 while ( ( o = it.current() ) ) {
374 ++it;
375 ++i;
376 QDockWindow *dw = ::qt_cast<QDockWindow*>(o);
377 if ( !dw || !dw->isVisible() )
378 continue;
379
380 if ( e->x() >= x && e->x() <= x + 30 ) {
381 int old = pressedHandle;
382 pressedHandle = i;
383 if ( pressedHandle != old )
384 repaint( TRUE );
385 return;
386 }
387 x += 30;
388 }
389 }
390 int old = pressedHandle;
391 pressedHandle = -1;
392 if ( old != -1 )
393 repaint( TRUE );
394 }
395
396 void mouseReleaseEvent( QMouseEvent *e ) {
397 pressed = FALSE;
398 if ( pressedHandle == -1 )
399 return;
400 if ( !children() || children()->isEmpty() )
401 return;
402 if ( e->button() == LeftButton ) {
403 if ( e->y() >= 0 && e->y() <= height() ) {
404 QObject *o = ( (QObjectList*)children() )->at( pressedHandle );
405 QDockWindow *dw = ::qt_cast<QDockWindow*>(o);
406 if ( dw ) {
407 dw->show();
408 dw->dock();
409 }
410 }
411 }
412 pressedHandle = -1;
413 repaint( FALSE );
414 }
415
416 bool eventFilter( QObject *o, QEvent *e ) {
417 if ( o == this || !o->isWidgetType() )
418 return QWidget::eventFilter( o, e );
419 if ( e->type() == QEvent::Hide ||
420 e->type() == QEvent::Show ||
421 e->type() == QEvent::ShowToParent )
422 updateState();
423 return QWidget::eventFilter( o, e );
424 }
425
426 void updateState() {
427 bool visible = TRUE;
428 if ( !children() || children()->isEmpty() ) {
429 visible = FALSE;
430 } else {
431 QObjectListIt it( *children() );
432 QObject *o;
433 while ( ( o = it.current() ) ) {
434 ++it;
435 QDockWindow *dw = ::qt_cast<QDockWindow*>(o);
436 if ( !dw )
437 continue;
438 if ( dw->isHidden() ) {
439 visible = FALSE;
440 continue;
441 }
442 if ( !dw->isVisible() )
443 continue;
444 visible = TRUE;
445 break;
446 }
447 }
448
449 if ( visible )
450 show();
451 else
452 hide();
453 win->triggerLayout( FALSE );
454 update();
455 }
456
457 void childEvent( QChildEvent *e ) {
458 QWidget::childEvent( e );
459 if ( e->type() == QEvent::ChildInserted )
460 e->child()->installEventFilter( this );
461 else
462 e->child()->removeEventFilter( this );
463 updateState();
464 }
465
466private:
467 QMainWindow *win;
468 int pressedHandle;
469 bool pressed;
470#ifndef QT_NO_TOOLTIP
471 QHideToolTip *tip;
472 friend class QHideToolTip;
473#endif
474};
475
476#ifndef QT_NO_TOOLTIP
477void QHideToolTip::maybeTip( const QPoint &pos )
478{
479 if ( !parentWidget() )
480 return;
481 QHideDock *dock = (QHideDock*)parentWidget();
482
483 if ( !dock->children() || dock->children()->isEmpty() )
484 return;
485 QObjectListIt it( *dock->children() );
486 QObject *o;
487 int x = 0;
488 while ( ( o = it.current() ) ) {
489 ++it;
490 QDockWindow *dw = ::qt_cast<QDockWindow*>(o);
491 if ( !dw || !dw->isVisible() )
492 continue;
493
494 if ( pos.x() >= x && pos.x() <= x + 30 ) {
495 QDockWindow *dw = (QDockWindow*)o;
496 if ( !dw->caption().isEmpty() )
497 tip( QRect( x, 0, 30, dock->height() ), dw->caption() );
498 return;
499 }
500 x += 30;
501 }
502}
503#endif
504
505/*!
506 \class QMainWindow qmainwindow.h
507 \brief The QMainWindow class provides a main application window,
508 with a menu bar, dock windows (e.g. for toolbars), and a status
509 bar.
510
511 \ingroup application
512 \mainclass
513
514 Main windows are most often used to provide menus, toolbars and a
515 status bar around a large central widget, such as a text edit,
516 drawing canvas or QWorkspace (for MDI applications). QMainWindow
517 is usually subclassed since this makes it easier to encapsulate
518 the central widget, menus and toolbars as well as the window's
519 state. Subclassing makes it possible to create the slots that are
520 called when the user clicks menu items or toolbar buttons. You can
521 also create main windows using \link designer-manual.book Qt
522 Designer\endlink. We'll briefly review adding menu items and
523 toolbar buttons then describe the facilities of QMainWindow
524 itself.
525
526 \code
527 QMainWindow *mw = new QMainWindow;
528 QTextEdit *edit = new QTextEdit( mw, "editor" );
529 edit->setFocus();
530 mw->setCaption( "Main Window" );
531 mw->setCentralWidget( edit );
532 mw->show();
533 \endcode
534
535 QMainWindows may be created in their own right as shown above.
536 The central widget is set with setCentralWidget(). Popup menus can
537 be added to the default menu bar, widgets can be added to the
538 status bar, toolbars and dock windows can be added to any of the
539 dock areas.
540
541 \quotefile application/main.cpp
542 \skipto ApplicationWindow
543 \printuntil show
544
545 In the extract above ApplicationWindow is a subclass of
546 QMainWindow that we must write for ourselves; this is the usual
547 approach to using QMainWindow. (The source for the extracts in
548 this description are taken from \l application/main.cpp, \l
549 application/application.cpp, \l action/main.cpp, and \l
550 action/application.cpp )
551
552 When subclassing we add the menu items and toolbars in the
553 subclass's constructor. If we've created a QMainWindow instance
554 directly we can add menu items and toolbars just as easily by
555 passing the QMainWindow instance as the parent instead of the \e
556 this pointer.
557
558 \quotefile application/application.cpp
559 \skipto help = new
560 \printuntil about
561
562 Here we've added a new menu with one menu item. The menu has been
563 inserted into the menu bar that QMainWindow provides by default
564 and which is accessible through the menuBar() function. The slot
565 will be called when the menu item is clicked.
566
567 \quotefile application/application.cpp
568 \skipto fileTools
569 \printuntil setLabel
570 \skipto QToolButton
571 \printuntil open file
572
573 This extract shows the creation of a toolbar with one toolbar
574 button. QMainWindow supplies four dock areas for toolbars. When a
575 toolbar is created as a child of a QMainWindow (or derived class)
576 instance it will be placed in a dock area (the \c Top dock area by
577 default). The slot will be called when the toolbar button is
578 clicked. Any dock window can be added to a dock area either using
579 addDockWindow(), or by creating a dock window with the QMainWindow
580 as the parent.
581
582 \quotefile application/application.cpp
583 \skipto editor
584 \printuntil statusBar
585
586 Having created the menus and toolbar we create an instance of the
587 large central widget, give it the focus and set it as the main
588 window's central widget. In the example we've also set the status
589 bar, accessed via the statusBar() function, to an initial message
590 which will be displayed for two seconds. Note that you can add
591 additional widgets to the status bar, for example labels, to show
592 further status information. See the QStatusBar documentation for
593 details, particularly the addWidget() function.
594
595 Often we want to synchronize a toolbar button with a menu item.
596 For example, if the user clicks a 'bold' toolbar button we want
597 the 'bold' menu item to be checked. This synchronization can be
598 achieved automatically by creating actions and adding the actions
599 to the toolbar and menu.
600
601 \quotefile action/application.cpp
602 \skipto QAction * fileOpen
603 \printline
604 \skipto fileOpenAction
605 \printuntil choose
606
607 Here we create an action with an icon which will be used in any
608 menu and toolbar that the action is added to. We've also given the
609 action a menu name, '\&Open', and a keyboard shortcut. The
610 connection that we have made will be used when the user clicks
611 either the menu item \e or the toolbar button.
612
613 \quotefile action/application.cpp
614 \skipto QPopupMenu * file
615 \printuntil menuBar
616 \skipto fileOpen
617 \printline
618
619 The extract above shows the creation of a popup menu. We add the
620 menu to the QMainWindow's menu bar and add our action.
621
622 \quotefile action/application.cpp
623 \skipto QToolBar * fileTool
624 \printuntil OpenAction
625
626 Here we create a new toolbar as a child of the QMainWindow and add
627 our action to the toolbar.
628
629 We'll now explore the functionality offered by QMainWindow.
630
631 The main window will take care of the dock areas, and the geometry
632 of the central widget, but all other aspects of the central widget
633 are left to you. QMainWindow automatically detects the creation of
634 a menu bar or status bar if you specify the QMainWindow as parent,
635 or you can use the provided menuBar() and statusBar() functions.
636 The functions menuBar() and statusBar() create a suitable widget
637 if one doesn't exist, and update the window's layout to make
638 space.
639
640 QMainWindow provides a QToolTipGroup connected to the status bar.
641 The function toolTipGroup() provides access to the default
642 QToolTipGroup. It isn't possible to set a different tool tip
643 group.
644
645 New dock windows and toolbars can be added to a QMainWindow using
646 addDockWindow(). Dock windows can be moved using moveDockWindow()
647 and removed with removeDockWindow(). QMainWindow allows default
648 dock window (toolbar) docking in all its dock areas (\c Top, \c
649 Left, \c Right, \c Bottom). You can use setDockEnabled() to
650 enable and disable docking areas for dock windows. When adding or
651 moving dock windows you can specify their 'edge' (dock area). The
652 currently available edges are: \c Top, \c Left, \c Right, \c
653 Bottom, \c Minimized (effectively a 'hidden' dock area) and \c
654 TornOff (floating). See \l Qt::Dock for an explanation of these
655 areas. Note that the *ToolBar functions are included for backward
656 compatibility; all new code should use the *DockWindow functions.
657 QToolbar is a subclass of QDockWindow so all functions that work
658 with dock windows work on toolbars in the same way.
659
660 \target dwm
661 If the user clicks the close button, then the dock window is
662 hidden. A dock window can be hidden or unhidden by the user by
663 right clicking a dock area and clicking the name of the relevant
664 dock window on the pop up dock window menu. This menu lists the
665 names of every dock window; visible dock windows have a tick
666 beside their names. The dock window menu is created automatically
667 as required by createDockWindowMenu(). Since it may not always be
668 appropriate for a dock window to appear on this menu the
669 setAppropriate() function is used to inform the main window
670 whether or not the dock window menu should include a particular
671 dock window. Double clicking a dock window handle (usually on the
672 left-hand side of the dock window) undocks (floats) the dock
673 window. Double clicking a floating dock window's titlebar will
674 dock the floating dock window. (See also
675 \l{QMainWindow::DockWindows}.)
676
677 Some functions change the appearance of a QMainWindow globally:
678 \list
679 \i QDockWindow::setHorizontalStretchable() and
680 QDockWindow::setVerticalStretchable() are used to make specific dock
681 windows or toolbars stretchable.
682 \i setUsesBigPixmaps() is used to set whether tool buttons should
683 draw small or large pixmaps (see QIconSet for more information).
684 \i setUsesTextLabel() is used to set whether tool buttons
685 should display a textual label in addition to pixmaps
686 (see QToolButton for more information).
687 \endlist
688
689 The user can drag dock windows into any enabled docking area. Dock
690 windows can also be dragged \e within a docking area, for example
691 to rearrange the order of some toolbars. Dock windows can also be
692 dragged outside any docking area (undocked or 'floated'). Being
693 able to drag dock windows can be enabled (the default) and
694 disabled using setDockWindowsMovable().
695
696 The \c Minimized edge is a hidden dock area. If this dock area is
697 enabled the user can hide (minimize) a dock window or show (restore)
698 a minimized dock window by clicking the dock window handle. If the
699 user hovers the mouse cursor over one of the handles, the caption of
700 the dock window is displayed in a tool tip (see
701 QDockWindow::caption() or QToolBar::label()), so if you enable the
702 \c Minimized dock area, it is best to specify a meaningful caption
703 or label for each dock window. To minimize a dock window
704 programmatically use moveDockWindow() with an edge of \c Minimized.
705
706 Dock windows are moved transparently by default, i.e. during the
707 drag an outline rectangle is drawn on the screen representing the
708 position of the dock window as it moves. If you want the dock
709 window to be shown normally whilst it is moved use
710 setOpaqueMoving().
711
712 The location of a dock window, i.e. its dock area and position
713 within the dock area, can be determined by calling getLocation().
714 Movable dock windows can be lined up to minimize wasted space with
715 lineUpDockWindows(). Pointers to the dock areas are available from
716 topDock(), leftDock(), rightDock() and bottomDock(). A customize
717 menu item is added to the pop up dock window menu if
718 isCustomizable() returns TRUE; it returns FALSE by default.
719 Reimplement isCustomizable() and customize() if you want to offer
720 this extra menu item, for example, to allow the user to change
721 settings relating to the main window and its toolbars and dock
722 windows.
723
724 The main window's menu bar is fixed (at the top) by default. If
725 you want a movable menu bar, create a QMenuBar as a stretchable
726 widget inside its own movable dock window and restrict this dock
727 window to only live within the \c Top or \c Bottom dock:
728
729 \code
730 QToolBar *tb = new QToolBar( this );
731 addDockWindow( tb, tr( "Menubar" ), Top, FALSE );
732 QMenuBar *mb = new QMenuBar( tb );
733 mb->setFrameStyle( QFrame::NoFrame );
734 tb->setStretchableWidget( mb );
735 setDockEnabled( tb, Left, FALSE );
736 setDockEnabled( tb, Right, FALSE );
737 \endcode
738
739 An application with multiple dock windows can choose to save the
740 current dock window layout in order to restore it later, e.g. in
741 the next session. You can do this by using the streaming operators
742 for QMainWindow.
743
744 To save the layout and positions of all the dock windows do this:
745
746 \code
747 QFile file( filename );
748 if ( file.open( IO_WriteOnly ) ) {
749 QTextStream stream( &file );
750 stream << *mainWindow;
751 file.close();
752 }
753 \endcode
754
755 To restore the dock window positions and sizes (normally when the
756 application is next started), do following:
757
758 \code
759 QFile file( filename );
760 if ( file.open( IO_ReadOnly ) ) {
761 QTextStream stream( &file );
762 stream >> *mainWindow;
763 file.close();
764 }
765 \endcode
766
767 The QSettings class can be used in conjunction with the streaming
768 operators to store the application's settings.
769
770 QMainWindow's management of dock windows and toolbars is done
771 transparently behind-the-scenes by QDockArea.
772
773 For multi-document interfaces (MDI), use a QWorkspace as the
774 central widget.
775
776 Adding dock windows, e.g. toolbars, to QMainWindow's dock areas is
777 straightforward. If the supplied dock areas are not sufficient for
778 your application we suggest that you create a QWidget subclass and
779 add your own dock areas (see \l QDockArea) to the subclass since
780 QMainWindow provides functionality specific to the standard dock
781 areas it provides.
782
783 <img src=qmainwindow-m.png> <img src=qmainwindow-w.png>
784
785 \sa QToolBar QDockWindow QStatusBar QAction QMenuBar QPopupMenu QToolTipGroup QDialog
786*/
787
788/*! \enum Qt::ToolBarDock
789 \internal
790*/
791
792/*!
793 \enum Qt::Dock
794
795 Each dock window can be in one of the following positions:
796
797 \value DockTop above the central widget, below the menu bar.
798
799 \value DockBottom below the central widget, above the status bar.
800
801 \value DockLeft to the left of the central widget.
802
803 \value DockRight to the right of the central widget.
804
805 \value DockMinimized the dock window is not shown (this is
806 effectively a 'hidden' dock area); the handles of all minimized
807 dock windows are drawn in one row below the menu bar.
808
809 \value DockTornOff the dock window floats as its own top level
810 window which always stays on top of the main window.
811
812 \value DockUnmanaged not managed by a QMainWindow.
813*/
814
815/*!
816 \enum QMainWindow::DockWindows
817
818 Right-clicking a dock area will pop-up the dock window menu
819 (createDockWindowMenu() is called automatically). When called in
820 code you can specify what items should appear on the menu with
821 this enum.
822
823 \value OnlyToolBars The menu will list all the toolbars, but not
824 any other dock windows.
825
826 \value NoToolBars The menu will list dock windows but not
827 toolbars.
828
829 \value AllDockWindows The menu will list all toolbars and other
830 dock windows. (This is the default.)
831*/
832
833/*!
834 \obsolete
835 \fn void QMainWindow::addToolBar( QDockWindow *, Dock = Top, bool newLine = FALSE );
836*/
837
838/*!
839 \obsolete
840 \overload void QMainWindow::addToolBar( QDockWindow *, const QString &label, Dock = Top, bool newLine = FALSE );
841*/
842
843/*!
844 \obsolete
845 \fn void QMainWindow::moveToolBar( QDockWindow *, Dock = Top );
846*/
847
848/*!
849 \obsolete
850 \overload void QMainWindow::moveToolBar( QDockWindow *, Dock, bool nl, int index, int extraOffset = -1 );
851*/
852
853/*!
854 \obsolete
855 \fn void QMainWindow::removeToolBar( QDockWindow * );
856*/
857
858/*!
859 \obsolete
860 \fn void QMainWindow::lineUpToolBars( bool keepNewLines = FALSE );
861*/
862
863/*!
864 \obsolete
865 \fn void QMainWindow::toolBarPositionChanged( QToolBar * );
866*/
867
868/*!
869 \obsolete
870 \fn bool QMainWindow::toolBarsMovable() const
871*/
872
873/*!
874 \obsolete
875 \fn void QMainWindow::setToolBarsMovable( bool )
876*/
877
878/*!
879 Constructs an empty main window. The \a parent, \a name and widget
880 flags \a f, are passed on to the QWidget constructor.
881
882 By default, the widget flags are set to \c WType_TopLevel rather
883 than 0 as they are with QWidget. If you don't want your
884 QMainWindow to be a top level widget then you will need to set \a
885 f to 0.
886*/
887
888QMainWindow::QMainWindow( QWidget * parent, const char * name, WFlags f )
889 : QWidget( parent, name, f )
890{
891 d = new QMainWindowPrivate;
892#ifdef Q_WS_MACX
893 d->opaque = TRUE;
894#else
895 d->opaque = FALSE;
896#endif
897 installEventFilter( this );
898 d->topDock = new QDockArea( Horizontal, QDockArea::Normal, this, "qt_top_dock" );
899 d->topDock->installEventFilter( this );
900 d->bottomDock = new QDockArea( Horizontal, QDockArea::Reverse, this, "qt_bottom_dock" );
901 d->bottomDock->installEventFilter( this );
902 d->leftDock = new QDockArea( Vertical, QDockArea::Normal, this, "qt_left_dock" );
903 d->leftDock->installEventFilter( this );
904 d->rightDock = new QDockArea( Vertical, QDockArea::Reverse, this, "qt_right_dock" );
905 d->rightDock->installEventFilter( this );
906 d->hideDock = new QHideDock( this );
907}
908
909
910/*!
911 Destroys the object and frees any allocated resources.
912*/
913
914QMainWindow::~QMainWindow()
915{
916 delete layout();
917 delete d;
918}
919
920#ifndef QT_NO_MENUBAR
921/*!
922 Sets this main window to use the menu bar \a newMenuBar.
923
924 The existing menu bar (if any) is deleted along with its contents.
925
926 \sa menuBar()
927*/
928
929void QMainWindow::setMenuBar( QMenuBar * newMenuBar )
930{
931 if ( !newMenuBar )
932 return;
933 if ( d->mb )
934 delete d->mb;
935 d->mb = newMenuBar;
936 d->mb->installEventFilter( this );
937 triggerLayout();
938}
939
940
941/*!
942 Returns the menu bar for this window.
943
944 If there isn't one, then menuBar() creates an empty menu bar.
945
946 \sa statusBar()
947*/
948
949QMenuBar * QMainWindow::menuBar() const
950{
951 if ( d->mb )
952 return d->mb;
953
954 QObjectList * l
955 = ((QObject*)this)->queryList( "QMenuBar", 0, FALSE, FALSE );
956 QMenuBar * b;
957 if ( l && l->count() ) {
958 b = (QMenuBar *)l->first();
959 } else {
960 b = new QMenuBar( (QMainWindow *)this, "automatic menu bar" );
961 b->show();
962 }
963 delete l;
964 d->mb = b;
965 d->mb->installEventFilter( this );
966 ((QMainWindow *)this)->triggerLayout();
967 return b;
968}
969#endif // QT_NO_MENUBAR
970
971/*!
972 Sets this main window to use the status bar \a newStatusBar.
973
974 The existing status bar (if any) is deleted along with its
975 contents.
976
977 Note that \a newStatusBar \e must be a child of this main window,
978 and that it is not automatically displayed. If you call this
979 function after show(), you will probably also need to call
980 newStatusBar->show().
981
982 \sa setMenuBar() statusBar()
983*/
984
985void QMainWindow::setStatusBar( QStatusBar * newStatusBar )
986{
987 if ( !newStatusBar || newStatusBar == d->sb )
988 return;
989 if ( d->sb )
990 delete d->sb;
991 d->sb = newStatusBar;
992#ifndef QT_NO_TOOLTIP
993 // ### this code can cause unnecessary creation of a tool tip group
994 connect( toolTipGroup(), SIGNAL(showTip(const QString&)),
995 d->sb, SLOT(message(const QString&)) );
996 connect( toolTipGroup(), SIGNAL(removeTip()),
997 d->sb, SLOT(clear()) );
998#endif
999 d->sb->installEventFilter( this );
1000 triggerLayout();
1001}
1002
1003
1004/*!
1005 Returns this main window's status bar. If there isn't one,
1006 statusBar() creates an empty status bar, and if necessary a tool
1007 tip group too.
1008
1009 \sa menuBar() toolTipGroup()
1010*/
1011
1012QStatusBar * QMainWindow::statusBar() const
1013{
1014 if ( d->sb )
1015 return d->sb;
1016
1017 QObjectList * l
1018 = ((QObject*)this)->queryList( "QStatusBar", 0, FALSE, FALSE );
1019 QStatusBar * s;
1020 if ( l && l->count() ) {
1021 s = (QStatusBar *)l->first();
1022 } else {
1023 s = new QStatusBar( (QMainWindow *)this, "automatic status bar" );
1024 s->show();
1025 }
1026 delete l;
1027 ((QMainWindow *)this)->setStatusBar( s );
1028 ((QMainWindow *)this)->triggerLayout( TRUE );
1029 return s;
1030}
1031
1032
1033#ifndef QT_NO_TOOLTIP
1034/*!
1035 Sets this main window to use the tool tip group \a
1036 newToolTipGroup.
1037
1038 The existing tool tip group (if any) is deleted along with its
1039 contents. All the tool tips connected to it lose the ability to
1040 display the group texts.
1041
1042 \sa menuBar() toolTipGroup()
1043*/
1044
1045void QMainWindow::setToolTipGroup( QToolTipGroup * newToolTipGroup )
1046{
1047 if ( !newToolTipGroup || newToolTipGroup == d->ttg )
1048 return;
1049 if ( d->ttg )
1050 delete d->ttg;
1051 d->ttg = newToolTipGroup;
1052
1053 connect( toolTipGroup(), SIGNAL(showTip(const QString&)),
1054 statusBar(), SLOT(message(const QString&)) );
1055 connect( toolTipGroup(), SIGNAL(removeTip()),
1056 statusBar(), SLOT(clear()) );
1057}
1058
1059
1060/*!
1061 Returns this main window's tool tip group. If there isn't one,
1062 toolTipGroup() creates an empty tool tip group.
1063
1064 \sa menuBar() statusBar()
1065*/
1066
1067QToolTipGroup * QMainWindow::toolTipGroup() const
1068{
1069 if ( d->ttg )
1070 return d->ttg;
1071
1072 QToolTipGroup * t = new QToolTipGroup( (QMainWindow*)this,
1073 "automatic tool tip group" );
1074 ((QMainWindowPrivate*)d)->ttg = t;
1075 return t;
1076}
1077#endif
1078
1079
1080/*!
1081 If \a enable is TRUE then users can dock windows in the \a dock
1082 area. If \a enable is FALSE users cannot dock windows in the \a
1083 dock dock area.
1084
1085 Users can dock (drag) dock windows into any enabled dock area.
1086*/
1087
1088void QMainWindow::setDockEnabled( Dock dock, bool enable )
1089{
1090 d->docks.replace( dock, enable );
1091}
1092
1093
1094/*!
1095 Returns TRUE if the \a dock dock area is enabled, i.e. it can
1096 accept user dragged dock windows; otherwise returns FALSE.
1097
1098 \sa setDockEnabled()
1099*/
1100
1101bool QMainWindow::isDockEnabled( Dock dock ) const
1102{
1103 return d->docks[ dock ];
1104}
1105
1106/*!
1107 \overload
1108
1109 Returns TRUE if dock area \a area is enabled, i.e. it can accept
1110 user dragged dock windows; otherwise returns FALSE.
1111
1112 \sa setDockEnabled()
1113*/
1114
1115bool QMainWindow::isDockEnabled( QDockArea *area ) const
1116{
1117
1118 if ( area == d->leftDock )
1119 return d->docks[ DockLeft ];
1120 if ( area == d->rightDock )
1121 return d->docks[ DockRight ];
1122 if ( area == d->topDock )
1123 return d->docks[ DockTop ];
1124 if ( area == d->bottomDock )
1125 return d->docks[ DockBottom ];
1126 return FALSE;
1127}
1128
1129/*!
1130 \overload
1131
1132 If \a enable is TRUE then users can dock the \a dw dock window in
1133 the \a dock area. If \a enable is FALSE users cannot dock the \a
1134 dw dock window in the \a dock area.
1135
1136 In general users can dock (drag) dock windows into any enabled
1137 dock area. Using this function particular dock areas can be
1138 enabled (or disabled) as docking points for particular dock
1139 windows.
1140*/
1141
1142
1143void QMainWindow::setDockEnabled( QDockWindow *dw, Dock dock, bool enable )
1144{
1145 if ( d->dockWindows.find( dw ) == -1 ) {
1146 d->dockWindows.append( dw );
1147 connect( dw, SIGNAL( placeChanged(QDockWindow::Place) ),
1148 this, SLOT( slotPlaceChanged() ) );
1149 }
1150 QString s;
1151 s.sprintf( "%p_%d", (void*)dw, (int)dock );
1152 if ( enable )
1153 d->disabledDocks.remove( s );
1154 else if ( d->disabledDocks.find( s ) == d->disabledDocks.end() )
1155 d->disabledDocks << s;
1156 switch ( dock ) {
1157 case DockTop:
1158 topDock()->setAcceptDockWindow( dw, enable );
1159 break;
1160 case DockLeft:
1161 leftDock()->setAcceptDockWindow( dw, enable );
1162 break;
1163 case DockRight:
1164 rightDock()->setAcceptDockWindow( dw, enable );
1165 break;
1166 case DockBottom:
1167 bottomDock()->setAcceptDockWindow( dw, enable );
1168 break;
1169 default:
1170 break;
1171 }
1172}
1173
1174/*!
1175 \overload
1176
1177 Returns TRUE if dock area \a area is enabled for the dock window
1178 \a dw; otherwise returns FALSE.
1179
1180 \sa setDockEnabled()
1181*/
1182
1183bool QMainWindow::isDockEnabled( QDockWindow *dw, QDockArea *area ) const
1184{
1185 if ( !isDockEnabled( area ) )
1186 return FALSE;
1187 Dock dock;
1188 if ( area == d->leftDock )
1189 dock = DockLeft;
1190 else if ( area == d->rightDock )
1191 dock = DockRight;
1192 else if ( area == d->topDock )
1193 dock = DockTop;
1194 else if ( area == d->bottomDock )
1195 dock = DockBottom;
1196 else
1197 return FALSE;
1198 return isDockEnabled( dw, dock );
1199}
1200
1201/*!
1202 \overload
1203
1204 Returns TRUE if dock area \a dock is enabled for the dock window
1205 \a tb; otherwise returns FALSE.
1206
1207 \sa setDockEnabled()
1208*/
1209
1210bool QMainWindow::isDockEnabled( QDockWindow *tb, Dock dock ) const
1211{
1212 if ( !isDockEnabled( dock ) )
1213 return FALSE;
1214 QString s;
1215 s.sprintf( "%p_%d", (void*)tb, (int)dock );
1216 return d->disabledDocks.find( s ) == d->disabledDocks.end();
1217}
1218
1219
1220
1221/*!
1222 Adds \a dockWindow to the \a edge dock area.
1223
1224 If \a newLine is FALSE (the default) then the \a dockWindow is
1225 added at the end of the \a edge. For vertical edges the end is at
1226 the bottom, for horizontal edges (including \c Minimized) the end
1227 is at the right. If \a newLine is TRUE a new line of dock windows
1228 is started with \a dockWindow as the first (left-most and
1229 top-most) dock window.
1230
1231 If \a dockWindow is managed by another main window, it is first
1232 removed from that window.
1233*/
1234
1235void QMainWindow::addDockWindow( QDockWindow *dockWindow,
1236 Dock edge, bool newLine )
1237{
1238#ifdef Q_WS_MAC
1239 if(isTopLevel() && edge == DockTop)
1240 ChangeWindowAttributes((WindowPtr)handle(), kWindowToolbarButtonAttribute, 0);
1241#endif
1242 moveDockWindow( dockWindow, edge );
1243 dockWindow->setNewLine( newLine );
1244 if ( d->dockWindows.find( dockWindow ) == -1 ) {
1245 d->dockWindows.append( dockWindow );
1246 connect( dockWindow, SIGNAL( placeChanged(QDockWindow::Place) ),
1247 this, SLOT( slotPlaceChanged() ) );
1248 dockWindow->installEventFilter( this );
1249 }
1250 dockWindow->setOpaqueMoving( d->opaque );
1251}
1252
1253
1254/*!
1255 \overload
1256
1257 Adds \a dockWindow to the dock area with label \a label.
1258
1259 If \a newLine is FALSE (the default) the \a dockWindow is added at
1260 the end of the \a edge. For vertical edges the end is at the
1261 bottom, for horizontal edges (including \c Minimized) the end is
1262 at the right. If \a newLine is TRUE a new line of dock windows is
1263 started with \a dockWindow as the first (left-most and top-most)
1264 dock window.
1265
1266 If \a dockWindow is managed by another main window, it is first
1267 removed from that window.
1268*/
1269
1270void QMainWindow::addDockWindow( QDockWindow * dockWindow, const QString &label,
1271 Dock edge, bool newLine )
1272{
1273 addDockWindow( dockWindow, edge, newLine );
1274#ifndef QT_NO_TOOLBAR
1275 QToolBar *tb = ::qt_cast<QToolBar*>(dockWindow);
1276 if ( tb )
1277 tb->setLabel( label );
1278#endif
1279}
1280
1281/*!
1282 Moves \a dockWindow to the end of the \a edge.
1283
1284 For vertical edges the end is at the bottom, for horizontal edges
1285 (including \c Minimized) the end is at the right.
1286
1287 If \a dockWindow is managed by another main window, it is first
1288 removed from that window.
1289*/
1290
1291void QMainWindow::moveDockWindow( QDockWindow * dockWindow, Dock edge )
1292{
1293 Orientation oo = dockWindow->orientation();
1294 switch ( edge ) {
1295 case DockTop:
1296 if ( dockWindow->area() != d->topDock )
1297 dockWindow->removeFromDock( FALSE );
1298 d->topDock->moveDockWindow( dockWindow );
1299 emit dockWindowPositionChanged( dockWindow );
1300 break;
1301 case DockBottom:
1302 if ( dockWindow->area() != d->bottomDock )
1303 dockWindow->removeFromDock( FALSE );
1304 d->bottomDock->moveDockWindow( dockWindow );
1305 emit dockWindowPositionChanged( dockWindow );
1306 break;
1307 case DockRight:
1308 if ( dockWindow->area() != d->rightDock )
1309 dockWindow->removeFromDock( FALSE );
1310 d->rightDock->moveDockWindow( dockWindow );
1311 emit dockWindowPositionChanged( dockWindow );
1312 break;
1313 case DockLeft:
1314 if ( dockWindow->area() != d->leftDock )
1315 dockWindow->removeFromDock( FALSE );
1316 d->leftDock->moveDockWindow( dockWindow );
1317 emit dockWindowPositionChanged( dockWindow );
1318 break;
1319 case DockTornOff:
1320 dockWindow->undock();
1321 break;
1322 case DockMinimized:
1323 dockWindow->undock( d->hideDock );
1324 break;
1325 case DockUnmanaged:
1326 break;
1327 }
1328
1329 if ( oo != dockWindow->orientation() )
1330 dockWindow->setOrientation( dockWindow->orientation() );
1331}
1332
1333/*!
1334 \overload
1335
1336 Moves \a dockWindow to position \a index within the \a edge dock
1337 area.
1338
1339 Any dock windows with positions \a index or higher have their
1340 position number incremented and any of these on the same line are
1341 moved right (down for vertical dock areas) to make room.
1342
1343 If \a nl is TRUE, a new dock window line is created below the line
1344 in which the moved dock window appears and the moved dock window,
1345 with any others with higher positions on the same line, is moved
1346 to this new line.
1347
1348 The \a extraOffset is the space to put between the left side of
1349 the dock area (top side for vertical dock areas) and the dock
1350 window. (This is mostly used for restoring dock windows to the
1351 positions the user has dragged them to.)
1352
1353 If \a dockWindow is managed by another main window, it is first
1354 removed from that window.
1355*/
1356
1357void QMainWindow::moveDockWindow( QDockWindow * dockWindow, Dock edge, bool nl, int index, int extraOffset )
1358{
1359 Orientation oo = dockWindow->orientation();
1360
1361 dockWindow->setNewLine( nl );
1362 dockWindow->setOffset( extraOffset );
1363 switch ( edge ) {
1364 case DockTop:
1365 if ( dockWindow->area() != d->topDock )
1366 dockWindow->removeFromDock( FALSE );
1367 d->topDock->moveDockWindow( dockWindow, index );
1368 break;
1369 case DockBottom:
1370 if ( dockWindow->area() != d->bottomDock )
1371 dockWindow->removeFromDock( FALSE );
1372 d->bottomDock->moveDockWindow( dockWindow, index );
1373 break;
1374 case DockRight:
1375 if ( dockWindow->area() != d->rightDock )
1376 dockWindow->removeFromDock( FALSE );
1377 d->rightDock->moveDockWindow( dockWindow, index );
1378 break;
1379 case DockLeft:
1380 if ( dockWindow->area() != d->leftDock )
1381 dockWindow->removeFromDock( FALSE );
1382 d->leftDock->moveDockWindow( dockWindow, index );
1383 break;
1384 case DockTornOff:
1385 dockWindow->undock();
1386 break;
1387 case DockMinimized:
1388 dockWindow->undock( d->hideDock );
1389 break;
1390 case DockUnmanaged:
1391 break;
1392 }
1393
1394 if ( oo != dockWindow->orientation() )
1395 dockWindow->setOrientation( dockWindow->orientation() );
1396}
1397
1398/*!
1399 Removes \a dockWindow from the main window's docking area,
1400 provided \a dockWindow is non-null and managed by this main
1401 window.
1402*/
1403
1404void QMainWindow::removeDockWindow( QDockWindow * dockWindow )
1405{
1406#ifdef Q_WS_MAC
1407 if(isTopLevel() && dockWindow->area() == topDock() && !dockWindows( DockTop ).count())
1408 ChangeWindowAttributes((WindowPtr)handle(), 0, kWindowToolbarButtonAttribute);
1409#endif
1410
1411 dockWindow->hide();
1412 d->dockWindows.removeRef( dockWindow );
1413 disconnect( dockWindow, SIGNAL( placeChanged(QDockWindow::Place) ),
1414 this, SLOT( slotPlaceChanged() ) );
1415 dockWindow->removeEventFilter( this );
1416}
1417
1418/*!
1419 Sets up the geometry management of the window. It is called
1420 automatically when needed, so you shouldn't need to call it.
1421*/
1422
1423void QMainWindow::setUpLayout()
1424{
1425#ifndef QT_NO_MENUBAR
1426 if ( !d->mb ) {
1427 // slightly evil hack here. reconsider this
1428 QObjectList * l
1429 = ((QObject*)this)->queryList( "QMenuBar", 0, FALSE, FALSE );
1430 if ( l && l->count() )
1431 d->mb = menuBar();
1432 delete l;
1433 }
1434#endif
1435 if ( !d->sb ) {
1436 // as above.
1437 QObjectList * l
1438 = ((QObject*)this)->queryList( "QStatusBar", 0, FALSE, FALSE );
1439 if ( l && l->count() )
1440 d->sb = statusBar();
1441 delete l;
1442 }
1443
1444 if (!d->tll) {
1445 d->tll = new QBoxLayout( this, QBoxLayout::Down );
1446 d->tll->setResizeMode( minimumSize().isNull() ? QLayout::Minimum : QLayout::FreeResize );
1447 } else {
1448 d->tll->setMenuBar( 0 );
1449 QLayoutIterator it = d->tll->iterator();
1450 QLayoutItem *item;
1451 while ( (item = it.takeCurrent()) )
1452 delete item;
1453 }
1454
1455#ifndef QT_NO_MENUBAR
1456 if ( d->mb && d->mb->isVisibleTo( this ) ) {
1457 d->tll->setMenuBar( d->mb );
1458 if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this))
1459 d->tll->addSpacing( d->movable ? 1 : 2 );
1460 }
1461#endif
1462
1463 d->tll->addWidget( d->hideDock );
1464 if(d->topDock->parentWidget() == this)
1465 d->tll->addWidget( d->topDock );
1466
1467 QMainWindowLayout *mwl = new QMainWindowLayout( this, d->tll );
1468 d->tll->setStretchFactor( mwl, 1 );
1469
1470 if(d->leftDock->parentWidget() == this)
1471 mwl->setLeftDock( d->leftDock );
1472 if ( centralWidget() )
1473 mwl->setCentralWidget( centralWidget() );
1474 if(d->rightDock->parentWidget() == this)
1475 mwl->setRightDock( d->rightDock );
1476 d->mwl = mwl;
1477
1478 if(d->bottomDock->parentWidget() == this)
1479 d->tll->addWidget( d->bottomDock );
1480
1481 if ( d->sb && d->sb->parentWidget() == this) {
1482 d->tll->addWidget( d->sb, 0 );
1483 // make the sb stay on top of tool bars if there isn't enough space
1484 d->sb->raise();
1485 }
1486}
1487
1488/*! \reimp */
1489void QMainWindow::show()
1490{
1491 if ( !d->tll )
1492 setUpLayout();
1493
1494 // show all floating dock windows not explicitly hidden
1495 if (!isVisible()) {
1496 QPtrListIterator<QDockWindow> it(d->dockWindows);
1497 while ( it.current() ) {
1498 QDockWindow *dw = it.current();
1499 ++it;
1500 if ( dw->isTopLevel() && !dw->isVisible() && !dw->testWState(WState_ForceHide) )
1501 dw->show();
1502 }
1503 }
1504
1505 // show us last so we get focus
1506 QWidget::show();
1507}
1508
1509
1510/*! \reimp
1511*/
1512void QMainWindow::hide()
1513{
1514 if ( isVisible() ) {
1515 QPtrListIterator<QDockWindow> it(d->dockWindows);
1516 while ( it.current() ) {
1517 QDockWindow *dw = it.current();
1518 ++it;
1519 if ( dw->isTopLevel() && dw->isVisible() ) {
1520 dw->hide(); // implicit hide, so clear forcehide
1521 ((QMainWindow*)dw)->clearWState(WState_ForceHide);
1522 }
1523 }
1524 }
1525
1526 QWidget::hide();
1527}
1528
1529
1530/*! \reimp */
1531QSize QMainWindow::sizeHint() const
1532{
1533 QMainWindow* that = (QMainWindow*) this;
1534 // Workaround: because d->tll get's deleted in
1535 // totalSizeHint->polish->sendPostedEvents->childEvent->triggerLayout
1536 // [eg. canvas example on Qt/Embedded]
1537 QApplication::sendPostedEvents( that, QEvent::ChildInserted );
1538 if ( !that->d->tll )
1539 that->setUpLayout();
1540 return that->d->tll->totalSizeHint();
1541}
1542
1543/*! \reimp */
1544QSize QMainWindow::minimumSizeHint() const
1545{
1546 if ( !d->tll ) {
1547 QMainWindow* that = (QMainWindow*) this;
1548 that->setUpLayout();
1549 }
1550 return d->tll->totalMinimumSize();
1551}
1552
1553/*!
1554 Sets the central widget for this main window to \a w.
1555
1556 The central widget is surrounded by the left, top, right and
1557 bottom dock areas. The menu bar is above the top dock area.
1558
1559 \sa centralWidget()
1560*/
1561
1562void QMainWindow::setCentralWidget( QWidget * w )
1563{
1564 if ( d->mc )
1565 d->mc->removeEventFilter( this );
1566 d->mc = w;
1567 if ( d->mc )
1568 d->mc->installEventFilter( this );
1569 triggerLayout();
1570}
1571
1572
1573/*!
1574 Returns a pointer to the main window's central widget.
1575
1576 The central widget is surrounded by the left, top, right and
1577 bottom dock areas. The menu bar is above the top dock area.
1578
1579 \sa setCentralWidget()
1580*/
1581
1582QWidget * QMainWindow::centralWidget() const
1583{
1584 return d->mc;
1585}
1586
1587
1588/*! \reimp */
1589
1590void QMainWindow::paintEvent( QPaintEvent * )
1591{
1592 if (d->mb &&
1593 style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) {
1594 QPainter p( this );
1595 int y = d->mb->height() + 1;
1596 style().drawPrimitive(QStyle::PE_Separator, &p, QRect(0, y, width(), 1),
1597 colorGroup(), QStyle::Style_Sunken);
1598 }
1599}
1600
1601
1602bool QMainWindow::dockMainWindow( QObject *dock )
1603{
1604 while ( dock ) {
1605 if ( dock->parent() && dock->parent() == this )
1606 return TRUE;
1607 if ( ::qt_cast<QMainWindow*>(dock->parent()) )
1608 return FALSE;
1609 dock = dock->parent();
1610 }
1611 return FALSE;
1612}
1613
1614/*!
1615 \reimp
1616*/
1617
1618bool QMainWindow::eventFilter( QObject* o, QEvent *e )
1619{
1620 if ( e->type() == QEvent::Show && o == this ) {
1621 if ( !d->tll )
1622 setUpLayout();
1623 d->tll->activate();
1624 } else if ( e->type() == QEvent::ContextMenu && d->dockMenu &&
1625 ( ::qt_cast<QDockArea*>(o) && dockMainWindow( o ) || o == d->hideDock || o == d->mb ) ) {
1626 if ( showDockMenu( ( (QMouseEvent*)e )->globalPos() ) ) {
1627 ( (QContextMenuEvent*)e )->accept();
1628 return TRUE;
1629 }
1630 }
1631
1632 return QWidget::eventFilter( o, e );
1633}
1634
1635
1636/*!
1637 Monitors events, recieved in \a e, to ensure the layout is updated.
1638*/
1639void QMainWindow::childEvent( QChildEvent* e)
1640{
1641 if ( e->type() == QEvent::ChildRemoved ) {
1642 if ( e->child() == 0 ||
1643 !e->child()->isWidgetType() ||
1644 ((QWidget*)e->child())->testWFlags( WType_TopLevel ) ) {
1645 // nothing
1646 } else if ( e->child() == d->sb ) {
1647 d->sb = 0;
1648 triggerLayout();
1649 } else if ( e->child() == d->mb ) {
1650 d->mb = 0;
1651 triggerLayout();
1652 } else if ( e->child() == d->mc ) {
1653 d->mc = 0;
1654 d->mwl->setCentralWidget( 0 );
1655 triggerLayout();
1656 } else if ( ::qt_cast<QDockWindow*>(e->child()) ) {
1657 removeDockWindow( (QDockWindow *)(e->child()) );
1658 d->appropriate.remove( (QDockWindow*)e->child() );
1659 triggerLayout();
1660 }
1661 } else if ( e->type() == QEvent::ChildInserted && !d->sb ) {
1662 d->sb = ::qt_cast<QStatusBar*>(e->child());
1663 if ( d->sb ) {
1664 if ( d->tll ) {
1665 if ( !d->tll->findWidget( d->sb ) )
1666 d->tll->addWidget( d->sb );
1667 } else {
1668 triggerLayout();
1669 }
1670 }
1671 }
1672}
1673
1674/*!
1675 \reimp
1676*/
1677
1678bool QMainWindow::event( QEvent * e )
1679{
1680 if ( e->type() == QEvent::ChildRemoved && ( (QChildEvent*)e )->child() == d->mc ) {
1681 d->mc->removeEventFilter( this );
1682 d->mc = 0;
1683 d->mwl->setCentralWidget( 0 );
1684 }
1685
1686 return QWidget::event( e );
1687}
1688
1689
1690/*!
1691 \property QMainWindow::usesBigPixmaps
1692 \brief whether big pixmaps are enabled
1693
1694 If FALSE (the default), the tool buttons will use small pixmaps;
1695 otherwise big pixmaps will be used.
1696
1697 Tool buttons and other widgets that wish to respond to this
1698 setting are responsible for reading the correct state on startup,
1699 and for connecting to the main window's widget's
1700 pixmapSizeChanged() signal.
1701*/
1702
1703bool QMainWindow::usesBigPixmaps() const
1704{
1705 return d->ubp;
1706}
1707
1708void QMainWindow::setUsesBigPixmaps( bool enable )
1709{
1710 if ( enable == (bool)d->ubp )
1711 return;
1712
1713 d->ubp = enable;
1714 emit pixmapSizeChanged( enable );
1715
1716 QObjectList *l = queryList( "QLayout" );
1717 if ( !l || !l->first() ) {
1718 delete l;
1719 return;
1720 }
1721 for ( QLayout *lay = (QLayout*)l->first(); lay; lay = (QLayout*)l->next() )
1722 lay->activate();
1723 delete l;
1724}
1725
1726/*!
1727 \property QMainWindow::usesTextLabel
1728 \brief whether text labels for toolbar buttons are enabled
1729
1730 If disabled (the default), the tool buttons will not use text
1731 labels. If enabled, text labels will be used.
1732
1733 Tool buttons and other widgets that wish to respond to this
1734 setting are responsible for reading the correct state on startup,
1735 and for connecting to the main window's widget's
1736 usesTextLabelChanged() signal.
1737
1738 \sa QToolButton::setUsesTextLabel()
1739*/
1740
1741bool QMainWindow::usesTextLabel() const
1742{
1743 return d->utl;
1744}
1745
1746
1747void QMainWindow::setUsesTextLabel( bool enable )
1748{
1749 if ( enable == (bool)d->utl )
1750 return;
1751
1752 d->utl = enable;
1753 emit usesTextLabelChanged( enable );
1754
1755 QObjectList *l = queryList( "QLayout" );
1756 if ( !l || !l->first() ) {
1757 delete l;
1758 return;
1759 }
1760 for ( QLayout *lay = (QLayout*)l->first(); lay; lay = (QLayout*)l->next() )
1761 lay->activate();
1762 delete l;
1763}
1764
1765
1766/*!
1767 \fn void QMainWindow::pixmapSizeChanged( bool )
1768
1769 This signal is emitted whenever the setUsesBigPixmaps() is called
1770 with a value different to the current setting. All widgets that
1771 should respond to such changes, e.g. toolbar buttons, must connect
1772 to this signal.
1773*/
1774
1775/*!
1776 \fn void QMainWindow::usesTextLabelChanged( bool )
1777
1778 This signal is emitted whenever the setUsesTextLabel() is called
1779 with a value different to the current setting. All widgets that
1780 should respond to such changes, e.g. toolbar buttons, must connect
1781 to this signal.
1782*/
1783
1784/*!
1785 \fn void QMainWindow::dockWindowPositionChanged( QDockWindow *dockWindow )
1786
1787 This signal is emitted when the \a dockWindow has changed its
1788 position. A change in position occurs when a dock window is moved
1789 within its dock area or moved to another dock area (including the
1790 \c Minimized and \c TearOff dock areas).
1791
1792 \sa getLocation()
1793*/
1794
1795void QMainWindow::setRightJustification( bool enable )
1796{
1797 if ( enable == (bool)d->justify )
1798 return;
1799 d->justify = enable;
1800 triggerLayout( TRUE );
1801}
1802
1803
1804/*!
1805 \obsolete
1806 \property QMainWindow::rightJustification
1807 \brief whether the main window right-justifies its dock windows
1808
1809 If disabled (the default), stretchable dock windows are expanded,
1810 and non-stretchable dock windows are given the minimum space they
1811 need. Since most dock windows are not stretchable, this usually
1812 results in an unjustified right edge (or unjustified bottom edge
1813 for a vertical dock area). If enabled, the main window will
1814 right-justify its dock windows.
1815
1816 \sa QDockWindow::setVerticalStretchable(), QDockWindow::setHorizontalStretchable()
1817*/
1818
1819bool QMainWindow::rightJustification() const
1820{
1821 return d->justify;
1822}
1823
1824/*! \internal
1825 */
1826
1827void QMainWindow::triggerLayout( bool deleteLayout )
1828{
1829 if ( deleteLayout || !d->tll )
1830 setUpLayout();
1831 QApplication::postEvent( this, new QEvent( QEvent::LayoutHint ) );
1832}
1833
1834/*!
1835 Enters 'What's This?' mode and returns immediately.
1836
1837 This is the same as QWhatsThis::enterWhatsThisMode(), but
1838 implemented as a main window object's slot. This way it can easily
1839 be used for popup menus, for example:
1840
1841 \code
1842 QPopupMenu * help = new QPopupMenu( this );
1843 help->insertItem( "What's &This", this , SLOT(whatsThis()), SHIFT+Key_F1);
1844 \endcode
1845
1846 \sa QWhatsThis::enterWhatsThisMode()
1847*/
1848void QMainWindow::whatsThis()
1849{
1850#ifndef QT_NO_WHATSTHIS
1851 QWhatsThis::enterWhatsThisMode();
1852#endif
1853}
1854
1855
1856/*!
1857 \reimp
1858*/
1859
1860void QMainWindow::styleChange( QStyle& old )
1861{
1862 QWidget::styleChange( old );
1863}
1864
1865/*!
1866 Finds the location of the dock window \a dw.
1867
1868 If the \a dw dock window is found in the main window the function
1869 returns TRUE and populates the \a dock variable with the dw's dock
1870 area and the \a index with the dw's position within the dock area.
1871 It also sets \a nl to TRUE if the \a dw begins a new line
1872 (otherwise FALSE), and \a extraOffset with the dock window's offset.
1873
1874 If the \a dw dock window is not found then the function returns
1875 FALSE and the state of \a dock, \a index, \a nl and \a extraOffset
1876 is undefined.
1877
1878 If you want to save and restore dock window positions then use
1879 operator>>() and operator<<().
1880
1881 \sa operator>>() operator<<()
1882*/
1883
1884bool QMainWindow::getLocation( QDockWindow *dw, Dock &dock, int &index, bool &nl, int &extraOffset ) const
1885{
1886 dock = DockTornOff;
1887 if ( d->topDock->hasDockWindow( dw, &index ) )
1888 dock = DockTop;
1889 else if ( d->bottomDock->hasDockWindow( dw, &index ) )
1890 dock = DockBottom;
1891 else if ( d->leftDock->hasDockWindow( dw, &index ) )
1892 dock = DockLeft;
1893 else if ( d->rightDock->hasDockWindow( dw, &index ) )
1894 dock = DockRight;
1895 else if ( dw->parentWidget() == d->hideDock ) {
1896 index = 0;
1897 dock = DockMinimized;
1898 } else {
1899 index = 0;
1900 }
1901 nl = dw->newLine();
1902 extraOffset = dw->offset();
1903 return TRUE;
1904}
1905
1906#ifndef QT_NO_TOOLBAR
1907/*!
1908 Returns a list of all the toolbars which are in the \a dock dock
1909 area, regardless of their state.
1910
1911 For example, the \c TornOff dock area may contain closed toolbars
1912 but these are returned along with the visible toolbars.
1913
1914 \sa dockWindows()
1915*/
1916
1917QPtrList<QToolBar> QMainWindow::toolBars( Dock dock ) const
1918{
1919 QPtrList<QDockWindow> lst = dockWindows( dock );
1920 QPtrList<QToolBar> tbl;
1921 for ( QDockWindow *w = lst.first(); w; w = lst.next() ) {
1922 QToolBar *tb = ::qt_cast<QToolBar*>(w);
1923 if ( tb )
1924 tbl.append( tb );
1925 }
1926 return tbl;
1927}
1928#endif
1929
1930/*!
1931 Returns a list of all the dock windows which are in the \a dock
1932 dock area, regardless of their state.
1933
1934 For example, the \c DockTornOff dock area may contain closed dock
1935 windows but these are returned along with the visible dock
1936 windows.
1937*/
1938
1939QPtrList<QDockWindow> QMainWindow::dockWindows( Dock dock ) const
1940{
1941 QPtrList<QDockWindow> lst;
1942 switch ( dock ) {
1943 case DockTop:
1944 return d->topDock->dockWindowList();
1945 case DockBottom:
1946 return d->bottomDock->dockWindowList();
1947 case DockLeft:
1948 return d->leftDock->dockWindowList();
1949 case DockRight:
1950 return d->rightDock->dockWindowList();
1951 case DockTornOff: {
1952 for ( QDockWindow *w = d->dockWindows.first(); w; w = d->dockWindows.next() ) {
1953 if ( !w->area() && w->place() == QDockWindow::OutsideDock )
1954 lst.append( w );
1955 }
1956 }
1957 return lst;
1958 case DockMinimized: {
1959 if ( d->hideDock->children() ) {
1960 QObjectListIt it( *d->hideDock->children() );
1961 QObject *o;
1962 while ( ( o = it.current() ) ) {
1963 ++it;
1964 QDockWindow *dw = ::qt_cast<QDockWindow*>(o);
1965 if ( !dw )
1966 continue;
1967 lst.append( dw );
1968 }
1969 }
1970 }
1971 return lst;
1972 default:
1973 break;
1974 }
1975 return lst;
1976}
1977
1978/*!
1979 \overload
1980
1981 Returns the list of dock windows which belong to this main window,
1982 regardless of which dock area they are in or what their state is,
1983 (e.g. irrespective of whether they are visible or not).
1984*/
1985
1986QPtrList<QDockWindow> QMainWindow::dockWindows() const
1987{
1988 return d->dockWindows;
1989}
1990
1991void QMainWindow::setDockWindowsMovable( bool enable )
1992{
1993 d->movable = enable;
1994 QObjectList *l = queryList( "QDockWindow" );
1995 if ( l ) {
1996 for ( QObject *o = l->first(); o; o = l->next() )
1997 ( (QDockWindow*)o )->setMovingEnabled( enable );
1998 }
1999 delete l;
2000}
2001
2002/*!
2003 \property QMainWindow::dockWindowsMovable
2004 \brief whether the dock windows are movable
2005
2006 If TRUE (the default), the user will be able to move movable dock
2007 windows from one QMainWindow dock area to another, including the
2008 \c TearOff area (i.e. where the dock window floats freely as a
2009 window in its own right), and the \c Minimized area (where only
2010 the dock window's handle is shown below the menu bar). Moveable
2011 dock windows can also be moved within QMainWindow dock areas, i.e.
2012 to rearrange them within a dock area.
2013
2014 If FALSE the user will not be able to move any dock windows.
2015
2016 By default dock windows are moved transparently (i.e. only an
2017 outline rectangle is shown during the drag), but this setting can
2018 be changed with setOpaqueMoving().
2019
2020 \sa setDockEnabled(), setOpaqueMoving()
2021*/
2022
2023bool QMainWindow::dockWindowsMovable() const
2024{
2025 return d->movable;
2026}
2027
2028void QMainWindow::setOpaqueMoving( bool b )
2029{
2030 d->opaque = b;
2031 QObjectList *l = queryList( "QDockWindow" );
2032 if ( l ) {
2033 for ( QObject *o = l->first(); o; o = l->next() )
2034 ( (QDockWindow*)o )->setOpaqueMoving( b );
2035 }
2036 delete l;
2037}
2038
2039/*!
2040 \property QMainWindow::opaqueMoving
2041 \brief whether dock windows are moved opaquely
2042
2043 If TRUE the dock windows of the main window are shown opaquely
2044 (i.e. it shows the toolbar as it looks when docked) whilst it is
2045 being moved. If FALSE (the default) they are shown transparently,
2046 (i.e. as an outline rectangle).
2047
2048 \warning Opaque moving of toolbars and dockwindows is known to
2049 have several problems. We recommend avoiding the use of this
2050 feature for the time being. We intend fixing the problems in a
2051 future release.
2052*/
2053
2054bool QMainWindow::opaqueMoving() const
2055{
2056 return d->opaque;
2057}
2058
2059/*!
2060 This function will line up dock windows within the visible dock
2061 areas (\c Top, \c Left, \c Right and \c Bottom) as compactly as
2062 possible.
2063
2064 If \a keepNewLines is TRUE, all dock windows stay on their
2065 original lines. If \a keepNewLines is FALSE then newlines may be
2066 removed to achieve the most compact layout possible.
2067
2068 The method only works if dockWindowsMovable() returns TRUE.
2069*/
2070
2071void QMainWindow::lineUpDockWindows( bool keepNewLines )
2072{
2073 if ( !dockWindowsMovable() )
2074 return;
2075 d->topDock->lineUp( keepNewLines );
2076 d->leftDock->lineUp( keepNewLines );
2077 d->rightDock->lineUp( keepNewLines );
2078 d->bottomDock->lineUp( keepNewLines );
2079}
2080
2081/*!
2082 Returns TRUE, if the dock window menu is enabled; otherwise
2083 returns FALSE.
2084
2085 The menu lists the (appropriate()) dock windows (which may be
2086 shown or hidden), and has a "Line Up Dock Windows" menu item. It
2087 will also have a "Customize" menu item if isCustomizable() returns
2088 TRUE.
2089
2090 \sa setDockEnabled(), lineUpDockWindows() appropriate()
2091 setAppropriate()
2092*/
2093
2094bool QMainWindow::isDockMenuEnabled() const
2095{
2096 return d->dockMenu;
2097}
2098
2099/*!
2100 If \a b is TRUE, then right clicking on a dock window or dock area
2101 will pop up the dock window menu. If \a b is FALSE, right clicking
2102 a dock window or dock area will not pop up the menu.
2103
2104 The menu lists the (appropriate()) dock windows (which may be
2105 shown or hidden), and has a "Line Up Dock Windows" item. It will
2106 also have a "Customize" menu item if isCustomizable() returns
2107 TRUE.
2108
2109 \sa lineUpDockWindows(), isDockMenuEnabled()
2110*/
2111
2112void QMainWindow::setDockMenuEnabled( bool b )
2113{
2114 d->dockMenu = b;
2115}
2116
2117/*!
2118 Creates the dock window menu which contains all toolbars (if \a
2119 dockWindows is \c OnlyToolBars ), all dock windows (if \a
2120 dockWindows is \c NoToolBars) or all toolbars and dock windows (if
2121 \a dockWindows is \c AllDockWindows - the default).
2122
2123 This function is called internally when necessary, e.g. when the
2124 user right clicks a dock area (providing isDockMenuEnabled()
2125 returns TRUE).
2126\omit
2127### Qt 4.0
2128 You can reimplement this function if you wish to customize the
2129 behaviour.
2130\endomit
2131
2132 The menu items representing the toolbars and dock windows are
2133 checkable. The visible dock windows are checked and the hidden
2134 dock windows are unchecked. The user can click a menu item to
2135 change its state (show or hide the dock window).
2136
2137 The list and the state are always kept up-to-date.
2138
2139 Toolbars and dock windows which are not appropriate in the current
2140 context (see setAppropriate()) are not listed in the menu.
2141
2142 The menu also has a menu item for lining up the dock windows.
2143
2144 If isCustomizable() returns TRUE, a Customize menu item is added
2145 to the menu, which if clicked will call customize(). The
2146 isCustomizable() function we provide returns FALSE and customize()
2147 does nothing, so they must be reimplemented in a subclass to be
2148 useful.
2149*/
2150
2151QPopupMenu *QMainWindow::createDockWindowMenu( DockWindows dockWindows ) const
2152{
2153 QObjectList *l = queryList( "QDockWindow" );
2154
2155 if ( !l || l->isEmpty() )
2156 return 0;
2157
2158 delete l;
2159
2160 QPopupMenu *menu = new QPopupMenu( (QMainWindow*)this, "qt_customize_menu" );
2161 menu->setCheckable( TRUE );
2162 d->dockWindowModes.replace( menu, dockWindows );
2163 connect( menu, SIGNAL( aboutToShow() ), this, SLOT( menuAboutToShow() ) );
2164 return menu;
2165}
2166
2167/*!
2168 This slot is called from the aboutToShow() signal of the default
2169 dock menu of the mainwindow. The default implementation
2170 initializes the menu with all dock windows and toolbars in this
2171 slot.
2172\omit
2173### Qt 4.0
2174 If you want to do small adjustments to the menu, you can do it in
2175 this slot; or you can reimplement createDockWindowMenu().
2176\endomit
2177*/
2178
2179void QMainWindow::menuAboutToShow()
2180{
2181 QPopupMenu *menu = (QPopupMenu*)sender();
2182 QMap<QPopupMenu*, DockWindows>::Iterator it = d->dockWindowModes.find( menu );
2183 if ( it == d->dockWindowModes.end() )
2184 return;
2185 menu->clear();
2186
2187 DockWindows dockWindows = *it;
2188
2189 QObjectList *l = queryList( "QDockWindow" );
2190
2191 bool empty = TRUE;
2192 if ( l && !l->isEmpty() ) {
2193
2194 QObject *o = 0;
2195 if ( dockWindows == AllDockWindows || dockWindows == NoToolBars ) {
2196 for ( o = l->first(); o; o = l->next() ) {
2197 QDockWindow *dw = (QDockWindow*)o;
2198 if ( !appropriate( dw ) || ::qt_cast<QToolBar*>(dw) || !dockMainWindow( dw ) )
2199 continue;
2200 QString label = dw->caption();
2201 if ( !label.isEmpty() ) {
2202 int id = menu->insertItem( label, dw, SLOT( toggleVisible() ) );
2203 menu->setItemChecked( id, dw->isVisible() );
2204 empty = FALSE;
2205 }
2206 }
2207 if ( !empty )
2208 menu->insertSeparator();
2209 }
2210
2211 empty = TRUE;
2212
2213#ifndef QT_NO_TOOLBAR
2214 if ( dockWindows == AllDockWindows || dockWindows == OnlyToolBars ) {
2215 for ( o = l->first(); o; o = l->next() ) {
2216 QToolBar *tb = ::qt_cast<QToolBar*>(o);
2217 if ( !tb || !appropriate(tb) || !dockMainWindow(tb) )
2218 continue;
2219 QString label = tb->label();
2220 if ( !label.isEmpty() ) {
2221 int id = menu->insertItem( label, tb, SLOT( toggleVisible() ) );
2222 menu->setItemChecked( id, tb->isVisible() );
2223 empty = FALSE;
2224 }
2225 }
2226 }
2227#endif
2228
2229 }
2230
2231 delete l;
2232
2233 if ( !empty )
2234 menu->insertSeparator();
2235
2236 if ( dockWindowsMovable() )
2237 menu->insertItem( tr( "Line up" ), this, SLOT( doLineUp() ) );
2238 if ( isCustomizable() )
2239 menu->insertItem( tr( "Customize..." ), this, SLOT( customize() ) );
2240}
2241
2242/*!
2243 Shows the dock menu at the position \a globalPos. The menu lists
2244 the dock windows so that they can be shown (or hidden), lined up,
2245 and possibly customized. Returns TRUE if the menu is shown;
2246 otherwise returns FALSE.
2247
2248 If you want a custom menu, reimplement this function. You can
2249 create the menu from scratch or call createDockWindowMenu() and
2250 modify the result.
2251\omit
2252### Qt 4.0
2253 The default implementation uses the dock window menu which gets
2254 created by createDockWindowMenu(). You can reimplement
2255 createDockWindowMenu() if you want to use your own specialized
2256 popup menu.
2257\endomit
2258*/
2259
2260bool QMainWindow::showDockMenu( const QPoint &globalPos )
2261{
2262 if ( !d->dockMenu )
2263 return FALSE;
2264 if ( !d->rmbMenu )
2265 d->rmbMenu = createDockWindowMenu();
2266 if ( !d->rmbMenu )
2267 return FALSE;
2268
2269 d->rmbMenu->exec( globalPos );
2270 return TRUE;
2271}
2272
2273void QMainWindow::slotPlaceChanged()
2274{
2275 QObject* obj = (QObject*)sender();
2276 QDockWindow *dw = ::qt_cast<QDockWindow*>(obj);
2277 if ( dw )
2278 emit dockWindowPositionChanged( dw );
2279#ifndef QT_NO_TOOLBAR
2280 QToolBar *tb = ::qt_cast<QToolBar*>(obj);
2281 if ( tb )
2282 emit toolBarPositionChanged( tb );
2283#endif
2284}
2285
2286/*!
2287 \internal
2288 For internal use of QDockWindow only.
2289 */
2290
2291QDockArea *QMainWindow::dockingArea( const QPoint &p )
2292{
2293 int mh = d->mb ? d->mb->height() : 0;
2294 int sh = d->sb ? d->sb->height() : 0;
2295 if ( p.x() >= -5 && p.x() <= 100 && p.y() > mh && p.y() - height() - sh )
2296 return d->leftDock;
2297 if ( p.x() >= width() - 100 && p.x() <= width() + 5 && p.y() > mh && p.y() - height() - sh )
2298 return d->rightDock;
2299 if ( p.y() >= -5 && p.y() < mh + 100 && p.x() >= 0 && p.x() <= width() )
2300 return d->topDock;
2301 if ( p.y() >= height() - sh - 100 && p.y() <= height() + 5 && p.x() >= 0 && p.x() <= width() )
2302 return d->bottomDock;
2303 return 0;
2304}
2305
2306/*!
2307 Returns TRUE if \a dw is a dock window known to the main window;
2308 otherwise returns FALSE.
2309*/
2310
2311bool QMainWindow::hasDockWindow( QDockWindow *dw )
2312{
2313 return d->dockWindows.findRef( dw ) != -1;
2314}
2315
2316/*!
2317 Returns the \c Left dock area
2318
2319 \sa rightDock() topDock() bottomDock()
2320*/
2321
2322QDockArea *QMainWindow::leftDock() const
2323{
2324 return d->leftDock;
2325}
2326
2327/*!
2328 Returns the \c Right dock area
2329
2330 \sa leftDock() topDock() bottomDock()
2331*/
2332
2333QDockArea *QMainWindow::rightDock() const
2334{
2335 return d->rightDock;
2336}
2337
2338/*!
2339 Returns the \c Top dock area
2340
2341 \sa bottomDock() leftDock() rightDock()
2342*/
2343
2344QDockArea *QMainWindow::topDock() const
2345{
2346 return d->topDock;
2347}
2348
2349/*!
2350 Returns a pointer the \c Bottom dock area
2351
2352 \sa topDock() leftDock() rightDock()
2353*/
2354
2355QDockArea *QMainWindow::bottomDock() const
2356{
2357 return d->bottomDock;
2358}
2359
2360/*!
2361 This function is called when the user clicks the Customize menu
2362 item on the dock window menu.
2363
2364 The customize menu item will only appear if isCustomizable()
2365 returns TRUE (it returns FALSE by default).
2366
2367 The function is intended, for example, to provide the user with a
2368 means of telling the application that they wish to customize the
2369 main window, dock windows or dock areas.
2370
2371 The default implementation does nothing and the Customize menu
2372 item is not shown on the right-click menu by default. If you want
2373 the item to appear then reimplement isCustomizable() to return
2374 TRUE, and reimplement this function to do whatever you want.
2375
2376 \sa isCustomizable()
2377*/
2378
2379void QMainWindow::customize()
2380{
2381}
2382
2383/*!
2384 Returns TRUE if the dock area dock window menu includes the
2385 Customize menu item (which calls customize() when clicked).
2386 Returns FALSE by default, i.e. the popup menu will not contain a
2387 Customize menu item. You will need to reimplement this function
2388 and set it to return TRUE if you wish the user to be able to see
2389 the dock window menu.
2390
2391 \sa customize()
2392*/
2393
2394bool QMainWindow::isCustomizable() const
2395{
2396 return FALSE;
2397}
2398
2399/*!
2400 Returns TRUE if it is appropriate to include a menu item for the
2401 \a dw dock window in the dock window menu; otherwise returns
2402 FALSE.
2403
2404 The user is able to change the state (show or hide) a dock window
2405 that has a menu item by clicking the item.
2406
2407 Call setAppropriate() to indicate whether or not a particular dock
2408 window should appear on the popup menu.
2409
2410 \sa setAppropriate()
2411*/
2412
2413bool QMainWindow::appropriate( QDockWindow *dw ) const
2414{
2415 QMap<QDockWindow*, bool>::ConstIterator it = d->appropriate.find( dw );
2416 if ( it == d->appropriate.end() )
2417 return TRUE;
2418 return *it;
2419}
2420
2421/*!
2422 Use this function to control whether or not the \a dw dock
2423 window's caption should appear as a menu item on the dock window
2424 menu that lists the dock windows.
2425
2426 If \a a is TRUE then the \a dw will appear as a menu item on the
2427 dock window menu. The user is able to change the state (show or
2428 hide) a dock window that has a menu item by clicking the item;
2429 depending on the state of your application, this may or may not be
2430 appropriate. If \a a is FALSE the \a dw will not appear on the
2431 popup menu.
2432
2433 \sa showDockMenu() isCustomizable() customize()
2434*/
2435
2436void QMainWindow::setAppropriate( QDockWindow *dw, bool a )
2437{
2438 d->appropriate.replace( dw, a );
2439}
2440
2441#ifndef QT_NO_TEXTSTREAM
2442static void saveDockArea( QTextStream &ts, QDockArea *a )
2443{
2444 QPtrList<QDockWindow> l = a->dockWindowList();
2445 for ( QDockWindow *dw = l.first(); dw; dw = l.next() ) {
2446 ts << QString( dw->caption() );
2447 ts << ",";
2448 }
2449 ts << endl;
2450 ts << *a;
2451}
2452
2453/*!
2454 \relates QMainWindow
2455
2456 Writes the layout (sizes and positions) of the dock windows in the
2457 dock areas of the QMainWindow \a mainWindow, including \c
2458 Minimized and \c TornOff dock windows, to the text stream \a ts.
2459
2460 This can be used, for example, in conjunction with QSettings to
2461 save the user's layout when the \mainWindow receives a closeEvent.
2462
2463 \sa operator>>() closeEvent()
2464*/
2465
2466QTextStream &operator<<( QTextStream &ts, const QMainWindow &mainWindow )
2467{
2468 QPtrList<QDockWindow> l = mainWindow.dockWindows( Qt::DockMinimized );
2469 QDockWindow *dw = 0;
2470 for ( dw = l.first(); dw; dw = l.next() ) {
2471 ts << dw->caption();
2472 ts << ",";
2473 }
2474 ts << endl;
2475
2476 l = mainWindow.dockWindows( Qt::DockTornOff );
2477 for ( dw = l.first(); dw; dw = l.next() ) {
2478 ts << dw->caption();
2479 ts << ",";
2480 }
2481 ts << endl;
2482 for ( dw = l.first(); dw; dw = l.next() ) {
2483 ts << "[" << dw->caption() << ","
2484 << (int)dw->geometry().x() << ","
2485 << (int)dw->geometry().y() << ","
2486 << (int)dw->geometry().width() << ","
2487 << (int)dw->geometry().height() << ","
2488 << (int)dw->isVisible() << "]";
2489 }
2490 ts << endl;
2491
2492 saveDockArea( ts, mainWindow.topDock() );
2493 saveDockArea( ts, mainWindow.bottomDock() );
2494 saveDockArea( ts, mainWindow.rightDock() );
2495 saveDockArea( ts, mainWindow.leftDock() );
2496 return ts;
2497}
2498
2499static void loadDockArea( const QStringList &names, QDockArea *a, Qt::Dock d, QPtrList<QDockWindow> &l, QMainWindow *mw, QTextStream &ts )
2500{
2501 for ( QStringList::ConstIterator it = names.begin(); it != names.end(); ++it ) {
2502 for ( QDockWindow *dw = l.first(); dw; dw = l.next() ) {
2503 if ( dw->caption() == *it ) {
2504 mw->addDockWindow( dw, d );
2505 break;
2506 }
2507 }
2508 }
2509 if ( a ) {
2510 ts >> *a;
2511 } else if ( d == Qt::DockTornOff ) {
2512 QString s = ts.readLine();
2513 enum State { Pre, Name, X, Y, Width, Height, Visible, Post };
2514 int state = Pre;
2515 QString name, x, y, w, h, visible;
2516 QChar c;
2517 for ( int i = 0; i < (int)s.length(); ++i ) {
2518 c = s[ i ];
2519 if ( state == Pre && c == '[' ) {
2520 state++;
2521 continue;
2522 }
2523 if ( c == ',' &&
2524 ( state == Name || state == X || state == Y || state == Width || state == Height ) ) {
2525 state++;
2526 continue;
2527 }
2528 if ( state == Visible && c == ']' ) {
2529 for ( QDockWindow *dw = l.first(); dw; dw = l.next() ) {
2530 if ( QString( dw->caption() ) == name ) {
2531 if ( !::qt_cast<QToolBar*>(dw) )
2532 dw->setGeometry( x.toInt(), y.toInt(), w.toInt(), h.toInt() );
2533 else
2534 dw->setGeometry( x.toInt(), y.toInt(), dw->width(), dw->height() );
2535 if ( !(bool)visible.toInt() )
2536 dw->hide();
2537 else
2538 dw->show();
2539 break;
2540 }
2541 }
2542
2543 name = x = y = w = h = visible = "";
2544
2545 state = Pre;
2546 continue;
2547 }
2548 if ( state == Name )
2549 name += c;
2550 else if ( state == X )
2551 x += c;
2552 else if ( state == Y )
2553 y += c;
2554 else if ( state == Width )
2555 w += c;
2556 else if ( state == Height )
2557 h += c;
2558 else if ( state == Visible )
2559 visible += c;
2560 }
2561 }
2562}
2563
2564/*!
2565 \relates QMainWindow
2566
2567 Reads the layout (sizes and positions) of the dock windows in the
2568 dock areas of the QMainWindow \a mainWindow from the text stream,
2569 \a ts, including \c Minimized and \c TornOff dock windows.
2570 Restores the dock windows and dock areas to these sizes and
2571 positions. The layout information must be in the format produced
2572 by operator<<().
2573
2574 This can be used, for example, in conjunction with QSettings to
2575 restore the user's layout.
2576
2577 \sa operator<<()
2578*/
2579
2580QTextStream &operator>>( QTextStream &ts, QMainWindow &mainWindow )
2581{
2582 QPtrList<QDockWindow> l = mainWindow.dockWindows();
2583
2584 QString s = ts.readLine();
2585 QStringList names = QStringList::split( ',', s );
2586 loadDockArea( names, 0, Qt::DockMinimized, l, &mainWindow, ts );
2587
2588 s = ts.readLine();
2589 names = QStringList::split( ',', s );
2590 loadDockArea( names, 0, Qt::DockTornOff, l, &mainWindow, ts );
2591
2592 int i = 0;
2593 QDockArea *areas[] = { mainWindow.topDock(), mainWindow.bottomDock(), mainWindow.rightDock(), mainWindow.leftDock() };
2594 for ( int d = (int)Qt::DockTop; d != (int)Qt::DockMinimized; ++d, ++i ) {
2595 s = ts.readLine();
2596 names = QStringList::split( ',', s );
2597 loadDockArea( names, areas[ i ], (Qt::Dock)d, l, &mainWindow, ts );
2598 }
2599 return ts;
2600}
2601#endif
2602
2603#include "qmainwindow.moc"
2604
2605#endif
Note: See TracBrowser for help on using the repository browser.