1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qmainwindowlayout_p.h"
43 #include "qdockarealayout_p.h"
44
45 #ifndef QT_NO_MAINWINDOW
46 #include "qdockwidget.h"
47 #include "qdockwidget_p.h"
48 #include "qtoolbar_p.h"
49 #include "qmainwindow.h"
50 #include "qmainwindowlayout_p.h"
51 #include "qtoolbar.h"
52 #include "qtoolbarlayout_p.h"
53 #include "qwidgetanimator_p.h"
54 #include "qrubberband.h"
55 #include "qdockwidget_p.h"
56 #include "qtabbar_p.h"
57
58 #include <qapplication.h>
59 #include <qstatusbar.h>
60 #include <qstring.h>
61 #include <qstyle.h>
62 #include <qvarlengtharray.h>
63 #include <qstack.h>
64 #include <qmap.h>
65 #include <qtimer.h>
66
67 #include <qdebug.h>
68
69 #include <private/qapplication_p.h>
70 #include <private/qlayoutengine_p.h>
71 #ifdef Q_WS_MAC
72 # include <private/qcore_mac_p.h>
73 # include <private/qt_cocoa_helpers_mac_p.h>
74 #endif
75
76 #ifdef QT_NO_DOCKWIDGET
77 extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
78 #endif
79
80 #ifdef Q_DEBUG_MAINWINDOW_LAYOUT
81 # include <QTextStream>
82 #endif
83
84 QT_BEGIN_NAMESPACE
85
86 /******************************************************************************
87 ** debug
88 */
89
90 #if defined(Q_DEBUG_MAINWINDOW_LAYOUT) && !defined(QT_NO_DOCKWIDGET)
91
92 static QTextStream qout(stderr, QIODevice::WriteOnly);
93
94 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent);
95
dumpLayout(QTextStream & qout,const QDockAreaLayoutItem & item,QString indent)96 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QString indent)
97 {
98 qout << indent << "QDockAreaLayoutItem: "
99 << "pos: " << item.pos << " size:" << item.size
100 << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
101 << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) << '\n';
102 indent += QLatin1String(" ");
103 if (item.widgetItem != 0) {
104 qout << indent << "widget: "
105 << item.widgetItem->widget()->metaObject()->className()
106 << ' ' << item.widgetItem->widget()->windowTitle() << '\n';
107 } else if (item.subinfo != 0) {
108 qout << indent << "subinfo:\n";
109 dumpLayout(qout, *item.subinfo, indent + QLatin1String(" "));
110 } else if (item.placeHolderItem != 0) {
111 QRect r = item.placeHolderItem->topLevelRect;
112 qout << indent << "placeHolder: "
113 << "pos: " << item.pos << " size:" << item.size
114 << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
115 << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize)
116 << " objectName:" << item.placeHolderItem->objectName
117 << " hidden:" << item.placeHolderItem->hidden
118 << " window:" << item.placeHolderItem->window
119 << " rect:" << r.x() << ',' << r.y() << ' '
120 << r.width() << 'x' << r.height() << '\n';
121 }
122 qout.flush();
123 }
124
dumpLayout(QTextStream & qout,const QDockAreaLayoutInfo & layout,QString indent)125 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent)
126 {
127 qout << indent << "QDockAreaLayoutInfo: "
128 << layout.rect.left() << ','
129 << layout.rect.top() << ' '
130 << layout.rect.width() << 'x'
131 << layout.rect.height()
132 << " orient:" << layout.o
133 << " tabbed:" << layout.tabbed
134 << " tbshape:" << layout.tabBarShape << '\n';
135
136 indent += QLatin1String(" ");
137
138 for (int i = 0; i < layout.item_list.count(); ++i) {
139 qout << indent << "Item: " << i << '\n';
140 dumpLayout(qout, layout.item_list.at(i), indent + QLatin1String(" "));
141 }
142 qout.flush();
143 };
144
dumpLayout(QTextStream & qout,const QDockAreaLayout & layout,QString indent)145 static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout, QString indent)
146 {
147 qout << indent << "QDockAreaLayout: "
148 << layout.rect.left() << ','
149 << layout.rect.top() << ' '
150 << layout.rect.width() << 'x'
151 << layout.rect.height() << '\n';
152
153 qout << indent << "TopDockArea:\n";
154 dumpLayout(qout, layout.docks[QInternal::TopDock], indent + QLatin1String(" "));
155 qout << indent << "LeftDockArea:\n";
156 dumpLayout(qout, layout.docks[QInternal::LeftDock], indent + QLatin1String(" "));
157 qout << indent << "RightDockArea:\n";
158 dumpLayout(qout, layout.docks[QInternal::RightDock], indent + QLatin1String(" "));
159 qout << indent << "BottomDockArea:\n";
160 dumpLayout(qout, layout.docks[QInternal::BottomDock], indent + QLatin1String(" "));
161
162 qout.flush();
163 };
164
qt_dumpLayout(QTextStream & qout,QMainWindow * window)165 void qt_dumpLayout(QTextStream &qout, QMainWindow *window)
166 {
167 QMainWindowLayout *layout = qt_mainwindow_layout(window);
168 dumpLayout(qout, layout->layoutState.dockAreaLayout, QString());
169 }
170
171 #endif // Q_DEBUG_MAINWINDOW_LAYOUT && !QT_NO_DOCKWIDGET
172
173 /******************************************************************************
174 ** QMainWindowLayoutState
175 */
176
177 // we deal with all the #ifndefferry here so QMainWindowLayout code is clean
178
QMainWindowLayoutState(QMainWindow * win)179 QMainWindowLayoutState::QMainWindowLayoutState(QMainWindow *win)
180 :
181 #ifndef QT_NO_TOOLBAR
182 toolBarAreaLayout(win),
183 #endif
184 #ifndef QT_NO_DOCKWIDGET
185 dockAreaLayout(win)
186 #else
187 centralWidgetItem(0)
188 #endif
189
190 {
191 mainWindow = win;
192 }
193
sizeHint() const194 QSize QMainWindowLayoutState::sizeHint() const
195 {
196
197 QSize result(0, 0);
198
199 #ifndef QT_NO_DOCKWIDGET
200 result = dockAreaLayout.sizeHint();
201 #else
202 if (centralWidgetItem != 0)
203 result = centralWidgetItem->sizeHint();
204 #endif
205
206 #ifndef QT_NO_TOOLBAR
207 result = toolBarAreaLayout.sizeHint(result);
208 #endif // QT_NO_TOOLBAR
209
210 return result;
211 }
212
minimumSize() const213 QSize QMainWindowLayoutState::minimumSize() const
214 {
215 QSize result(0, 0);
216
217 #ifndef QT_NO_DOCKWIDGET
218 result = dockAreaLayout.minimumSize();
219 #else
220 if (centralWidgetItem != 0)
221 result = centralWidgetItem->minimumSize();
222 #endif
223
224 #ifndef QT_NO_TOOLBAR
225 result = toolBarAreaLayout.minimumSize(result);
226 #endif // QT_NO_TOOLBAR
227
228 return result;
229 }
230
apply(bool animated)231 void QMainWindowLayoutState::apply(bool animated)
232 {
233 #ifndef QT_NO_TOOLBAR
234 toolBarAreaLayout.apply(animated);
235 #endif
236
237 #ifndef QT_NO_DOCKWIDGET
238 // dumpLayout(dockAreaLayout, QString());
239 dockAreaLayout.apply(animated);
240 #else
241 if (centralWidgetItem != 0) {
242 QMainWindowLayout *layout = qt_mainwindow_layout(mainWindow);
243 Q_ASSERT(layout != 0);
244 layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
245 }
246 #endif
247 }
248
fitLayout()249 void QMainWindowLayoutState::fitLayout()
250 {
251 QRect r;
252 #ifdef QT_NO_TOOLBAR
253 r = rect;
254 #else
255 toolBarAreaLayout.rect = rect;
256 r = toolBarAreaLayout.fitLayout();
257 #endif // QT_NO_TOOLBAR
258
259 #ifndef QT_NO_DOCKWIDGET
260 dockAreaLayout.rect = r;
261 dockAreaLayout.fitLayout();
262 #else
263 centralWidgetRect = r;
264 #endif
265 }
266
deleteAllLayoutItems()267 void QMainWindowLayoutState::deleteAllLayoutItems()
268 {
269 #ifndef QT_NO_TOOLBAR
270 toolBarAreaLayout.deleteAllLayoutItems();
271 #endif
272
273 #ifndef QT_NO_DOCKWIDGET
274 dockAreaLayout.deleteAllLayoutItems();
275 #endif
276 }
277
deleteCentralWidgetItem()278 void QMainWindowLayoutState::deleteCentralWidgetItem()
279 {
280 #ifndef QT_NO_DOCKWIDGET
281 delete dockAreaLayout.centralWidgetItem;
282 dockAreaLayout.centralWidgetItem = 0;
283 #else
284 delete centralWidgetItem;
285 centralWidgetItem = 0;
286 #endif
287 }
288
itemAt(int index,int * x) const289 QLayoutItem *QMainWindowLayoutState::itemAt(int index, int *x) const
290 {
291 #ifndef QT_NO_TOOLBAR
292 if (QLayoutItem *ret = toolBarAreaLayout.itemAt(x, index))
293 return ret;
294 #endif
295
296 #ifndef QT_NO_DOCKWIDGET
297 if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index))
298 return ret;
299 #else
300 if (centralWidgetItem != 0 && (*x)++ == index)
301 return centralWidgetItem;
302 #endif
303
304 return 0;
305 }
306
takeAt(int index,int * x)307 QLayoutItem *QMainWindowLayoutState::takeAt(int index, int *x)
308 {
309 #ifndef QT_NO_TOOLBAR
310 if (QLayoutItem *ret = toolBarAreaLayout.takeAt(x, index))
311 return ret;
312 #endif
313
314 #ifndef QT_NO_DOCKWIDGET
315 if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index))
316 return ret;
317 #else
318 if (centralWidgetItem != 0 && (*x)++ == index) {
319 QLayoutItem *ret = centralWidgetItem;
320 centralWidgetItem = 0;
321 return ret;
322 }
323 #endif
324
325 return 0;
326 }
327
indexOf(QWidget * widget) const328 QList<int> QMainWindowLayoutState::indexOf(QWidget *widget) const
329 {
330 QList<int> result;
331
332 #ifndef QT_NO_TOOLBAR
333 // is it a toolbar?
334 if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
335 result = toolBarAreaLayout.indexOf(toolBar);
336 if (!result.isEmpty())
337 result.prepend(0);
338 return result;
339 }
340 #endif
341
342 #ifndef QT_NO_DOCKWIDGET
343 // is it a dock widget?
344 if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget)) {
345 result = dockAreaLayout.indexOf(dockWidget);
346 if (!result.isEmpty())
347 result.prepend(1);
348 return result;
349 }
350 #endif //QT_NO_DOCKWIDGET
351
352 return result;
353 }
354
contains(QWidget * widget) const355 bool QMainWindowLayoutState::contains(QWidget *widget) const
356 {
357 #ifndef QT_NO_DOCKWIDGET
358 if (dockAreaLayout.centralWidgetItem != 0 && dockAreaLayout.centralWidgetItem->widget() == widget)
359 return true;
360 if (!dockAreaLayout.indexOf(widget).isEmpty())
361 return true;
362 #else
363 if (centralWidgetItem != 0 && centralWidgetItem->widget() == widget)
364 return true;
365 #endif
366
367 #ifndef QT_NO_TOOLBAR
368 if (!toolBarAreaLayout.indexOf(widget).isEmpty())
369 return true;
370 #endif
371 return false;
372 }
373
setCentralWidget(QWidget * widget)374 void QMainWindowLayoutState::setCentralWidget(QWidget *widget)
375 {
376 QLayoutItem *item = 0;
377 //make sure we remove the widget
378 deleteCentralWidgetItem();
379
380 if (widget != 0)
381 item = new QWidgetItemV2(widget);
382
383 #ifndef QT_NO_DOCKWIDGET
384 dockAreaLayout.centralWidgetItem = item;
385 #else
386 centralWidgetItem = item;
387 #endif
388 }
389
centralWidget() const390 QWidget *QMainWindowLayoutState::centralWidget() const
391 {
392 QLayoutItem *item = 0;
393
394 #ifndef QT_NO_DOCKWIDGET
395 item = dockAreaLayout.centralWidgetItem;
396 #else
397 item = centralWidgetItem;
398 #endif
399
400 if (item != 0)
401 return item->widget();
402 return 0;
403 }
404
gapIndex(QWidget * widget,const QPoint & pos) const405 QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
406 const QPoint &pos) const
407 {
408 QList<int> result;
409
410 #ifndef QT_NO_TOOLBAR
411 // is it a toolbar?
412 if (qobject_cast<QToolBar*>(widget) != 0) {
413 result = toolBarAreaLayout.gapIndex(pos);
414 if (!result.isEmpty())
415 result.prepend(0);
416 return result;
417 }
418 #endif
419
420 #ifndef QT_NO_DOCKWIDGET
421 // is it a dock widget?
422 if (qobject_cast<QDockWidget *>(widget) != 0) {
423 result = dockAreaLayout.gapIndex(pos);
424 if (!result.isEmpty())
425 result.prepend(1);
426 return result;
427 }
428 #endif //QT_NO_DOCKWIDGET
429
430 return result;
431 }
432
insertGap(const QList<int> & path,QLayoutItem * item)433 bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item)
434 {
435 if (path.isEmpty())
436 return false;
437
438 int i = path.first();
439
440 #ifndef QT_NO_TOOLBAR
441 if (i == 0) {
442 Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0);
443 return toolBarAreaLayout.insertGap(path.mid(1), item);
444 }
445 #endif
446
447 #ifndef QT_NO_DOCKWIDGET
448 if (i == 1) {
449 Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0);
450 return dockAreaLayout.insertGap(path.mid(1), item);
451 }
452 #endif //QT_NO_DOCKWIDGET
453
454 return false;
455 }
456
remove(const QList<int> & path)457 void QMainWindowLayoutState::remove(const QList<int> &path)
458 {
459 int i = path.first();
460
461 #ifndef QT_NO_TOOLBAR
462 if (i == 0)
463 toolBarAreaLayout.remove(path.mid(1));
464 #endif
465
466 #ifndef QT_NO_DOCKWIDGET
467 if (i == 1)
468 dockAreaLayout.remove(path.mid(1));
469 #endif //QT_NO_DOCKWIDGET
470 }
471
remove(QLayoutItem * item)472 void QMainWindowLayoutState::remove(QLayoutItem *item)
473 {
474 #ifndef QT_NO_TOOLBAR
475 toolBarAreaLayout.remove(item);
476 #endif
477
478 #ifndef QT_NO_DOCKWIDGET
479 // is it a dock widget?
480 if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(item->widget())) {
481 QList<int> path = dockAreaLayout.indexOf(dockWidget);
482 if (!path.isEmpty())
483 dockAreaLayout.remove(path);
484 }
485 #endif //QT_NO_DOCKWIDGET
486 }
487
clear()488 void QMainWindowLayoutState::clear()
489 {
490 #ifndef QT_NO_TOOLBAR
491 toolBarAreaLayout.clear();
492 #endif
493
494 #ifndef QT_NO_DOCKWIDGET
495 dockAreaLayout.clear();
496 #else
497 centralWidgetRect = QRect();
498 #endif
499
500 rect = QRect();
501 }
502
isValid() const503 bool QMainWindowLayoutState::isValid() const
504 {
505 return rect.isValid();
506 }
507
item(const QList<int> & path)508 QLayoutItem *QMainWindowLayoutState::item(const QList<int> &path)
509 {
510 int i = path.first();
511
512 #ifndef QT_NO_TOOLBAR
513 if (i == 0) {
514 const QToolBarAreaLayoutItem *tbItem = toolBarAreaLayout.item(path.mid(1));
515 Q_ASSERT(tbItem);
516 return tbItem->widgetItem;
517 }
518 #endif
519
520 #ifndef QT_NO_DOCKWIDGET
521 if (i == 1)
522 return dockAreaLayout.item(path.mid(1)).widgetItem;
523 #endif //QT_NO_DOCKWIDGET
524
525 return 0;
526 }
527
itemRect(const QList<int> & path) const528 QRect QMainWindowLayoutState::itemRect(const QList<int> &path) const
529 {
530 int i = path.first();
531
532 #ifndef QT_NO_TOOLBAR
533 if (i == 0)
534 return toolBarAreaLayout.itemRect(path.mid(1));
535 #endif
536
537 #ifndef QT_NO_DOCKWIDGET
538 if (i == 1)
539 return dockAreaLayout.itemRect(path.mid(1));
540 #endif //QT_NO_DOCKWIDGET
541
542 return QRect();
543 }
544
gapRect(const QList<int> & path) const545 QRect QMainWindowLayoutState::gapRect(const QList<int> &path) const
546 {
547 int i = path.first();
548
549 #ifndef QT_NO_TOOLBAR
550 if (i == 0)
551 return toolBarAreaLayout.itemRect(path.mid(1));
552 #endif
553
554 #ifndef QT_NO_DOCKWIDGET
555 if (i == 1)
556 return dockAreaLayout.gapRect(path.mid(1));
557 #endif //QT_NO_DOCKWIDGET
558
559 return QRect();
560 }
561
plug(const QList<int> & path)562 QLayoutItem *QMainWindowLayoutState::plug(const QList<int> &path)
563 {
564 int i = path.first();
565
566 #ifndef QT_NO_TOOLBAR
567 if (i == 0)
568 return toolBarAreaLayout.plug(path.mid(1));
569 #endif
570
571 #ifndef QT_NO_DOCKWIDGET
572 if (i == 1)
573 return dockAreaLayout.plug(path.mid(1));
574 #endif //QT_NO_DOCKWIDGET
575
576 return 0;
577 }
578
unplug(const QList<int> & path,QMainWindowLayoutState * other)579 QLayoutItem *QMainWindowLayoutState::unplug(const QList<int> &path, QMainWindowLayoutState *other)
580 {
581 int i = path.first();
582
583 #ifdef QT_NO_TOOLBAR
584 Q_UNUSED(other);
585 #else
586 if (i == 0)
587 return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : 0);
588 #endif
589
590 #ifndef QT_NO_DOCKWIDGET
591 if (i == 1)
592 return dockAreaLayout.unplug(path.mid(1));
593 #endif //QT_NO_DOCKWIDGET
594
595 return 0;
596 }
597
saveState(QDataStream & stream) const598 void QMainWindowLayoutState::saveState(QDataStream &stream) const
599 {
600 #ifndef QT_NO_DOCKWIDGET
601 dockAreaLayout.saveState(stream);
602 #endif
603 #ifndef QT_NO_TOOLBAR
604 toolBarAreaLayout.saveState(stream);
605 #endif
606 }
607
608 template <typename T>
findChildrenHelper(const QObject * o)609 static QList<T> findChildrenHelper(const QObject *o)
610 {
611 const QObjectList &list = o->children();
612 QList<T> result;
613
614 for (int i=0; i < list.size(); ++i) {
615 if (T t = qobject_cast<T>(list[i])) {
616 result.append(t);
617 }
618 }
619
620 return result;
621 }
622
623 //pre4.3 tests the format that was used before 4.3
checkFormat(QDataStream & stream,bool pre43)624 bool QMainWindowLayoutState::checkFormat(QDataStream &stream, bool pre43)
625 {
626 #ifdef QT_NO_TOOLBAR
627 Q_UNUSED(pre43);
628 #endif
629 while (!stream.atEnd()) {
630 uchar marker;
631 stream >> marker;
632 switch(marker)
633 {
634 #ifndef QT_NO_TOOLBAR
635 case QToolBarAreaLayout::ToolBarStateMarker:
636 case QToolBarAreaLayout::ToolBarStateMarkerEx:
637 {
638 QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
639 if (!toolBarAreaLayout.restoreState(stream, toolBars, marker,
640 pre43 /*testing 4.3 format*/, true /*testing*/)) {
641 return false;
642 }
643 }
644 break;
645 #endif // QT_NO_TOOLBAR
646
647 #ifndef QT_NO_DOCKWIDGET
648 case QDockAreaLayout::DockWidgetStateMarker:
649 {
650 QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
651 if (!dockAreaLayout.restoreState(stream, dockWidgets, true /*testing*/)) {
652 return false;
653 }
654 }
655 break;
656 #endif
657 default:
658 //there was an error during the parsing
659 return false;
660 }// switch
661 } //while
662
663 //everything went fine: it must be a pre-4.3 saved state
664 return true;
665 }
666
restoreState(QDataStream & _stream,const QMainWindowLayoutState & oldState)667 bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
668 const QMainWindowLayoutState &oldState)
669 {
670 //make a copy of the data so that we can read it more than once
671 QByteArray copy;
672 while(!_stream.atEnd()) {
673 int length = 1024;
674 QByteArray ba(length, '\0');
675 length = _stream.readRawData(ba.data(), ba.size());
676 ba.resize(length);
677 copy += ba;
678 }
679
680 QDataStream ds(copy);
681 const bool oldFormat = !checkFormat(ds, false);
682 if (oldFormat) {
683 //we should try with the old format
684 QDataStream ds2(copy);
685 if (!checkFormat(ds2, true)) {
686 return false; //format unknown
687 }
688 }
689
690 QDataStream stream(copy);
691
692 while (!stream.atEnd()) {
693 uchar marker;
694 stream >> marker;
695 switch(marker)
696 {
697 #ifndef QT_NO_DOCKWIDGET
698 case QDockAreaLayout::DockWidgetStateMarker:
699 {
700 QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
701 if (!dockAreaLayout.restoreState(stream, dockWidgets))
702 return false;
703
704 for (int i = 0; i < dockWidgets.size(); ++i) {
705 QDockWidget *w = dockWidgets.at(i);
706 QList<int> path = dockAreaLayout.indexOf(w);
707 if (path.isEmpty()) {
708 QList<int> oldPath = oldState.dockAreaLayout.indexOf(w);
709 if (oldPath.isEmpty()) {
710 continue;
711 }
712 QDockAreaLayoutInfo *info = dockAreaLayout.info(oldPath);
713 if (info == 0) {
714 continue;
715 }
716 info->item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(w)));
717 }
718 }
719 }
720 break;
721 #endif // QT_NO_DOCKWIDGET
722
723 #ifndef QT_NO_TOOLBAR
724 case QToolBarAreaLayout::ToolBarStateMarker:
725 case QToolBarAreaLayout::ToolBarStateMarkerEx:
726 {
727 QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
728 if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, oldFormat))
729 return false;
730
731 for (int i = 0; i < toolBars.size(); ++i) {
732 QToolBar *w = toolBars.at(i);
733 QList<int> path = toolBarAreaLayout.indexOf(w);
734 if (path.isEmpty()) {
735 QList<int> oldPath = oldState.toolBarAreaLayout.indexOf(w);
736 if (oldPath.isEmpty()) {
737 continue;
738 }
739 toolBarAreaLayout.docks[oldPath.at(0)].insertToolBar(0, w);
740 }
741 }
742 }
743 break;
744 #endif //QT_NO_TOOLBAR
745 default:
746 return false;
747 }// switch
748 } //while
749
750
751 return true;
752 }
753
754 /******************************************************************************
755 ** QMainWindowLayoutState - toolbars
756 */
757
758 #ifndef QT_NO_TOOLBAR
759
validateToolBarArea(Qt::ToolBarArea & area)760 static inline void validateToolBarArea(Qt::ToolBarArea &area)
761 {
762 switch (area) {
763 case Qt::LeftToolBarArea:
764 case Qt::RightToolBarArea:
765 case Qt::TopToolBarArea:
766 case Qt::BottomToolBarArea:
767 break;
768 default:
769 area = Qt::TopToolBarArea;
770 }
771 }
772
toDockPos(Qt::ToolBarArea area)773 static QInternal::DockPosition toDockPos(Qt::ToolBarArea area)
774 {
775 switch (area) {
776 case Qt::LeftToolBarArea: return QInternal::LeftDock;
777 case Qt::RightToolBarArea: return QInternal::RightDock;
778 case Qt::TopToolBarArea: return QInternal::TopDock;
779 case Qt::BottomToolBarArea: return QInternal::BottomDock;
780 default:
781 break;
782 }
783
784 return QInternal::DockCount;
785 }
786
toToolBarArea(QInternal::DockPosition pos)787 static Qt::ToolBarArea toToolBarArea(QInternal::DockPosition pos)
788 {
789 switch (pos) {
790 case QInternal::LeftDock: return Qt::LeftToolBarArea;
791 case QInternal::RightDock: return Qt::RightToolBarArea;
792 case QInternal::TopDock: return Qt::TopToolBarArea;
793 case QInternal::BottomDock: return Qt::BottomToolBarArea;
794 default: break;
795 }
796 return Qt::NoToolBarArea;
797 }
798
toToolBarArea(int pos)799 static inline Qt::ToolBarArea toToolBarArea(int pos)
800 {
801 return toToolBarArea(static_cast<QInternal::DockPosition>(pos));
802 }
803
addToolBarBreak(Qt::ToolBarArea area)804 void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area)
805 {
806 validateToolBarArea(area);
807
808 layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
809 if (savedState.isValid())
810 savedState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
811
812 invalidate();
813 }
814
insertToolBarBreak(QToolBar * before)815 void QMainWindowLayout::insertToolBarBreak(QToolBar *before)
816 {
817 layoutState.toolBarAreaLayout.insertToolBarBreak(before);
818 if (savedState.isValid())
819 savedState.toolBarAreaLayout.insertToolBarBreak(before);
820 invalidate();
821 }
822
removeToolBarBreak(QToolBar * before)823 void QMainWindowLayout::removeToolBarBreak(QToolBar *before)
824 {
825 layoutState.toolBarAreaLayout.removeToolBarBreak(before);
826 if (savedState.isValid())
827 savedState.toolBarAreaLayout.removeToolBarBreak(before);
828 invalidate();
829 }
830
moveToolBar(QToolBar * toolbar,int pos)831 void QMainWindowLayout::moveToolBar(QToolBar *toolbar, int pos)
832 {
833 layoutState.toolBarAreaLayout.moveToolBar(toolbar, pos);
834 if (savedState.isValid())
835 savedState.toolBarAreaLayout.moveToolBar(toolbar, pos);
836 invalidate();
837 }
838
839 /* Removes the toolbar from the mainwindow so that it can be added again. Does not
840 explicitly hide the toolbar. */
removeToolBar(QToolBar * toolbar)841 void QMainWindowLayout::removeToolBar(QToolBar *toolbar)
842 {
843 if (toolbar) {
844 QObject::disconnect(parentWidget(), SIGNAL(iconSizeChanged(QSize)),
845 toolbar, SLOT(_q_updateIconSize(QSize)));
846 QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
847 toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
848
849 #ifdef Q_WS_MAC
850 if (usesHIToolBar(toolbar)) {
851 removeFromMacToolbar(toolbar);
852 } else
853 #endif // Q_WS_MAC
854 {
855 removeWidget(toolbar);
856 }
857 }
858 }
859
860 /*!
861 Adds \a toolbar to \a area, continuing the current line.
862 */
addToolBar(Qt::ToolBarArea area,QToolBar * toolbar,bool)863 void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
864 QToolBar *toolbar,
865 bool)
866 {
867 validateToolBarArea(area);
868 #ifdef Q_WS_MAC
869 if ((area == Qt::TopToolBarArea)
870 && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
871 insertIntoMacToolbar(0, toolbar);
872 } else
873 #endif
874 {
875 //let's add the toolbar to the layout
876 addChildWidget(toolbar);
877 QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
878 if (savedState.isValid() && item) {
879 // copy the toolbar also in the saved state
880 savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
881 }
882 invalidate();
883
884 //this ensures that the toolbar has the right window flags (not floating any more)
885 toolbar->d_func()->updateWindowFlags(false /*floating*/);
886 }
887 }
888
889 /*!
890 Adds \a toolbar before \a before
891 */
insertToolBar(QToolBar * before,QToolBar * toolbar)892 void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
893 {
894 #ifdef Q_WS_MAC
895 if (usesHIToolBar(before)) {
896 insertIntoMacToolbar(before, toolbar);
897 } else
898 #endif // Q_WS_MAC
899 {
900 addChildWidget(toolbar);
901 QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
902 if (savedState.isValid() && item) {
903 // copy the toolbar also in the saved state
904 savedState.toolBarAreaLayout.insertItem(before, item);
905 }
906 if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
907 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
908 if (!currentGapPos.isEmpty()) {
909 currentGapPos.prepend(0);
910 currentGapRect = layoutState.itemRect(currentGapPos);
911 }
912 }
913 invalidate();
914 }
915 }
916
toolBarArea(QToolBar * toolbar) const917 Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const
918 {
919 QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar);
920 switch (pos) {
921 case QInternal::LeftDock: return Qt::LeftToolBarArea;
922 case QInternal::RightDock: return Qt::RightToolBarArea;
923 case QInternal::TopDock: return Qt::TopToolBarArea;
924 case QInternal::BottomDock: return Qt::BottomToolBarArea;
925 default: break;
926 }
927 #ifdef Q_WS_MAC
928 if (pos == QInternal::DockCount) {
929 if (qtoolbarsInUnifiedToolbarList.contains(toolbar))
930 return Qt::TopToolBarArea;
931 }
932 #endif
933 return Qt::NoToolBarArea;
934 }
935
toolBarBreak(QToolBar * toolBar) const936 bool QMainWindowLayout::toolBarBreak(QToolBar *toolBar) const
937 {
938 return layoutState.toolBarAreaLayout.toolBarBreak(toolBar);
939 }
940
getStyleOptionInfo(QStyleOptionToolBar * option,QToolBar * toolBar) const941 void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const
942 {
943 option->toolBarArea = toolBarArea(toolBar);
944 layoutState.toolBarAreaLayout.getStyleOptionInfo(option, toolBar);
945 }
946
toggleToolBarsVisible()947 void QMainWindowLayout::toggleToolBarsVisible()
948 {
949 bool updateNonUnifiedParts = true;
950 #ifdef Q_WS_MAC
951 if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
952 // If we hit this case, someone has pressed the "toolbar button" which will
953 // toggle the unified toolbar visibility, because that's what the user wants.
954 // We might be in a situation where someone has hidden all the toolbars
955 // beforehand (maybe in construction), but now they've hit this button and
956 // and are expecting the items to show. What do we do?
957 // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this
958 // preserves what people would expect (these toolbars were visible when I clicked last time).
959 // 2) If NONE are visible, then show them all. Again, this preserves the user expectation
960 // of, "I want to see the toolbars." The user may get more toolbars than expected, but this
961 // is better seeing nothing.
962 // Don't worry about any of this if we are going invisible. This does mean we may get
963 // into issues when switching into and out of fullscreen mode, but this is probably minor.
964 // If we ever need to do hiding, that would have to be taken care of after the unified toolbar
965 // has finished hiding.
966 // People can of course handle the QEvent::ToolBarChange event themselves and do
967 // WHATEVER they want if they don't like what we are doing (though the unified toolbar
968 // will fire regardless).
969
970 // Check if we REALLY need to update the geometry below. If we only have items in the
971 // unified toolbar, all the docks will be empty, so there's very little point
972 // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well).
973 // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar
974 // visibility can get out of sync. I really don't think it's a big issue. It is kept
975 // to a minimum because we only change the visibility if we absolutely must.
976 // update the "non unified parts."
977 updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty();
978
979 // We get this function before the unified toolbar does its thing.
980 // So, the value will be opposite of what we expect.
981 bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow));
982 if (goingVisible) {
983 const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size();
984 bool needAllVisible = true;
985 for (int i = 0; i < ToolBarCount; ++i) {
986 if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) {
987 needAllVisible = false;
988 break;
989 }
990 }
991 if (needAllVisible) {
992 QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because
993 // the toggle has already happened.
994 for (int i = 0; i < ToolBarCount; ++i)
995 qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true);
996 }
997 }
998 if (!updateNonUnifiedParts)
999 layoutState.toolBarAreaLayout.visible = goingVisible;
1000 }
1001 #endif
1002 if (updateNonUnifiedParts) {
1003 layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
1004 if (!layoutState.mainWindow->isMaximized()) {
1005 QPoint topLeft = parentWidget()->geometry().topLeft();
1006 QRect r = parentWidget()->geometry();
1007 r = layoutState.toolBarAreaLayout.rectHint(r);
1008 r.moveTo(topLeft);
1009 parentWidget()->setGeometry(r);
1010 } else {
1011 update();
1012 }
1013 }
1014 }
1015
1016 #endif // QT_NO_TOOLBAR
1017
1018 /******************************************************************************
1019 ** QMainWindowLayoutState - dock areas
1020 */
1021
1022 #ifndef QT_NO_DOCKWIDGET
1023
validateDockWidgetArea(Qt::DockWidgetArea & area)1024 static inline void validateDockWidgetArea(Qt::DockWidgetArea &area)
1025 {
1026 switch (area) {
1027 case Qt::LeftDockWidgetArea:
1028 case Qt::RightDockWidgetArea:
1029 case Qt::TopDockWidgetArea:
1030 case Qt::BottomDockWidgetArea:
1031 break;
1032 default:
1033 area = Qt::LeftDockWidgetArea;
1034 }
1035 }
1036
toDockPos(Qt::DockWidgetArea area)1037 static QInternal::DockPosition toDockPos(Qt::DockWidgetArea area)
1038 {
1039 switch (area) {
1040 case Qt::LeftDockWidgetArea: return QInternal::LeftDock;
1041 case Qt::RightDockWidgetArea: return QInternal::RightDock;
1042 case Qt::TopDockWidgetArea: return QInternal::TopDock;
1043 case Qt::BottomDockWidgetArea: return QInternal::BottomDock;
1044 default:
1045 break;
1046 }
1047
1048 return QInternal::DockCount;
1049 }
1050
toDockWidgetArea(QInternal::DockPosition pos)1051 static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
1052 {
1053 switch (pos) {
1054 case QInternal::LeftDock : return Qt::LeftDockWidgetArea;
1055 case QInternal::RightDock : return Qt::RightDockWidgetArea;
1056 case QInternal::TopDock : return Qt::TopDockWidgetArea;
1057 case QInternal::BottomDock : return Qt::BottomDockWidgetArea;
1058 default:
1059 break;
1060 }
1061
1062 return Qt::NoDockWidgetArea;
1063 }
1064
toDockWidgetArea(int pos)1065 inline static Qt::DockWidgetArea toDockWidgetArea(int pos)
1066 {
1067 return toDockWidgetArea(static_cast<QInternal::DockPosition>(pos));
1068 }
1069
setCorner(Qt::Corner corner,Qt::DockWidgetArea area)1070 void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
1071 {
1072 if (layoutState.dockAreaLayout.corners[corner] == area)
1073 return;
1074 layoutState.dockAreaLayout.corners[corner] = area;
1075 if (savedState.isValid())
1076 savedState.dockAreaLayout.corners[corner] = area;
1077 invalidate();
1078 }
1079
corner(Qt::Corner corner) const1080 Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner) const
1081 {
1082 return layoutState.dockAreaLayout.corners[corner];
1083 }
1084
addDockWidget(Qt::DockWidgetArea area,QDockWidget * dockwidget,Qt::Orientation orientation)1085 void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area,
1086 QDockWidget *dockwidget,
1087 Qt::Orientation orientation)
1088 {
1089 addChildWidget(dockwidget);
1090
1091 // If we are currently moving a separator, then we need to abort the move, since each
1092 // time we move the mouse layoutState is replaced by savedState modified by the move.
1093 if (!movingSeparator.isEmpty())
1094 endSeparatorMove(movingSeparatorPos);
1095
1096 layoutState.dockAreaLayout.addDockWidget(toDockPos(area), dockwidget, orientation);
1097 emit dockwidget->dockLocationChanged(area);
1098 invalidate();
1099 }
1100
tabifyDockWidget(QDockWidget * first,QDockWidget * second)1101 void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
1102 {
1103 addChildWidget(second);
1104 layoutState.dockAreaLayout.tabifyDockWidget(first, second);
1105 emit second->dockLocationChanged(dockWidgetArea(first));
1106 invalidate();
1107 }
1108
restoreDockWidget(QDockWidget * dockwidget)1109 bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget)
1110 {
1111 addChildWidget(dockwidget);
1112 if (!layoutState.dockAreaLayout.restoreDockWidget(dockwidget))
1113 return false;
1114 emit dockwidget->dockLocationChanged(dockWidgetArea(dockwidget));
1115 invalidate();
1116 return true;
1117 }
1118
1119 #ifndef QT_NO_TABBAR
documentMode() const1120 bool QMainWindowLayout::documentMode() const
1121 {
1122 return _documentMode;
1123 }
1124
setDocumentMode(bool enabled)1125 void QMainWindowLayout::setDocumentMode(bool enabled)
1126 {
1127 if (_documentMode == enabled)
1128 return;
1129
1130 _documentMode = enabled;
1131
1132 // Update the document mode for all tab bars
1133 foreach (QTabBar *bar, usedTabBars)
1134 bar->setDocumentMode(_documentMode);
1135 foreach (QTabBar *bar, unusedTabBars)
1136 bar->setDocumentMode(_documentMode);
1137 }
1138 #endif // QT_NO_TABBAR
1139
setVerticalTabsEnabled(bool enabled)1140 void QMainWindowLayout::setVerticalTabsEnabled(bool enabled)
1141 {
1142 #ifdef QT_NO_TABBAR
1143 Q_UNUSED(enabled);
1144 #else
1145 if (verticalTabsEnabled == enabled)
1146 return;
1147
1148 verticalTabsEnabled = enabled;
1149
1150 updateTabBarShapes();
1151 #endif // QT_NO_TABBAR
1152 }
1153
1154 #ifndef QT_NO_TABWIDGET
tabShape() const1155 QTabWidget::TabShape QMainWindowLayout::tabShape() const
1156 {
1157 return _tabShape;
1158 }
1159
setTabShape(QTabWidget::TabShape tabShape)1160 void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape)
1161 {
1162 if (_tabShape == tabShape)
1163 return;
1164
1165 _tabShape = tabShape;
1166
1167 updateTabBarShapes();
1168 }
1169
tabPosition(Qt::DockWidgetArea area) const1170 QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const
1171 {
1172 return tabPositions[toDockPos(area)];
1173 }
1174
setTabPosition(Qt::DockWidgetAreas areas,QTabWidget::TabPosition tabPosition)1175 void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
1176 {
1177 const Qt::DockWidgetArea dockWidgetAreas[] = {
1178 Qt::TopDockWidgetArea,
1179 Qt::LeftDockWidgetArea,
1180 Qt::BottomDockWidgetArea,
1181 Qt::RightDockWidgetArea
1182 };
1183 const QInternal::DockPosition dockPositions[] = {
1184 QInternal::TopDock,
1185 QInternal::LeftDock,
1186 QInternal::BottomDock,
1187 QInternal::RightDock
1188 };
1189
1190 for (int i = 0; i < QInternal::DockCount; ++i)
1191 if (areas & dockWidgetAreas[i])
1192 tabPositions[dockPositions[i]] = tabPosition;
1193
1194 updateTabBarShapes();
1195 }
1196
tabBarShapeFrom(QTabWidget::TabShape shape,QTabWidget::TabPosition position)1197 static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
1198 {
1199 const bool rounded = (shape == QTabWidget::Rounded);
1200 if (position == QTabWidget::North)
1201 return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
1202 if (position == QTabWidget::South)
1203 return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
1204 if (position == QTabWidget::East)
1205 return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
1206 if (position == QTabWidget::West)
1207 return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
1208 return QTabBar::RoundedNorth;
1209 }
1210 #endif // QT_NO_TABWIDGET
1211
1212 #ifndef QT_NO_TABBAR
updateTabBarShapes()1213 void QMainWindowLayout::updateTabBarShapes()
1214 {
1215 #ifndef QT_NO_TABWIDGET
1216 const QTabWidget::TabPosition vertical[] = {
1217 QTabWidget::West,
1218 QTabWidget::East,
1219 QTabWidget::North,
1220 QTabWidget::South
1221 };
1222 #else
1223 const QTabBar::Shape vertical[] = {
1224 QTabBar::RoundedWest,
1225 QTabBar::RoundedEast,
1226 QTabBar::RoundedNorth,
1227 QTabBar::RoundedSouth
1228 };
1229 #endif
1230
1231 QDockAreaLayout &layout = layoutState.dockAreaLayout;
1232
1233 for (int i = 0; i < QInternal::DockCount; ++i) {
1234 #ifndef QT_NO_TABWIDGET
1235 QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i];
1236 QTabBar::Shape shape = tabBarShapeFrom(_tabShape, pos);
1237 #else
1238 QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth;
1239 #endif
1240 layout.docks[i].setTabBarShape(shape);
1241 }
1242 }
1243 #endif // QT_NO_TABBAR
1244
splitDockWidget(QDockWidget * after,QDockWidget * dockwidget,Qt::Orientation orientation)1245 void QMainWindowLayout::splitDockWidget(QDockWidget *after,
1246 QDockWidget *dockwidget,
1247 Qt::Orientation orientation)
1248 {
1249 addChildWidget(dockwidget);
1250 layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation);
1251 emit dockwidget->dockLocationChanged(dockWidgetArea(after));
1252 invalidate();
1253 }
1254
dockWidgetArea(QDockWidget * widget) const1255 Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QDockWidget *widget) const
1256 {
1257 QList<int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget);
1258 if (pathToWidget.isEmpty())
1259 return Qt::NoDockWidgetArea;
1260 return toDockWidgetArea(pathToWidget.first());
1261 }
1262
keepSize(QDockWidget * w)1263 void QMainWindowLayout::keepSize(QDockWidget *w)
1264 {
1265 layoutState.dockAreaLayout.keepSize(w);
1266 }
1267
1268 #ifndef QT_NO_TABBAR
1269
1270 class QMainWindowTabBar : public QTabBar
1271 {
1272 public:
1273 QMainWindowTabBar(QWidget *parent);
1274 protected:
1275 bool event(QEvent *e);
1276 };
1277
QMainWindowTabBar(QWidget * parent)1278 QMainWindowTabBar::QMainWindowTabBar(QWidget *parent)
1279 : QTabBar(parent)
1280 {
1281 setExpanding(false);
1282 }
1283
event(QEvent * e)1284 bool QMainWindowTabBar::event(QEvent *e)
1285 {
1286 // show the tooltip if tab is too small to fit label
1287
1288 if (e->type() != QEvent::ToolTip)
1289 return QTabBar::event(e);
1290 QSize size = this->size();
1291 QSize hint = sizeHint();
1292 if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
1293 size.transpose();
1294 hint.transpose();
1295 }
1296 if (size.width() < hint.width())
1297 return QTabBar::event(e);
1298 e->accept();
1299 return true;
1300 }
1301
getTabBar()1302 QTabBar *QMainWindowLayout::getTabBar()
1303 {
1304 QTabBar *result = 0;
1305 if (!unusedTabBars.isEmpty()) {
1306 result = unusedTabBars.takeLast();
1307 } else {
1308 result = new QMainWindowTabBar(parentWidget());
1309 result->setDrawBase(true);
1310 result->setElideMode(Qt::ElideRight);
1311 result->setDocumentMode(_documentMode);
1312 connect(result, SIGNAL(currentChanged(int)), this, SLOT(tabChanged()));
1313 }
1314
1315 usedTabBars.insert(result);
1316 return result;
1317 }
1318
1319 // Allocates a new separator widget if needed
getSeparatorWidget()1320 QWidget *QMainWindowLayout::getSeparatorWidget()
1321 {
1322 QWidget *result = 0;
1323 if (!unusedSeparatorWidgets.isEmpty()) {
1324 result = unusedSeparatorWidgets.takeLast();
1325 } else {
1326 result = new QWidget(parentWidget());
1327 result->setAttribute(Qt::WA_MouseNoMask, true);
1328 result->setAutoFillBackground(false);
1329 result->setObjectName(QLatin1String("qt_qmainwindow_extended_splitter"));
1330 }
1331 usedSeparatorWidgets.insert(result);
1332 return result;
1333 }
1334
tabChanged()1335 void QMainWindowLayout::tabChanged()
1336 {
1337 QTabBar *tb = qobject_cast<QTabBar*>(sender());
1338 if (tb == 0)
1339 return;
1340 QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(tb);
1341 if (info == 0)
1342 return;
1343 info->apply(false);
1344
1345 if (QWidget *w = centralWidget())
1346 w->raise();
1347 }
1348 #endif // QT_NO_TABBAR
1349
startSeparatorMove(const QPoint & pos)1350 bool QMainWindowLayout::startSeparatorMove(const QPoint &pos)
1351 {
1352 movingSeparator = layoutState.dockAreaLayout.findSeparator(pos);
1353
1354 if (movingSeparator.isEmpty())
1355 return false;
1356
1357 savedState = layoutState;
1358 movingSeparatorPos = movingSeparatorOrigin = pos;
1359
1360 return true;
1361 }
1362
separatorMove(const QPoint & pos)1363 bool QMainWindowLayout::separatorMove(const QPoint &pos)
1364 {
1365 if (movingSeparator.isEmpty())
1366 return false;
1367 movingSeparatorPos = pos;
1368 separatorMoveTimer.start(0, this);
1369 return true;
1370 }
1371
endSeparatorMove(const QPoint &)1372 bool QMainWindowLayout::endSeparatorMove(const QPoint&)
1373 {
1374 if (movingSeparator.isEmpty())
1375 return false;
1376 movingSeparator.clear();
1377 savedState.clear();
1378 return true;
1379 }
1380
raise(QDockWidget * widget)1381 void QMainWindowLayout::raise(QDockWidget *widget)
1382 {
1383 QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
1384 if (info == 0)
1385 return;
1386 #ifndef QT_NO_TABBAR
1387 if (!info->tabbed)
1388 return;
1389 info->setCurrentTab(widget);
1390 #endif
1391 }
1392
1393 #endif // QT_NO_DOCKWIDGET
1394
1395
1396 /******************************************************************************
1397 ** QMainWindowLayoutState - layout interface
1398 */
1399
count() const1400 int QMainWindowLayout::count() const
1401 {
1402 qWarning("QMainWindowLayout::count: ?");
1403 return 0; //#################################################
1404 }
1405
itemAt(int index) const1406 QLayoutItem *QMainWindowLayout::itemAt(int index) const
1407 {
1408 int x = 0;
1409
1410 if (QLayoutItem *ret = layoutState.itemAt(index, &x))
1411 return ret;
1412
1413 if (statusbar && x++ == index)
1414 return statusbar;
1415
1416 return 0;
1417 }
1418
takeAt(int index)1419 QLayoutItem *QMainWindowLayout::takeAt(int index)
1420 {
1421 int x = 0;
1422
1423 if (QLayoutItem *ret = layoutState.takeAt(index, &x)) {
1424 // the widget might in fact have been destroyed by now
1425 if (QWidget *w = ret->widget()) {
1426 widgetAnimator.abort(w);
1427 if (w == pluggingWidget)
1428 pluggingWidget = 0;
1429 }
1430
1431 if (savedState.isValid() ) {
1432 //we need to remove the item also from the saved state to prevent crash
1433 savedState.remove(ret);
1434 //Also, the item may be contained several times as a gap item.
1435 layoutState.remove(ret);
1436 }
1437
1438 #ifndef QT_NO_TOOLBAR
1439 if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
1440 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
1441 if (!currentGapPos.isEmpty()) {
1442 currentGapPos.prepend(0);
1443 currentGapRect = layoutState.itemRect(currentGapPos);
1444 }
1445 }
1446 #endif
1447
1448 return ret;
1449 }
1450
1451 if (statusbar && x++ == index) {
1452 QLayoutItem *ret = statusbar;
1453 statusbar = 0;
1454 return ret;
1455 }
1456
1457 return 0;
1458 }
1459
setGeometry(const QRect & _r)1460 void QMainWindowLayout::setGeometry(const QRect &_r)
1461 {
1462 if (savedState.isValid())
1463 return;
1464
1465 QRect r = _r;
1466
1467 QLayout::setGeometry(r);
1468
1469 if (statusbar) {
1470 QRect sbr(QPoint(0, 0),
1471 QSize(r.width(), statusbar->heightForWidth(r.width()))
1472 .expandedTo(statusbar->minimumSize()));
1473 sbr.moveBottom(r.bottom());
1474 QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr);
1475 statusbar->setGeometry(vr);
1476 r.setBottom(sbr.top() - 1);
1477 }
1478
1479 layoutState.rect = r;
1480 layoutState.fitLayout();
1481 applyState(layoutState, false);
1482 }
1483
addItem(QLayoutItem *)1484 void QMainWindowLayout::addItem(QLayoutItem *)
1485 { qWarning("QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); }
1486
sizeHint() const1487 QSize QMainWindowLayout::sizeHint() const
1488 {
1489 if (!szHint.isValid()) {
1490 szHint = layoutState.sizeHint();
1491 const QSize sbHint = statusbar ? statusbar->sizeHint() : QSize(0, 0);
1492 szHint = QSize(qMax(sbHint.width(), szHint.width()),
1493 sbHint.height() + szHint.height());
1494 }
1495 return szHint;
1496 }
1497
minimumSize() const1498 QSize QMainWindowLayout::minimumSize() const
1499 {
1500 if (!minSize.isValid()) {
1501 minSize = layoutState.minimumSize();
1502 const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0);
1503 minSize = QSize(qMax(sbMin.width(), minSize.width()),
1504 sbMin.height() + minSize.height());
1505 #ifdef Q_WS_MAC
1506 const QSize storedSize = minSize;
1507 int minWidth = 0;
1508 foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) {
1509 minWidth += toolbar->sizeHint().width() + 20;
1510 }
1511 minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height());
1512 #endif
1513 }
1514 return minSize;
1515 }
1516
invalidate()1517 void QMainWindowLayout::invalidate()
1518 {
1519 QLayout::invalidate();
1520 minSize = szHint = QSize();
1521 }
1522
1523 /******************************************************************************
1524 ** QMainWindowLayout - remaining stuff
1525 */
1526
fixToolBarOrientation(QLayoutItem * item,int dockPos)1527 static void fixToolBarOrientation(QLayoutItem *item, int dockPos)
1528 {
1529 #ifndef QT_NO_TOOLBAR
1530 QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget());
1531 if (toolBar == 0)
1532 return;
1533
1534 QRect oldGeo = toolBar->geometry();
1535
1536 QInternal::DockPosition pos
1537 = static_cast<QInternal::DockPosition>(dockPos);
1538 Qt::Orientation o = pos == QInternal::TopDock || pos == QInternal::BottomDock
1539 ? Qt::Horizontal : Qt::Vertical;
1540 if (o != toolBar->orientation())
1541 toolBar->setOrientation(o);
1542
1543 QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize())
1544 .expandedTo(toolBar->minimumSize());
1545
1546 if (toolBar->size() != hint) {
1547 QRect newGeo(oldGeo.topLeft(), hint);
1548 if (toolBar->layoutDirection() == Qt::RightToLeft)
1549 newGeo.moveRight(oldGeo.right());
1550 toolBar->setGeometry(newGeo);
1551 }
1552
1553 #else
1554 Q_UNUSED(item);
1555 Q_UNUSED(dockPos);
1556 #endif
1557 }
1558
revert(QLayoutItem * widgetItem)1559 void QMainWindowLayout::revert(QLayoutItem *widgetItem)
1560 {
1561 if (!savedState.isValid())
1562 return;
1563
1564 QWidget *widget = widgetItem->widget();
1565 layoutState = savedState;
1566 currentGapPos = layoutState.indexOf(widget);
1567 fixToolBarOrientation(widgetItem, currentGapPos.at(1));
1568 layoutState.unplug(currentGapPos);
1569 layoutState.fitLayout();
1570 currentGapRect = layoutState.itemRect(currentGapPos);
1571
1572 plug(widgetItem);
1573 }
1574
plug(QLayoutItem * widgetItem)1575 bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
1576 {
1577 if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty())
1578 return false;
1579
1580 fixToolBarOrientation(widgetItem, currentGapPos.at(1));
1581
1582 QWidget *widget = widgetItem->widget();
1583
1584 QList<int> previousPath = layoutState.indexOf(widget);
1585
1586 const QLayoutItem *it = layoutState.plug(currentGapPos);
1587 if (!it)
1588 return false;
1589 Q_ASSERT(it == widgetItem);
1590 if (!previousPath.isEmpty())
1591 layoutState.remove(previousPath);
1592
1593 pluggingWidget = widget;
1594 QRect globalRect = currentGapRect;
1595 globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
1596 #ifndef QT_NO_DOCKWIDGET
1597 if (qobject_cast<QDockWidget*>(widget) != 0) {
1598 QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
1599 if (layout->nativeWindowDeco()) {
1600 globalRect.adjust(0, layout->titleHeight(), 0, 0);
1601 } else {
1602 int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget);
1603 globalRect.adjust(-fw, -fw, fw, fw);
1604 }
1605 }
1606 #endif
1607 widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks);
1608
1609 return true;
1610 }
1611
animationFinished(QWidget * widget)1612 void QMainWindowLayout::animationFinished(QWidget *widget)
1613 {
1614 //this function is called from within the Widget Animator whenever an animation is finished
1615 //on a certain widget
1616 #ifndef QT_NO_TOOLBAR
1617 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
1618 QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
1619 if (tbl->animating) {
1620 tbl->animating = false;
1621 if (tbl->expanded)
1622 tbl->layoutActions(tb->size());
1623 tb->update();
1624 }
1625 }
1626 #endif
1627
1628 if (widget == pluggingWidget) {
1629
1630 #ifndef QT_NO_DOCKWIDGET
1631 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
1632 dw->d_func()->plug(currentGapRect);
1633 #endif
1634 #ifndef QT_NO_TOOLBAR
1635 if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
1636 tb->d_func()->plug(currentGapRect);
1637 #endif
1638
1639 savedState.clear();
1640 currentGapPos.clear();
1641 pluggingWidget = 0;
1642 //applying the state will make sure that the currentGap is updated correctly
1643 //and all the geometries (especially the one from the central widget) is correct
1644 layoutState.apply(false);
1645
1646 #ifndef QT_NO_DOCKWIDGET
1647 #ifndef QT_NO_TABBAR
1648 if (qobject_cast<QDockWidget*>(widget) != 0) {
1649 // info() might return null if the widget is destroyed while
1650 // animating but before the animationFinished signal is received.
1651 if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget))
1652 info->setCurrentTab(widget);
1653 }
1654 #endif
1655 #endif
1656 }
1657
1658 if (!widgetAnimator.animating()) {
1659 //all animations are finished
1660 #ifndef QT_NO_DOCKWIDGET
1661 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
1662 #ifndef QT_NO_TABBAR
1663 foreach (QTabBar *tab_bar, usedTabBars)
1664 tab_bar->show();
1665 #endif // QT_NO_TABBAR
1666 #endif // QT_NO_DOCKWIDGET
1667 }
1668
1669 updateGapIndicator();
1670 }
1671
restore(bool keepSavedState)1672 void QMainWindowLayout::restore(bool keepSavedState)
1673 {
1674 if (!savedState.isValid())
1675 return;
1676
1677 layoutState = savedState;
1678 applyState(layoutState);
1679 if (!keepSavedState)
1680 savedState.clear();
1681 currentGapPos.clear();
1682 pluggingWidget = 0;
1683 updateGapIndicator();
1684 }
1685
QMainWindowLayout(QMainWindow * mainwindow,QLayout * parentLayout)1686 QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout)
1687 : QLayout(parentLayout ? static_cast<QWidget *>(0) : mainwindow)
1688 , layoutState(mainwindow)
1689 , savedState(mainwindow)
1690 , dockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
1691 , statusbar(0)
1692 #ifndef QT_NO_DOCKWIDGET
1693 #ifndef QT_NO_TABBAR
1694 , _documentMode(false)
1695 , verticalTabsEnabled(false)
1696 #ifndef QT_NO_TABWIDGET
1697 , _tabShape(QTabWidget::Rounded)
1698 #endif
1699 #endif
1700 #endif // QT_NO_DOCKWIDGET
1701 , widgetAnimator(this)
1702 , pluggingWidget(0)
1703 #ifndef QT_NO_RUBBERBAND
1704 , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow))
1705 #endif //QT_NO_RUBBERBAND
1706 #ifdef Q_WS_MAC
1707 , activateUnifiedToolbarAfterFullScreen(false)
1708 , blockVisiblityCheck(false)
1709 #endif
1710 {
1711 if (parentLayout)
1712 setParent(parentLayout);
1713
1714 #ifndef QT_NO_DOCKWIDGET
1715 #ifndef QT_NO_TABBAR
1716 sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainwindow);
1717 #endif
1718
1719 #ifndef QT_NO_TABWIDGET
1720 for (int i = 0; i < QInternal::DockCount; ++i)
1721 tabPositions[i] = QTabWidget::South;
1722 #endif
1723 #endif // QT_NO_DOCKWIDGET
1724
1725 #ifndef QT_NO_RUBBERBAND
1726 // For accessibility to identify this special widget.
1727 gapIndicator->setObjectName(QLatin1String("qt_rubberband"));
1728 gapIndicator->hide();
1729 #endif
1730 pluggingWidget = 0;
1731
1732 setObjectName(mainwindow->objectName() + QLatin1String("_layout"));
1733 }
1734
~QMainWindowLayout()1735 QMainWindowLayout::~QMainWindowLayout()
1736 {
1737 layoutState.deleteAllLayoutItems();
1738 layoutState.deleteCentralWidgetItem();
1739
1740 #ifdef Q_WS_MAC
1741 cleanUpMacToolbarItems();
1742 #endif
1743
1744 delete statusbar;
1745 }
1746
setDockOptions(QMainWindow::DockOptions opts)1747 void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts)
1748 {
1749 if (opts == dockOptions)
1750 return;
1751
1752 dockOptions = opts;
1753
1754 #ifndef QT_NO_DOCKWIDGET
1755 setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs);
1756 #endif
1757
1758 invalidate();
1759 }
1760
1761 #ifndef QT_NO_STATUSBAR
statusBar() const1762 QStatusBar *QMainWindowLayout::statusBar() const
1763 { return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; }
1764
setStatusBar(QStatusBar * sb)1765 void QMainWindowLayout::setStatusBar(QStatusBar *sb)
1766 {
1767 if (sb)
1768 addChildWidget(sb);
1769 delete statusbar;
1770 statusbar = sb ? new QWidgetItemV2(sb) : 0;
1771 invalidate();
1772 }
1773 #endif // QT_NO_STATUSBAR
1774
centralWidget() const1775 QWidget *QMainWindowLayout::centralWidget() const
1776 {
1777 return layoutState.centralWidget();
1778 }
1779
setCentralWidget(QWidget * widget)1780 void QMainWindowLayout::setCentralWidget(QWidget *widget)
1781 {
1782 if (widget != 0)
1783 addChildWidget(widget);
1784 layoutState.setCentralWidget(widget);
1785 if (savedState.isValid()) {
1786 #ifndef QT_NO_DOCKWIDGET
1787 savedState.dockAreaLayout.centralWidgetItem = layoutState.dockAreaLayout.centralWidgetItem;
1788 savedState.dockAreaLayout.fallbackToSizeHints = true;
1789 #else
1790 savedState.centralWidgetItem = layoutState.centralWidgetItem;
1791 #endif
1792 }
1793 invalidate();
1794 }
1795
unplug(QWidget * widget)1796 QLayoutItem *QMainWindowLayout::unplug(QWidget *widget)
1797 {
1798 QList<int> path = layoutState.indexOf(widget);
1799 if (path.isEmpty())
1800 return 0;
1801
1802 QLayoutItem *item = layoutState.item(path);
1803 if (widget->isWindow())
1804 return item;
1805
1806 QRect r = layoutState.itemRect(path);
1807 savedState = layoutState;
1808
1809 #ifndef QT_NO_DOCKWIDGET
1810 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
1811 dw->d_func()->unplug(r);
1812 }
1813 #endif
1814 #ifndef QT_NO_TOOLBAR
1815 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
1816 tb->d_func()->unplug(r);
1817 }
1818 #endif
1819
1820
1821 layoutState.unplug(path ,&savedState);
1822 savedState.fitLayout();
1823 currentGapPos = path;
1824 currentGapRect = r;
1825 updateGapIndicator();
1826
1827 fixToolBarOrientation(item, currentGapPos.at(1));
1828
1829 return item;
1830 }
1831
updateGapIndicator()1832 void QMainWindowLayout::updateGapIndicator()
1833 {
1834 #ifndef QT_NO_RUBBERBAND
1835 gapIndicator->setVisible(!widgetAnimator.animating() && !currentGapPos.isEmpty());
1836 gapIndicator->setGeometry(currentGapRect);
1837 #endif
1838 }
1839
hover(QLayoutItem * widgetItem,const QPoint & mousePos)1840 QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
1841 {
1842 if (!parentWidget()->isVisible() || parentWidget()->isMinimized()
1843 || pluggingWidget != 0 || widgetItem == 0)
1844 return QList<int>();
1845
1846 QWidget *widget = widgetItem->widget();
1847 QPoint pos = parentWidget()->mapFromGlobal(mousePos);
1848
1849 if (!savedState.isValid())
1850 savedState = layoutState;
1851
1852 QList<int> path = savedState.gapIndex(widget, pos);
1853
1854 if (!path.isEmpty()) {
1855 bool allowed = false;
1856
1857 #ifndef QT_NO_DOCKWIDGET
1858 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
1859 allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1)));
1860 #endif
1861 #ifndef QT_NO_TOOLBAR
1862 if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
1863 allowed = tb->isAreaAllowed(toToolBarArea(path.at(1)));
1864 #endif
1865
1866 if (!allowed)
1867 path.clear();
1868 }
1869
1870 if (path == currentGapPos)
1871 return currentGapPos; // the gap is already there
1872
1873 currentGapPos = path;
1874 if (path.isEmpty()) {
1875 fixToolBarOrientation(widgetItem, 2); // 2 = top dock, ie. horizontal
1876 restore(true);
1877 return QList<int>();
1878 }
1879
1880 fixToolBarOrientation(widgetItem, currentGapPos.at(1));
1881
1882 QMainWindowLayoutState newState = savedState;
1883
1884 if (!newState.insertGap(path, widgetItem)) {
1885 restore(true); // not enough space
1886 return QList<int>();
1887 }
1888
1889 QSize min = newState.minimumSize();
1890 QSize size = newState.rect.size();
1891
1892 if (min.width() > size.width() || min.height() > size.height()) {
1893 restore(true);
1894 return QList<int>();
1895 }
1896
1897 newState.fitLayout();
1898
1899 currentGapRect = newState.gapRect(currentGapPos);
1900
1901 #ifndef QT_NO_DOCKWIDGET
1902 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
1903 #endif
1904 layoutState = newState;
1905 applyState(layoutState);
1906
1907 updateGapIndicator();
1908
1909 return path;
1910 }
1911
applyState(QMainWindowLayoutState & newState,bool animate)1912 void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate)
1913 {
1914 #ifndef QT_NO_DOCKWIDGET
1915 #ifndef QT_NO_TABBAR
1916 QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
1917 QSet<QTabBar*> retired = usedTabBars - used;
1918 usedTabBars = used;
1919 foreach (QTabBar *tab_bar, retired) {
1920 tab_bar->hide();
1921 while (tab_bar->count() > 0)
1922 tab_bar->removeTab(0);
1923 unusedTabBars.append(tab_bar);
1924 }
1925
1926 if (sep == 1) {
1927 QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
1928 QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
1929 usedSeparatorWidgets = usedSeps;
1930 foreach (QWidget *sepWidget, retiredSeps) {
1931 unusedSeparatorWidgets.append(sepWidget);
1932 }
1933 }
1934
1935
1936 #endif // QT_NO_TABBAR
1937 #endif // QT_NO_DOCKWIDGET
1938 newState.apply(dockOptions & QMainWindow::AnimatedDocks && animate);
1939 }
1940
saveState(QDataStream & stream) const1941 void QMainWindowLayout::saveState(QDataStream &stream) const
1942 {
1943 layoutState.saveState(stream);
1944 }
1945
restoreState(QDataStream & stream)1946 bool QMainWindowLayout::restoreState(QDataStream &stream)
1947 {
1948 savedState = layoutState;
1949 layoutState.clear();
1950 layoutState.rect = savedState.rect;
1951
1952 if (!layoutState.restoreState(stream, savedState)) {
1953 layoutState.deleteAllLayoutItems();
1954 layoutState = savedState;
1955 if (parentWidget()->isVisible())
1956 applyState(layoutState, false); // hides tabBars allocated by newState
1957 return false;
1958 }
1959
1960 if (parentWidget()->isVisible()) {
1961 layoutState.fitLayout();
1962 applyState(layoutState, false);
1963 }
1964
1965 savedState.deleteAllLayoutItems();
1966 savedState.clear();
1967
1968 #ifndef QT_NO_DOCKWIDGET
1969 if (parentWidget()->isVisible()) {
1970 #ifndef QT_NO_TABBAR
1971 foreach (QTabBar *tab_bar, usedTabBars)
1972 tab_bar->show();
1973
1974 #endif
1975 }
1976 #endif // QT_NO_DOCKWIDGET
1977
1978 return true;
1979 }
1980
1981
1982 // Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases
1983 // for example, you have a toolbar in the top area and then you suddenly turn on
1984 // HIToolbar.
usesHIToolBar(QToolBar * toolbar) const1985 bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const
1986 {
1987 #ifndef Q_WS_MAC
1988 Q_UNUSED(toolbar);
1989 return false;
1990 #else
1991 return qtoolbarsInUnifiedToolbarList.contains(toolbar)
1992 || ((toolBarArea(toolbar) == Qt::TopToolBarArea)
1993 && layoutState.mainWindow->unifiedTitleAndToolBarOnMac());
1994 #endif
1995 }
1996
timerEvent(QTimerEvent * e)1997 void QMainWindowLayout::timerEvent(QTimerEvent *e)
1998 {
1999 #ifndef QT_NO_DOCKWIDGET
2000 if (e->timerId() == separatorMoveTimer.timerId()) {
2001 //let's move the separators
2002 separatorMoveTimer.stop();
2003 if (movingSeparator.isEmpty())
2004 return;
2005 if (movingSeparatorOrigin == movingSeparatorPos)
2006 return;
2007
2008 //when moving the separator, we need to update the previous position
2009 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
2010
2011 layoutState = savedState;
2012 layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
2013 movingSeparatorPos);
2014 movingSeparatorPos = movingSeparatorOrigin;
2015 }
2016 #endif
2017 QLayout::timerEvent(e);
2018 }
2019
2020
2021 QT_END_NAMESPACE
2022
2023 #endif // QT_NO_MAINWINDOW
2024