source: trunk/src/qt3support/widgets/q3mainwindow.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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