source: trunk/src/gui/widgets/qmainwindow.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

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

File size: 50.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui 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 qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qmainwindow.h"
43#include "qmainwindowlayout_p.h"
44
45#ifndef QT_NO_MAINWINDOW
46
47#include "qdockwidget.h"
48#include "qtoolbar.h"
49
50#include <qapplication.h>
51#include <qmenubar.h>
52#include <qstatusbar.h>
53#include <qevent.h>
54#include <qstyle.h>
55#include <qdebug.h>
56#include <qpainter.h>
57
58#include <private/qwidget_p.h>
59#include "qtoolbar_p.h"
60#include "qwidgetanimator_p.h"
61#ifdef Q_WS_MAC
62#include <private/qt_mac_p.h>
63#include <private/qt_cocoa_helpers_mac_p.h>
64QT_BEGIN_NAMESPACE
65extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
66QT_END_NAMESPACE
67#endif
68
69QT_BEGIN_NAMESPACE
70
71class QMainWindowPrivate : public QWidgetPrivate
72{
73 Q_DECLARE_PUBLIC(QMainWindow)
74public:
75 inline QMainWindowPrivate()
76 : layout(0), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly)
77#ifdef Q_WS_MAC
78 , useHIToolBar(false)
79#endif
80#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
81 , hasOldCursor(false) , cursorAdjusted(false)
82#endif
83 { }
84 QMainWindowLayout *layout;
85 QSize iconSize;
86 bool explicitIconSize;
87 Qt::ToolButtonStyle toolButtonStyle;
88#ifdef Q_WS_MAC
89 bool useHIToolBar;
90#endif
91 void init();
92 QList<int> hoverSeparator;
93 QPoint hoverPos;
94
95#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
96 QCursor separatorCursor(const QList<int> &path) const;
97 void adjustCursor(const QPoint &pos);
98 QCursor oldCursor;
99 uint hasOldCursor : 1;
100 uint cursorAdjusted : 1;
101#endif
102};
103
104void QMainWindowPrivate::init()
105{
106 Q_Q(QMainWindow);
107 layout = new QMainWindowLayout(q);
108 const int metric = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q);
109 iconSize = QSize(metric, metric);
110 q->setAttribute(Qt::WA_Hover);
111}
112
113/*
114 The Main Window:
115
116 +----------------------------------------------------------+
117 | Menu Bar |
118 +----------------------------------------------------------+
119 | Tool Bar Area |
120 | +--------------------------------------------------+ |
121 | | Dock Window Area | |
122 | | +------------------------------------------+ | |
123 | | | | | |
124 | | | Central Widget | | |
125 | | | | | |
126 | | | | | |
127 | | | | | |
128 | | | | | |
129 | | | | | |
130 | | | | | |
131 | | | | | |
132 | | | | | |
133 | | | | | |
134 | | | | | |
135 | | +------------------------------------------+ | |
136 | | | |
137 | +--------------------------------------------------+ |
138 | |
139 +----------------------------------------------------------+
140 | Status Bar |
141 +----------------------------------------------------------+
142
143*/
144
145/*!
146 \class QMainWindow
147 \brief The QMainWindow class provides a main application
148 window.
149 \ingroup mainwindow-classes
150
151
152 \tableofcontents
153
154 \section1 Qt Main Window Framework
155
156 A main window provides a framework for building an
157 application's user interface. Qt has QMainWindow and its \l{Main
158 Window and Related Classes}{related classes} for main window
159 management. QMainWindow has its own layout to which you can add
160 \l{QToolBar}s, \l{QDockWidget}s, a
161 QMenuBar, and a QStatusBar. The layout has a center area that can
162 be occupied by any kind of widget. You can see an image of the
163 layout below.
164
165 \image mainwindowlayout.png
166
167 \note Creating a main window without a central widget is not supported.
168 You must have a central widget even if it is just a placeholder.
169
170 \section1 Creating Main Window Components
171
172 A central widget will typically be a standard Qt widget such
173 as a QTextEdit or a QGraphicsView. Custom widgets can also be
174 used for advanced applications. You set the central widget with \c
175 setCentralWidget().
176
177 Main windows have either a single (SDI) or multiple (MDI)
178 document interface. You create MDI applications in Qt by using a
179 QMdiArea as the central widget.
180
181 We will now examine each of the other widgets that can be
182 added to a main window. We give examples on how to create and add
183 them.
184
185 \section2 Creating Menus
186
187 Qt implements menus in QMenu and QMainWindow keeps them in a
188 QMenuBar. \l{QAction}{QAction}s are added to the menus, which
189 display them as menu items.
190
191 You can add new menus to the main window's menu bar by calling
192 \c menuBar(), which returns the QMenuBar for the window, and then
193 add a menu with QMenuBar::addMenu().
194
195 QMainWindow comes with a default menu bar, but you can also
196 set one yourself with \c setMenuBar(). If you wish to implement a
197 custom menu bar (i.e., not use the QMenuBar widget), you can set it
198 with \c setMenuWidget().
199
200 An example of how to create menus follows:
201
202 \snippet examples/mainwindows/application/mainwindow.cpp 26
203
204 The \c createPopupMenu() function creates popup menus when the
205 main window receives context menu events. The default
206 implementation generates a menu with the checkable actions from
207 the dock widgets and toolbars. You can reimplement \c
208 createPopupMenu() for a custom menu.
209
210 \section2 Creating Toolbars
211
212 Toolbars are implemented in the QToolBar class. You add a
213 toolbar to a main window with \c addToolBar().
214
215 You control the initial position of toolbars by assigning them
216 to a specific Qt::ToolBarArea. You can split an area by inserting
217 a toolbar break - think of this as a line break in text editing -
218 with \c addToolBarBreak() or \c insertToolBarBreak(). You can also
219 restrict placement by the user with QToolBar::setAllowedAreas()
220 and QToolBar::setMovable().
221
222 The size of toolbar icons can be retrieved with \c iconSize().
223 The sizes are platform dependent; you can set a fixed size with \c
224 setIconSize(). You can alter the appearance of all tool buttons in
225 the toolbars with \c setToolButtonStyle().
226
227 An example of toolbar creation follows:
228
229 \snippet examples/mainwindows/application/mainwindow.cpp 29
230
231 \section2 Creating Dock Widgets
232
233 Dock widgets are implemented in the QDockWidget class. A dock
234 widget is a window that can be docked into the main window. You
235 add dock widgets to a main window with \c addDockWidget().
236
237 There are four dock widget areas as given by the
238 Qt::DockWidgetArea enum: left, right, top, and bottom. You can
239 specify which dock widget area that should occupy the corners
240 where the areas overlap with \c setCorner(). By default
241 each area can only contain one row (vertical or horizontal) of
242 dock widgets, but if you enable nesting with \c
243 setDockNestingEnabled(), dock widgets can be added in either
244 direction.
245
246 Two dock widgets may also be stacked on top of each other. A
247 QTabBar is then used to select which of the widgets that should be
248 displayed.
249
250 We give an example of how to create and add dock widgets to a
251 main window:
252
253 \snippet doc/src/snippets/mainwindowsnippet.cpp 0
254
255 \section2 The Status Bar
256
257 You can set a status bar with \c setStatusBar(), but one is
258 created the first time \c statusBar() (which returns the main
259 window's status bar) is called. See QStatusBar for information on
260 how to use it.
261
262 \section1 Storing State
263
264 QMainWindow can store the state of its layout with \c
265 saveState(); it can later be retrieved with \c restoreState(). It
266 is the position and size (relative to the size of the main window)
267 of the toolbars and dock widgets that are stored.
268
269 \sa QMenuBar, QToolBar, QStatusBar, QDockWidget, {Application
270 Example}, {Dock Widgets Example}, {MDI Example}, {SDI Example},
271 {Menus Example}
272*/
273
274/*!
275 \fn void QMainWindow::iconSizeChanged(const QSize &iconSize)
276
277 This signal is emitted when the size of the icons used in the
278 window is changed. The new icon size is passed in \a iconSize.
279
280 You can connect this signal to other components to help maintain
281 a consistent appearance for your application.
282
283 \sa setIconSize()
284*/
285
286/*!
287 \fn void QMainWindow::toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle)
288
289 This signal is emitted when the style used for tool buttons in the
290 window is changed. The new style is passed in \a toolButtonStyle.
291
292 You can connect this signal to other components to help maintain
293 a consistent appearance for your application.
294
295 \sa setToolButtonStyle()
296*/
297
298/*!
299 Constructs a QMainWindow with the given \a parent and the specified
300 widget \a flags.
301
302 QMainWindow sets the Qt::Window flag itself, and will hence
303 always be created as a top-level widget.
304 */
305QMainWindow::QMainWindow(QWidget *parent, Qt::WindowFlags flags)
306 : QWidget(*(new QMainWindowPrivate()), parent, flags | Qt::Window)
307{
308 d_func()->init();
309}
310
311#ifdef QT3_SUPPORT
312/*!
313 \obsolete
314 Constructs a QMainWindow with the given \a parent, \a name, and
315 with the specified widget \a flags.
316 */
317QMainWindow::QMainWindow(QWidget *parent, const char *name, Qt::WindowFlags flags)
318 : QWidget(*(new QMainWindowPrivate()), parent, flags | Qt::WType_TopLevel)
319{
320 setObjectName(QString::fromAscii(name));
321 d_func()->init();
322}
323#endif
324
325/*!
326 Destroys the main window.
327 */
328QMainWindow::~QMainWindow()
329{ }
330
331/*! \property QMainWindow::iconSize
332 \brief size of toolbar icons in this mainwindow.
333
334 The default is the default tool bar icon size of the GUI style.
335 Note that the icons used must be at least of this size as the
336 icons are only scaled down.
337*/
338
339/*!
340 \property QMainWindow::dockOptions
341 \brief the docking behavior of QMainWindow
342 \since 4.3
343
344 The default value is AnimatedDocks | AllowTabbedDocks.
345*/
346
347/*!
348 \enum QMainWindow::DockOption
349 \since 4.3
350
351 This enum contains flags that specify the docking behavior of QMainWindow.
352
353 \value AnimatedDocks Identical to the \l animated property.
354
355 \value AllowNestedDocks Identical to the \l dockNestingEnabled property.
356
357 \value AllowTabbedDocks The user can drop one dock widget "on top" of
358 another. The two widgets are stacked and a tab
359 bar appears for selecting which one is visible.
360
361 \value ForceTabbedDocks Each dock area contains a single stack of tabbed
362 dock widgets. In other words, dock widgets cannot
363 be placed next to each other in a dock area. If
364 this option is set, AllowNestedDocks has no effect.
365
366 \value VerticalTabs The two vertical dock areas on the sides of the
367 main window show their tabs vertically. If this
368 option is not set, all dock areas show their tabs
369 at the bottom. Implies AllowTabbedDocks. See also
370 \l setTabPosition().
371
372 These options only control how dock widgets may be dropped in a QMainWindow.
373 They do not re-arrange the dock widgets to conform with the specified
374 options. For this reason they should be set before any dock widgets
375 are added to the main window. Exceptions to this are the AnimatedDocks and
376 VerticalTabs options, which may be set at any time.
377*/
378
379void QMainWindow::setDockOptions(DockOptions opt)
380{
381 Q_D(QMainWindow);
382 d->layout->setDockOptions(opt);
383}
384
385QMainWindow::DockOptions QMainWindow::dockOptions() const
386{
387 Q_D(const QMainWindow);
388 return d->layout->dockOptions;
389}
390
391QSize QMainWindow::iconSize() const
392{ return d_func()->iconSize; }
393
394void QMainWindow::setIconSize(const QSize &iconSize)
395{
396 Q_D(QMainWindow);
397 QSize sz = iconSize;
398 if (!sz.isValid()) {
399 const int metric = style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, this);
400 sz = QSize(metric, metric);
401 }
402 if (d->iconSize != sz) {
403 d->iconSize = sz;
404 emit iconSizeChanged(d->iconSize);
405 }
406 d->explicitIconSize = iconSize.isValid();
407}
408
409/*! \property QMainWindow::toolButtonStyle
410 \brief style of toolbar buttons in this mainwindow.
411
412 The default is Qt::ToolButtonIconOnly.
413*/
414
415Qt::ToolButtonStyle QMainWindow::toolButtonStyle() const
416{ return d_func()->toolButtonStyle; }
417
418void QMainWindow::setToolButtonStyle(Qt::ToolButtonStyle toolButtonStyle)
419{
420 Q_D(QMainWindow);
421 if (d->toolButtonStyle == toolButtonStyle)
422 return;
423 d->toolButtonStyle = toolButtonStyle;
424 emit toolButtonStyleChanged(d->toolButtonStyle);
425}
426
427#ifndef QT_NO_MENUBAR
428/*!
429 Returns the menu bar for the main window. This function creates
430 and returns an empty menu bar if the menu bar does not exist.
431
432 If you want all windows in a Mac application to share one menu
433 bar, don't use this function to create it, because the menu bar
434 created here will have this QMainWindow as its parent. Instead,
435 you must create a menu bar that does not have a parent, which you
436 can then share among all the Mac windows. Create a parent-less
437 menu bar this way:
438
439 \snippet doc/src/snippets/code/src_gui_widgets_qmenubar.cpp 1
440
441 \sa setMenuBar()
442*/
443QMenuBar *QMainWindow::menuBar() const
444{
445 QMenuBar *menuBar = qobject_cast<QMenuBar *>(d_func()->layout->menuBar());
446 if (!menuBar) {
447 QMainWindow *self = const_cast<QMainWindow *>(this);
448 menuBar = new QMenuBar(self);
449 self->setMenuBar(menuBar);
450 }
451 return menuBar;
452}
453
454/*!
455 Sets the menu bar for the main window to \a menuBar.
456
457 Note: QMainWindow takes ownership of the \a menuBar pointer and
458 deletes it at the appropriate time.
459
460 \sa menuBar()
461*/
462void QMainWindow::setMenuBar(QMenuBar *menuBar)
463{
464 Q_D(QMainWindow);
465 if (d->layout->menuBar() && d->layout->menuBar() != menuBar) {
466 // Reparent corner widgets before we delete the old menu bar.
467 QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(d->layout->menuBar());
468 if (menuBar) {
469 // TopLeftCorner widget.
470 QWidget *cornerWidget = oldMenuBar->cornerWidget(Qt::TopLeftCorner);
471 if (cornerWidget)
472 menuBar->setCornerWidget(cornerWidget, Qt::TopLeftCorner);
473 // TopRightCorner widget.
474 cornerWidget = oldMenuBar->cornerWidget(Qt::TopRightCorner);
475 if (cornerWidget)
476 menuBar->setCornerWidget(cornerWidget, Qt::TopRightCorner);
477 }
478 oldMenuBar->hide();
479 oldMenuBar->deleteLater();
480 }
481 d->layout->setMenuBar(menuBar);
482}
483
484/*!
485 \since 4.2
486
487 Returns the menu bar for the main window. This function returns
488 null if a menu bar hasn't been constructed yet.
489*/
490QWidget *QMainWindow::menuWidget() const
491{
492 QWidget *menuBar = d_func()->layout->menuBar();
493 return menuBar;
494}
495
496/*!
497 \since 4.2
498
499 Sets the menu bar for the main window to \a menuBar.
500
501 QMainWindow takes ownership of the \a menuBar pointer and
502 deletes it at the appropriate time.
503*/
504void QMainWindow::setMenuWidget(QWidget *menuBar)
505{
506 Q_D(QMainWindow);
507 if (d->layout->menuBar() && d->layout->menuBar() != menuBar) {
508 d->layout->menuBar()->hide();
509 d->layout->menuBar()->deleteLater();
510 }
511 d->layout->setMenuBar(menuBar);
512}
513#endif // QT_NO_MENUBAR
514
515#ifndef QT_NO_STATUSBAR
516/*!
517 Returns the status bar for the main window. This function creates
518 and returns an empty status bar if the status bar does not exist.
519
520 \sa setStatusBar()
521*/
522QStatusBar *QMainWindow::statusBar() const
523{
524 QStatusBar *statusbar = d_func()->layout->statusBar();
525 if (!statusbar) {
526 QMainWindow *self = const_cast<QMainWindow *>(this);
527 statusbar = new QStatusBar(self);
528 statusbar->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
529 self->setStatusBar(statusbar);
530 }
531 return statusbar;
532}
533
534/*!
535 Sets the status bar for the main window to \a statusbar.
536
537 Setting the status bar to 0 will remove it from the main window.
538 Note that QMainWindow takes ownership of the \a statusbar pointer
539 and deletes it at the appropriate time.
540
541 \sa statusBar()
542*/
543void QMainWindow::setStatusBar(QStatusBar *statusbar)
544{
545 Q_D(QMainWindow);
546 if (d->layout->statusBar() && d->layout->statusBar() != statusbar) {
547 d->layout->statusBar()->hide();
548 d->layout->statusBar()->deleteLater();
549 }
550 d->layout->setStatusBar(statusbar);
551}
552#endif // QT_NO_STATUSBAR
553
554/*!
555 Returns the central widget for the main window. This function
556 returns zero if the central widget has not been set.
557
558 \sa setCentralWidget()
559*/
560QWidget *QMainWindow::centralWidget() const
561{ return d_func()->layout->centralWidget(); }
562
563/*!
564 Sets the given \a widget to be the main window's central widget.
565
566 Note: QMainWindow takes ownership of the \a widget pointer and
567 deletes it at the appropriate time.
568
569 \sa centralWidget()
570*/
571void QMainWindow::setCentralWidget(QWidget *widget)
572{
573 Q_D(QMainWindow);
574 if (d->layout->centralWidget() && d->layout->centralWidget() != widget) {
575 d->layout->centralWidget()->hide();
576 d->layout->centralWidget()->deleteLater();
577 }
578 d->layout->setCentralWidget(widget);
579}
580
581#ifndef QT_NO_DOCKWIDGET
582/*!
583 Sets the given dock widget \a area to occupy the specified \a
584 corner.
585
586 \sa corner()
587*/
588void QMainWindow::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
589{
590 bool valid = false;
591 switch (corner) {
592 case Qt::TopLeftCorner:
593 valid = (area == Qt::TopDockWidgetArea || area == Qt::LeftDockWidgetArea);
594 break;
595 case Qt::TopRightCorner:
596 valid = (area == Qt::TopDockWidgetArea || area == Qt::RightDockWidgetArea);
597 break;
598 case Qt::BottomLeftCorner:
599 valid = (area == Qt::BottomDockWidgetArea || area == Qt::LeftDockWidgetArea);
600 break;
601 case Qt::BottomRightCorner:
602 valid = (area == Qt::BottomDockWidgetArea || area == Qt::RightDockWidgetArea);
603 break;
604 }
605 if (!valid)
606 qWarning("QMainWindow::setCorner(): 'area' is not valid for 'corner'");
607 else
608 d_func()->layout->setCorner(corner, area);
609}
610
611/*!
612 Returns the dock widget area that occupies the specified \a
613 corner.
614
615 \sa setCorner()
616*/
617Qt::DockWidgetArea QMainWindow::corner(Qt::Corner corner) const
618{ return d_func()->layout->corner(corner); }
619#endif
620
621#ifndef QT_NO_TOOLBAR
622
623static bool checkToolBarArea(Qt::ToolBarArea area, const char *where)
624{
625 switch (area) {
626 case Qt::LeftToolBarArea:
627 case Qt::RightToolBarArea:
628 case Qt::TopToolBarArea:
629 case Qt::BottomToolBarArea:
630 return true;
631 default:
632 break;
633 }
634 qWarning("%s: invalid 'area' argument", where);
635 return false;
636}
637
638/*!
639 Adds a toolbar break to the given \a area after all the other
640 objects that are present.
641*/
642void QMainWindow::addToolBarBreak(Qt::ToolBarArea area)
643{
644 if (!checkToolBarArea(area, "QMainWindow::addToolBarBreak"))
645 return;
646 d_func()->layout->addToolBarBreak(area);
647}
648
649/*!
650 Inserts a toolbar break before the toolbar specified by \a before.
651*/
652void QMainWindow::insertToolBarBreak(QToolBar *before)
653{ d_func()->layout->insertToolBarBreak(before); }
654
655/*!
656 Removes a toolbar break previously inserted before the toolbar specified by \a before.
657*/
658
659void QMainWindow::removeToolBarBreak(QToolBar *before)
660{
661 Q_D(QMainWindow);
662 d->layout->removeToolBarBreak(before);
663}
664
665/*!
666 Adds the \a toolbar into the specified \a area in this main
667 window. The \a toolbar is placed at the end of the current tool
668 bar block (i.e. line). If the main window already manages \a toolbar
669 then it will only move the toolbar to \a area.
670
671 \sa insertToolBar() addToolBarBreak() insertToolBarBreak()
672*/
673void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar)
674{
675 if (!checkToolBarArea(area, "QMainWindow::addToolBar"))
676 return;
677
678 Q_D(QMainWindow);
679
680 disconnect(this, SIGNAL(iconSizeChanged(QSize)),
681 toolbar, SLOT(_q_updateIconSize(QSize)));
682 disconnect(this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
683 toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
684
685 if(toolbar->d_func()->state && toolbar->d_func()->state->dragging) {
686 //removing a toolbar which is dragging will cause crash
687#ifndef QT_NO_DOCKWIDGET
688 bool animated = isAnimated();
689 setAnimated(false);
690#endif
691 toolbar->d_func()->endDrag();
692#ifndef QT_NO_DOCKWIDGET
693 setAnimated(animated);
694#endif
695 }
696
697 if (!d->layout->usesHIToolBar(toolbar)) {
698 d->layout->removeWidget(toolbar);
699 } else {
700 d->layout->removeToolBar(toolbar);
701 }
702
703 toolbar->d_func()->_q_updateIconSize(d->iconSize);
704 toolbar->d_func()->_q_updateToolButtonStyle(d->toolButtonStyle);
705 connect(this, SIGNAL(iconSizeChanged(QSize)),
706 toolbar, SLOT(_q_updateIconSize(QSize)));
707 connect(this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
708 toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
709
710 d->layout->addToolBar(area, toolbar);
711}
712
713/*! \overload
714 Equivalent of calling addToolBar(Qt::TopToolBarArea, \a toolbar)
715*/
716void QMainWindow::addToolBar(QToolBar *toolbar)
717{ addToolBar(Qt::TopToolBarArea, toolbar); }
718
719/*!
720 \overload
721
722 Creates a QToolBar object, setting its window title to \a title,
723 and inserts it into the top toolbar area.
724
725 \sa setWindowTitle()
726*/
727QToolBar *QMainWindow::addToolBar(const QString &title)
728{
729 QToolBar *toolBar = new QToolBar(this);
730 toolBar->setWindowTitle(title);
731 addToolBar(toolBar);
732 return toolBar;
733}
734
735/*!
736 Inserts the \a toolbar into the area occupied by the \a before toolbar
737 so that it appears before it. For example, in normal left-to-right
738 layout operation, this means that \a toolbar will appear to the left
739 of the toolbar specified by \a before in a horizontal toolbar area.
740
741 \sa insertToolBarBreak() addToolBar() addToolBarBreak()
742*/
743void QMainWindow::insertToolBar(QToolBar *before, QToolBar *toolbar)
744{
745 Q_D(QMainWindow);
746
747 d->layout->removeToolBar(toolbar);
748
749 toolbar->d_func()->_q_updateIconSize(d->iconSize);
750 toolbar->d_func()->_q_updateToolButtonStyle(d->toolButtonStyle);
751 connect(this, SIGNAL(iconSizeChanged(QSize)),
752 toolbar, SLOT(_q_updateIconSize(QSize)));
753 connect(this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
754 toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
755
756 d->layout->insertToolBar(before, toolbar);
757}
758
759/*!
760 Removes the \a toolbar from the main window layout and hides
761 it. Note that the \a toolbar is \e not deleted.
762*/
763void QMainWindow::removeToolBar(QToolBar *toolbar)
764{
765 if (toolbar) {
766 d_func()->layout->removeToolBar(toolbar);
767 toolbar->hide();
768 }
769}
770
771/*!
772 Returns the Qt::ToolBarArea for \a toolbar. If \a toolbar has not
773 been added to the main window, this function returns \c
774 Qt::NoToolBarArea.
775
776 \sa addToolBar() addToolBarBreak() Qt::ToolBarArea
777*/
778Qt::ToolBarArea QMainWindow::toolBarArea(QToolBar *toolbar) const
779{ return d_func()->layout->toolBarArea(toolbar); }
780
781/*!
782
783 Returns whether there is a toolbar
784 break before the \a toolbar.
785
786 \sa addToolBarBreak(), insertToolBarBreak()
787*/
788bool QMainWindow::toolBarBreak(QToolBar *toolbar) const
789{
790 return d_func()->layout->toolBarBreak(toolbar);
791}
792
793#endif // QT_NO_TOOLBAR
794
795#ifndef QT_NO_DOCKWIDGET
796
797/*! \property QMainWindow::animated
798 \brief whether manipulating dock widgets and tool bars is animated
799 \since 4.2
800
801 When a dock widget or tool bar is dragged over the
802 main window, the main window adjusts its contents
803 to indicate where the dock widget or tool bar will
804 be docked if it is dropped. Setting this property
805 causes QMainWindow to move its contents in a smooth
806 animation. Clearing this property causes the contents
807 to snap into their new positions.
808
809 By default, this property is set. It may be cleared if
810 the main window contains widgets which are slow at resizing
811 or repainting themselves.
812
813 Setting this property is identical to setting the AnimatedDocks
814 option using setDockOptions().
815*/
816
817bool QMainWindow::isAnimated() const
818{
819 Q_D(const QMainWindow);
820 return d->layout->dockOptions & AnimatedDocks;
821}
822
823void QMainWindow::setAnimated(bool enabled)
824{
825 Q_D(QMainWindow);
826
827 DockOptions opts = d->layout->dockOptions;
828 if (enabled)
829 opts |= AnimatedDocks;
830 else
831 opts &= ~AnimatedDocks;
832
833 d->layout->setDockOptions(opts);
834}
835
836/*! \property QMainWindow::dockNestingEnabled
837 \brief whether docks can be nested
838 \since 4.2
839
840 If this property is false, dock areas can only contain a single row
841 (horizontal or vertical) of dock widgets. If this property is true,
842 the area occupied by a dock widget can be split in either direction to contain
843 more dock widgets.
844
845 Dock nesting is only necessary in applications that contain a lot of
846 dock widgets. It gives the user greater freedom in organizing their
847 main window. However, dock nesting leads to more complex
848 (and less intuitive) behavior when a dock widget is dragged over the
849 main window, since there are more ways in which a dropped dock widget
850 may be placed in the dock area.
851
852 Setting this property is identical to setting the AllowNestedDocks option
853 using setDockOptions().
854*/
855
856bool QMainWindow::isDockNestingEnabled() const
857{
858 Q_D(const QMainWindow);
859 return d->layout->dockOptions & AllowNestedDocks;
860}
861
862void QMainWindow::setDockNestingEnabled(bool enabled)
863{
864 Q_D(QMainWindow);
865
866 DockOptions opts = d->layout->dockOptions;
867 if (enabled)
868 opts |= AllowNestedDocks;
869 else
870 opts &= ~AllowNestedDocks;
871
872 d->layout->setDockOptions(opts);
873}
874
875#if 0
876/*! \property QMainWindow::verticalTabsEnabled
877 \brief whether left and right dock areas use vertical tabs
878 \since 4.2
879
880 If this property is set to false, dock areas containing tabbed dock widgets
881 display horizontal tabs, simmilar to Visual Studio.
882
883 If this property is set to true, then the right and left dock areas display vertical
884 tabs, simmilar to KDevelop.
885
886 This property should be set before any dock widgets are added to the main window.
887*/
888
889bool QMainWindow::verticalTabsEnabled() const
890{
891 return d_func()->layout->verticalTabsEnabled();
892}
893
894void QMainWindow::setVerticalTabsEnabled(bool enabled)
895{
896 d_func()->layout->setVerticalTabsEnabled(enabled);
897}
898#endif
899
900static bool checkDockWidgetArea(Qt::DockWidgetArea area, const char *where)
901{
902 switch (area) {
903 case Qt::LeftDockWidgetArea:
904 case Qt::RightDockWidgetArea:
905 case Qt::TopDockWidgetArea:
906 case Qt::BottomDockWidgetArea:
907 return true;
908 default:
909 break;
910 }
911 qWarning("%s: invalid 'area' argument", where);
912 return false;
913}
914
915#ifndef QT_NO_TABBAR
916/*!
917 \property QMainWindow::documentMode
918 \brief whether the tab bar for tabbed dockwidgets is set to document mode.
919 \since 4.5
920
921 The default is false.
922
923 \sa QTabBar::documentMode
924*/
925bool QMainWindow::documentMode() const
926{
927 return d_func()->layout->documentMode();
928}
929
930void QMainWindow::setDocumentMode(bool enabled)
931{
932 d_func()->layout->setDocumentMode(enabled);
933}
934#endif // QT_NO_TABBAR
935
936#ifndef QT_NO_TABWIDGET
937/*!
938 \property QMainWindow::tabShape
939 \brief the tab shape used for tabbed dock widgets.
940 \since 4.5
941
942 The default is \l QTabWidget::Rounded.
943
944 \sa setTabPosition()
945*/
946QTabWidget::TabShape QMainWindow::tabShape() const
947{
948 return d_func()->layout->tabShape();
949}
950
951void QMainWindow::setTabShape(QTabWidget::TabShape tabShape)
952{
953 d_func()->layout->setTabShape(tabShape);
954}
955
956/*!
957 \since 4.5
958
959 Returns the tab position for \a area.
960
961 \note The \l VerticalTabs dock option overrides the tab positions returned
962 by this function.
963
964 \sa setTabPosition(), tabShape()
965*/
966QTabWidget::TabPosition QMainWindow::tabPosition(Qt::DockWidgetArea area) const
967{
968 if (!checkDockWidgetArea(area, "QMainWindow::tabPosition"))
969 return QTabWidget::South;
970 return d_func()->layout->tabPosition(area);
971}
972
973/*!
974 \since 4.5
975
976 Sets the tab position for the given dock widget \a areas to the specified
977 \a tabPosition. By default, all dock areas show their tabs at the bottom.
978
979 \note The \l VerticalTabs dock option overrides the tab positions set by
980 this method.
981
982 \sa tabPosition(), setTabShape()
983*/
984void QMainWindow::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
985{
986 d_func()->layout->setTabPosition(areas, tabPosition);
987}
988#endif // QT_NO_TABWIDGET
989
990/*!
991 Adds the given \a dockwidget to the specified \a area.
992*/
993void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget)
994{
995 if (!checkDockWidgetArea(area, "QMainWindow::addDockWidget"))
996 return;
997
998 Qt::Orientation orientation = Qt::Vertical;
999 switch (area) {
1000 case Qt::TopDockWidgetArea:
1001 case Qt::BottomDockWidgetArea:
1002 orientation = Qt::Horizontal;
1003 break;
1004 default:
1005 break;
1006 }
1007 d_func()->layout->removeWidget(dockwidget); // in case it was already in here
1008 addDockWidget(area, dockwidget, orientation);
1009
1010#ifdef Q_WS_MAC //drawer support
1011 QMacCocoaAutoReleasePool pool;
1012 extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
1013 if (qt_mac_is_macdrawer(dockwidget)) {
1014 extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp
1015 window()->createWinId();
1016 dockwidget->window()->createWinId();
1017 qt_mac_set_drawer_preferred_edge(dockwidget, area);
1018 if (dockwidget->isVisible()) {
1019 dockwidget->hide();
1020 dockwidget->show();
1021 }
1022 }
1023#endif
1024}
1025
1026/*!
1027 Restores the state of \a dockwidget if it is created after the call
1028 to restoreState(). Returns true if the state was restored; otherwise
1029 returns false.
1030
1031 \sa restoreState(), saveState()
1032*/
1033
1034bool QMainWindow::restoreDockWidget(QDockWidget *dockwidget)
1035{
1036 return d_func()->layout->restoreDockWidget(dockwidget);
1037}
1038
1039/*!
1040 Adds \a dockwidget into the given \a area in the direction
1041 specified by the \a orientation.
1042*/
1043void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget,
1044 Qt::Orientation orientation)
1045{
1046 if (!checkDockWidgetArea(area, "QMainWindow::addDockWidget"))
1047 return;
1048
1049 // add a window to an area, placing done relative to the previous
1050 d_func()->layout->addDockWidget(area, dockwidget, orientation);
1051}
1052
1053/*!
1054 \fn void QMainWindow::splitDockWidget(QDockWidget *first, QDockWidget *second, Qt::Orientation orientation)
1055
1056 Splits the space covered by the \a first dock widget into two parts,
1057 moves the \a first dock widget into the first part, and moves the
1058 \a second dock widget into the second part.
1059
1060 The \a orientation specifies how the space is divided: A Qt::Horizontal
1061 split places the second dock widget to the right of the first; a
1062 Qt::Vertical split places the second dock widget below the first.
1063
1064 \e Note: if \a first is currently in a tabbed docked area, \a second will
1065 be added as a new tab, not as a neighbor of \a first. This is because a
1066 single tab can contain only one dock widget.
1067
1068 \e Note: The Qt::LayoutDirection influences the order of the dock widgets
1069 in the two parts of the divided area. When right-to-left layout direction
1070 is enabled, the placing of the dock widgets will be reversed.
1071
1072 \sa tabifyDockWidget(), addDockWidget(), removeDockWidget()
1073*/
1074void QMainWindow::splitDockWidget(QDockWidget *after, QDockWidget *dockwidget,
1075 Qt::Orientation orientation)
1076{
1077 d_func()->layout->splitDockWidget(after, dockwidget, orientation);
1078}
1079
1080/*!
1081 \fn void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
1082
1083 Moves \a second dock widget on top of \a first dock widget, creating a tabbed
1084 docked area in the main window.
1085
1086 \sa tabifiedDockWidgets()
1087*/
1088void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
1089{
1090 d_func()->layout->tabifyDockWidget(first, second);
1091}
1092
1093
1094/*!
1095 \fn QList<QDockWidget*> QMainWindow::tabifiedDockWidgets(QDockWidget *dockwidget) const
1096
1097 Returns the dock widgets that are tabified together with \a dockwidget.
1098
1099 \since 4.5
1100 \sa tabifyDockWidget()
1101*/
1102
1103QList<QDockWidget*> QMainWindow::tabifiedDockWidgets(QDockWidget *dockwidget) const
1104{
1105 QList<QDockWidget*> ret;
1106#if defined(QT_NO_TABBAR)
1107 Q_UNUSED(dockwidget);
1108#else
1109 const QDockAreaLayoutInfo *info = d_func()->layout->layoutState.dockAreaLayout.info(dockwidget);
1110 if (info && info->tabbed && info->tabBar) {
1111 for(int i = 0; i < info->item_list.count(); ++i) {
1112 const QDockAreaLayoutItem &item = info->item_list.at(i);
1113 if (item.widgetItem) {
1114 if (QDockWidget *dock = qobject_cast<QDockWidget*>(item.widgetItem->widget())) {
1115 if (dock != dockwidget) {
1116 ret += dock;
1117 }
1118 }
1119 }
1120 }
1121 }
1122#endif
1123 return ret;
1124}
1125
1126
1127/*!
1128 Removes the \a dockwidget from the main window layout and hides
1129 it. Note that the \a dockwidget is \e not deleted.
1130*/
1131void QMainWindow::removeDockWidget(QDockWidget *dockwidget)
1132{
1133 if (dockwidget) {
1134 d_func()->layout->removeWidget(dockwidget);
1135 dockwidget->hide();
1136 }
1137}
1138
1139/*!
1140 Returns the Qt::DockWidgetArea for \a dockwidget. If \a dockwidget
1141 has not been added to the main window, this function returns \c
1142 Qt::NoDockWidgetArea.
1143
1144 \sa addDockWidget() splitDockWidget() Qt::DockWidgetArea
1145*/
1146Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
1147{ return d_func()->layout->dockWidgetArea(dockwidget); }
1148
1149#endif // QT_NO_DOCKWIDGET
1150
1151/*!
1152 Saves the current state of this mainwindow's toolbars and
1153 dockwidgets. The \a version number is stored as part of the data.
1154
1155 The \link QObject::objectName objectName\endlink property is used
1156 to identify each QToolBar and QDockWidget. You should make sure
1157 that this property is unique for each QToolBar and QDockWidget you
1158 add to the QMainWindow
1159
1160 To restore the saved state, pass the return value and \a version
1161 number to restoreState().
1162
1163 To save the geometry when the window closes, you can
1164 implement a close event like this:
1165
1166 \snippet doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp 0
1167
1168 \sa restoreState(), QWidget::saveGeometry(), QWidget::restoreGeometry()
1169*/
1170QByteArray QMainWindow::saveState(int version) const
1171{
1172 QByteArray data;
1173 QDataStream stream(&data, QIODevice::WriteOnly);
1174 stream << QMainWindowLayout::VersionMarker;
1175 stream << version;
1176 d_func()->layout->saveState(stream);
1177 return data;
1178}
1179
1180/*!
1181 Restores the \a state of this mainwindow's toolbars and
1182 dockwidgets. The \a version number is compared with that stored
1183 in \a state. If they do not match, the mainwindow's state is left
1184 unchanged, and this function returns \c false; otherwise, the state
1185 is restored, and this function returns \c true.
1186
1187 To restore geometry saved using QSettings, you can use code like
1188 this:
1189
1190 \snippet doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp 1
1191
1192 \sa saveState(), QWidget::saveGeometry(),
1193 QWidget::restoreGeometry(), restoreDockWidget()
1194*/
1195bool QMainWindow::restoreState(const QByteArray &state, int version)
1196{
1197 if (state.isEmpty())
1198 return false;
1199 QByteArray sd = state;
1200 QDataStream stream(&sd, QIODevice::ReadOnly);
1201 int marker, v;
1202 stream >> marker;
1203 stream >> v;
1204 if (stream.status() != QDataStream::Ok || marker != QMainWindowLayout::VersionMarker || v != version)
1205 return false;
1206 bool restored = d_func()->layout->restoreState(stream);
1207 return restored;
1208}
1209
1210#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
1211QCursor QMainWindowPrivate::separatorCursor(const QList<int> &path) const
1212{
1213 QDockAreaLayoutInfo *info = layout->layoutState.dockAreaLayout.info(path);
1214 Q_ASSERT(info != 0);
1215 if (path.size() == 1) { // is this the "top-level" separator which separates a dock area
1216 // from the central widget?
1217 switch (path.first()) {
1218 case QInternal::LeftDock:
1219 case QInternal::RightDock:
1220 return Qt::SplitHCursor;
1221 case QInternal::TopDock:
1222 case QInternal::BottomDock:
1223 return Qt::SplitVCursor;
1224 default:
1225 break;
1226 }
1227 }
1228
1229 // no, it's a splitter inside a dock area, separating two dock widgets
1230
1231 return info->o == Qt::Horizontal
1232 ? Qt::SplitHCursor : Qt::SplitVCursor;
1233}
1234
1235void QMainWindowPrivate::adjustCursor(const QPoint &pos)
1236{
1237 Q_Q(QMainWindow);
1238
1239 hoverPos = pos;
1240
1241 if (pos == QPoint(0, 0)) {
1242 if (!hoverSeparator.isEmpty())
1243 q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
1244 hoverSeparator.clear();
1245
1246 if (cursorAdjusted) {
1247 cursorAdjusted = false;
1248 if (hasOldCursor)
1249 q->setCursor(oldCursor);
1250 else
1251 q->unsetCursor();
1252 }
1253 } else {
1254 QList<int> pathToSeparator
1255 = layout->layoutState.dockAreaLayout.findSeparator(pos);
1256
1257 if (pathToSeparator != hoverSeparator) {
1258 if (!hoverSeparator.isEmpty())
1259 q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
1260
1261 hoverSeparator = pathToSeparator;
1262
1263 if (hoverSeparator.isEmpty()) {
1264 if (cursorAdjusted) {
1265 cursorAdjusted = false;
1266 if (hasOldCursor)
1267 q->setCursor(oldCursor);
1268 else
1269 q->unsetCursor();
1270 }
1271 } else {
1272 q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
1273 if (!cursorAdjusted) {
1274 oldCursor = q->cursor();
1275 hasOldCursor = q->testAttribute(Qt::WA_SetCursor);
1276 }
1277 QCursor cursor = separatorCursor(hoverSeparator);
1278 cursorAdjusted = false; //to not reset the oldCursor in event(CursorChange)
1279 q->setCursor(cursor);
1280 cursorAdjusted = true;
1281 }
1282 }
1283 }
1284}
1285#endif
1286
1287/*! \reimp */
1288bool QMainWindow::event(QEvent *event)
1289{
1290 Q_D(QMainWindow);
1291 switch (event->type()) {
1292
1293#ifndef QT_NO_DOCKWIDGET
1294 case QEvent::Paint: {
1295 QPainter p(this);
1296 QRegion r = static_cast<QPaintEvent*>(event)->region();
1297 d->layout->layoutState.dockAreaLayout.paintSeparators(&p, this, r, d->hoverPos);
1298 break;
1299 }
1300
1301#ifndef QT_NO_CURSOR
1302 case QEvent::HoverMove: {
1303 d->adjustCursor(static_cast<QHoverEvent*>(event)->pos());
1304 break;
1305 }
1306
1307 // We don't want QWidget to call update() on the entire QMainWindow
1308 // on HoverEnter and HoverLeave, hence accept the event (return true).
1309 case QEvent::HoverEnter:
1310 return true;
1311 case QEvent::HoverLeave:
1312 d->adjustCursor(QPoint(0, 0));
1313 return true;
1314 case QEvent::ShortcutOverride: // when a menu pops up
1315 d->adjustCursor(QPoint(0, 0));
1316 break;
1317#endif // QT_NO_CURSOR
1318
1319 case QEvent::MouseButtonPress: {
1320 QMouseEvent *e = static_cast<QMouseEvent*>(event);
1321 if (e->button() == Qt::LeftButton && d->layout->startSeparatorMove(e->pos())) {
1322 // The click was on a separator, eat this event
1323 e->accept();
1324 return true;
1325 }
1326 break;
1327 }
1328
1329 case QEvent::MouseMove: {
1330 QMouseEvent *e = static_cast<QMouseEvent*>(event);
1331
1332#ifndef QT_NO_CURSOR
1333 d->adjustCursor(e->pos());
1334#endif
1335 if (e->buttons() & Qt::LeftButton) {
1336 if (d->layout->separatorMove(e->pos())) {
1337 // We're moving a separator, eat this event
1338 e->accept();
1339 return true;
1340 }
1341 }
1342
1343 break;
1344 }
1345
1346 case QEvent::MouseButtonRelease: {
1347 QMouseEvent *e = static_cast<QMouseEvent*>(event);
1348 if (d->layout->endSeparatorMove(e->pos())) {
1349 // We've released a separator, eat this event
1350 e->accept();
1351 return true;
1352 }
1353 break;
1354 }
1355
1356#endif
1357
1358#ifndef QT_NO_TOOLBAR
1359 case QEvent::ToolBarChange: {
1360 d->layout->toggleToolBarsVisible();
1361 return true;
1362 }
1363#endif
1364
1365#ifndef QT_NO_STATUSTIP
1366 case QEvent::StatusTip:
1367#ifndef QT_NO_STATUSBAR
1368 if (QStatusBar *sb = d->layout->statusBar())
1369 sb->showMessage(static_cast<QStatusTipEvent*>(event)->tip());
1370 else
1371#endif
1372 static_cast<QStatusTipEvent*>(event)->ignore();
1373 return true;
1374#endif // QT_NO_STATUSTIP
1375
1376 case QEvent::StyleChange:
1377 if (!d->explicitIconSize)
1378 setIconSize(QSize());
1379 break;
1380#ifdef Q_WS_MAC
1381 case QEvent::Show:
1382 if (unifiedTitleAndToolBarOnMac())
1383 d->layout->syncUnifiedToolbarVisibility();
1384 d->layout->blockVisiblityCheck = false;
1385 break;
1386 case QEvent::WindowStateChange:
1387 {
1388 if (isHidden()) {
1389 // We are coming out of a minimize, leave things as is.
1390 d->layout->blockVisiblityCheck = true;
1391 }
1392# ifdef QT_MAC_USE_COCOA
1393 // We need to update the HIToolbar status when we go out of or into fullscreen.
1394 QWindowStateChangeEvent *wce = static_cast<QWindowStateChangeEvent *>(event);
1395 if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) {
1396 d->layout->updateHIToolBarStatus();
1397 }
1398# endif // Cocoa
1399 }
1400 break;
1401#endif // Q_WS_MAC
1402#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
1403 case QEvent::CursorChange:
1404 if (d->cursorAdjusted) {
1405 d->oldCursor = cursor();
1406 d->hasOldCursor = testAttribute(Qt::WA_SetCursor);
1407 }
1408 break;
1409#endif
1410 default:
1411 break;
1412 }
1413
1414 return QWidget::event(event);
1415}
1416
1417#ifndef QT_NO_TOOLBAR
1418
1419/*!
1420 \property QMainWindow::unifiedTitleAndToolBarOnMac
1421 \brief whether the window uses the unified title and toolbar look on Mac OS X
1422 \since 4.3
1423
1424 This property is false by default and only has any effect on Mac OS X 10.4 or higher.
1425
1426 If set to true, then the top toolbar area is replaced with a Carbon HIToolbar
1427 or a Cocoa NSToolbar (depending on whether Qt was built with Carbon or Cocoa).
1428 All toolbars in the top toolbar area and any toolbars added afterwards are
1429 moved to that. This means a couple of things.
1430
1431 \list
1432 \i QToolBars in this toolbar area are not movable and you cannot drag other
1433 toolbars to it
1434 \i Toolbar breaks are not respected or preserved
1435 \i Any custom widgets in the toolbar will not be shown if the toolbar
1436 becomes too small (only actions will be shown)
1437 \i Before Qt 4.5, if you called showFullScreen() on the main window, the QToolbar would
1438 disappear since it is considered to be part of the title bar. Qt 4.5 and up will now work around this by pulling
1439 the toolbars out and back into the regular toolbar and vice versa when you swap out.
1440 However, a good practice would be that turning off the unified toolbar before you call
1441 showFullScreen() and restoring it after you call showNormal().
1442 \endlist
1443
1444 Setting this back to false will remove these restrictions.
1445
1446 The Qt::WA_MacBrushedMetal attribute takes precedence over this property.
1447*/
1448void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
1449{
1450#ifdef Q_WS_MAC
1451 Q_D(QMainWindow);
1452 if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3)
1453 return;
1454
1455 // ### Disable the unified toolbar when using anything but the native graphics system.
1456 if (windowSurface())
1457 return;
1458
1459 d->useHIToolBar = set;
1460 createWinId(); // We need the hiview for down below.
1461
1462 d->layout->updateHIToolBarStatus();
1463 // Enabling the unified toolbar clears the opaque size grip setting, update it.
1464 d->macUpdateOpaqueSizeGrip();
1465#else
1466 Q_UNUSED(set)
1467#endif
1468}
1469
1470bool QMainWindow::unifiedTitleAndToolBarOnMac() const
1471{
1472#ifdef Q_WS_MAC
1473 return d_func()->useHIToolBar && !testAttribute(Qt::WA_MacBrushedMetal) && !(windowFlags() & Qt::FramelessWindowHint);
1474#endif
1475 return false;
1476}
1477
1478#endif // QT_NO_TOOLBAR
1479
1480/*!
1481 \internal
1482*/
1483bool QMainWindow::isSeparator(const QPoint &pos) const
1484{
1485#ifndef QT_NO_DOCKWIDGET
1486 Q_D(const QMainWindow);
1487 return !d->layout->layoutState.dockAreaLayout.findSeparator(pos).isEmpty();
1488#else
1489 Q_UNUSED(pos);
1490 return false;
1491#endif
1492}
1493
1494#ifndef QT_NO_CONTEXTMENU
1495/*!
1496 \reimp
1497*/
1498void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
1499{
1500 event->ignore();
1501 // only show the context menu for direct QDockWidget and QToolBar
1502 // children and for the menu bar as well
1503 QWidget *child = childAt(event->pos());
1504 while (child && child != this) {
1505#ifndef QT_NO_MENUBAR
1506 if (QMenuBar *mb = qobject_cast<QMenuBar *>(child)) {
1507 if (mb->parentWidget() != this)
1508 return;
1509 break;
1510 }
1511#endif
1512#ifndef QT_NO_DOCKWIDGET
1513 if (QDockWidget *dw = qobject_cast<QDockWidget *>(child)) {
1514 if (dw->parentWidget() != this)
1515 return;
1516 if (dw->widget()
1517 && dw->widget()->geometry().contains(child->mapFrom(this, event->pos()))) {
1518 // ignore the event if the mouse is over the QDockWidget contents
1519 return;
1520 }
1521 break;
1522 }
1523#endif // QT_NO_DOCKWIDGET
1524#ifndef QT_NO_TOOLBAR
1525 if (QToolBar *tb = qobject_cast<QToolBar *>(child)) {
1526 if (tb->parentWidget() != this)
1527 return;
1528 break;
1529 }
1530#endif
1531 child = child->parentWidget();
1532 }
1533 if (child == this)
1534 return;
1535
1536#ifndef QT_NO_MENU
1537 QMenu *popup = createPopupMenu();
1538 if (popup && !popup->isEmpty()) {
1539 popup->exec(event->globalPos());
1540 event->accept();
1541 }
1542 delete popup;
1543#endif
1544}
1545#endif // QT_NO_CONTEXTMENU
1546
1547#ifndef QT_NO_MENU
1548/*!
1549 Returns a popup menu containing checkable entries for the toolbars and
1550 dock widgets present in the main window. If there are no toolbars and
1551 dock widgets present, this function returns a null pointer.
1552
1553 By default, this function is called by the main window when the user
1554 activates a context menu, typically by right-clicking on a toolbar or a dock
1555 widget.
1556
1557 If you want to create a custom popup menu, reimplement this function and
1558 return a newly-created popup menu. Ownership of the popup menu is transferred
1559 to the caller.
1560
1561 \sa addDockWidget(), addToolBar(), menuBar()
1562*/
1563QMenu *QMainWindow::createPopupMenu()
1564{
1565 Q_D(QMainWindow);
1566 QMenu *menu = 0;
1567#ifndef QT_NO_DOCKWIDGET
1568 QList<QDockWidget *> dockwidgets = qFindChildren<QDockWidget *>(this);
1569 if (dockwidgets.size()) {
1570 menu = new QMenu(this);
1571 for (int i = 0; i < dockwidgets.size(); ++i) {
1572 QDockWidget *dockWidget = dockwidgets.at(i);
1573 if (dockWidget->parentWidget() == this
1574 && !d->layout->layoutState.dockAreaLayout.indexOf(dockWidget).isEmpty()) {
1575 menu->addAction(dockwidgets.at(i)->toggleViewAction());
1576 }
1577 }
1578 menu->addSeparator();
1579 }
1580#endif // QT_NO_DOCKWIDGET
1581#ifndef QT_NO_TOOLBAR
1582 QList<QToolBar *> toolbars = qFindChildren<QToolBar *>(this);
1583 if (toolbars.size()) {
1584 if (!menu)
1585 menu = new QMenu(this);
1586 for (int i = 0; i < toolbars.size(); ++i) {
1587 QToolBar *toolBar = toolbars.at(i);
1588 if (toolBar->parentWidget() == this
1589 && (!d->layout->layoutState.toolBarAreaLayout.indexOf(toolBar).isEmpty()
1590 || (unifiedTitleAndToolBarOnMac()
1591 && toolBarArea(toolBar) == Qt::TopToolBarArea))) {
1592 menu->addAction(toolbars.at(i)->toggleViewAction());
1593 }
1594 }
1595 }
1596#endif
1597 Q_UNUSED(d);
1598 return menu;
1599}
1600#endif // QT_NO_MENU
1601
1602QT_END_NAMESPACE
1603
1604#endif // QT_NO_MAINWINDOW
Note: See TracBrowser for help on using the repository browser.