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

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

trunk: Merged in qt 4.6.1 sources.

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