source: trunk/src/gui/widgets/qdockarealayout.cpp

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

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

File size: 101.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the 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 [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "QtGui/qapplication.h"
43#include "QtGui/qwidget.h"
44#include "QtGui/qtabbar.h"
45#include "QtGui/qstyle.h"
46#include "QtGui/qdesktopwidget.h"
47#include "QtCore/qvariant.h"
48#include "qdockarealayout_p.h"
49#include "qdockwidget.h"
50#include "qmainwindow.h"
51#include "qwidgetanimator_p.h"
52#include "qmainwindowlayout_p.h"
53#include "qdockwidget_p.h"
54#include <private/qlayoutengine_p.h>
55
56#include <qpainter.h>
57#include <qstyleoption.h>
58
59#ifndef QT_NO_DOCKWIDGET
60
61QT_BEGIN_NAMESPACE
62
63// qmainwindow.cpp
64extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
65
66enum { StateFlagVisible = 1, StateFlagFloating = 2 };
67
68/******************************************************************************
69** QPlaceHolderItem
70*/
71
72QPlaceHolderItem::QPlaceHolderItem(QWidget *w)
73{
74 objectName = w->objectName();
75 hidden = w->isHidden();
76 window = w->isWindow();
77 if (window)
78 topLevelRect = w->geometry();
79}
80
81/******************************************************************************
82** QDockAreaLayoutItem
83*/
84
85QDockAreaLayoutItem::QDockAreaLayoutItem(QLayoutItem *_widgetItem)
86 : widgetItem(_widgetItem), subinfo(0), placeHolderItem(0), pos(0), size(-1), flags(NoFlags)
87{
88}
89
90QDockAreaLayoutItem::QDockAreaLayoutItem(QDockAreaLayoutInfo *_subinfo)
91 : widgetItem(0), subinfo(_subinfo), placeHolderItem(0), pos(0), size(-1), flags(NoFlags)
92{
93}
94
95QDockAreaLayoutItem::QDockAreaLayoutItem(QPlaceHolderItem *_placeHolderItem)
96 : widgetItem(0), subinfo(0), placeHolderItem(_placeHolderItem), pos(0), size(-1), flags(NoFlags)
97{
98}
99
100QDockAreaLayoutItem::QDockAreaLayoutItem(const QDockAreaLayoutItem &other)
101 : widgetItem(other.widgetItem), subinfo(0), placeHolderItem(0), pos(other.pos),
102 size(other.size), flags(other.flags)
103{
104 if (other.subinfo != 0)
105 subinfo = new QDockAreaLayoutInfo(*other.subinfo);
106 else if (other.placeHolderItem != 0)
107 placeHolderItem = new QPlaceHolderItem(*other.placeHolderItem);
108}
109
110QDockAreaLayoutItem::~QDockAreaLayoutItem()
111{
112 delete subinfo;
113 delete placeHolderItem;
114}
115
116bool QDockAreaLayoutItem::skip() const
117{
118 if (placeHolderItem != 0)
119 return true;
120
121 if (flags & GapItem)
122 return false;
123
124 if (widgetItem != 0)
125 return widgetItem->isEmpty();
126
127 if (subinfo != 0) {
128 for (int i = 0; i < subinfo->item_list.count(); ++i) {
129 if (!subinfo->item_list.at(i).skip())
130 return false;
131 }
132 }
133
134 return true;
135}
136
137QSize QDockAreaLayoutItem::minimumSize() const
138{
139 if (widgetItem != 0) {
140 int left, top, right, bottom;
141 widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
142 return widgetItem->minimumSize() + QSize(left+right, top+bottom);
143 }
144 if (subinfo != 0)
145 return subinfo->minimumSize();
146 return QSize(0, 0);
147}
148
149QSize QDockAreaLayoutItem::maximumSize() const
150{
151 if (widgetItem != 0) {
152 int left, top, right, bottom;
153 widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
154 return widgetItem->maximumSize()+ QSize(left+right, top+bottom);
155 }
156 if (subinfo != 0)
157 return subinfo->maximumSize();
158 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
159}
160
161bool QDockAreaLayoutItem::hasFixedSize(Qt::Orientation o) const
162{
163 return perp(o, minimumSize()) == perp(o, maximumSize());
164}
165
166bool QDockAreaLayoutItem::expansive(Qt::Orientation o) const
167{
168 if ((flags & GapItem) || placeHolderItem != 0)
169 return false;
170 if (widgetItem != 0)
171 return ((widgetItem->expandingDirections() & o) == o);
172 if (subinfo != 0)
173 return subinfo->expansive(o);
174 return false;
175}
176
177QSize QDockAreaLayoutItem::sizeHint() const
178{
179 if (placeHolderItem != 0)
180 return QSize(0, 0);
181 if (widgetItem != 0) {
182 int left, top, right, bottom;
183 widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
184 return widgetItem->sizeHint() + QSize(left+right, top+bottom);
185 }
186 if (subinfo != 0)
187 return subinfo->sizeHint();
188 return QSize(-1, -1);
189}
190
191QDockAreaLayoutItem
192 &QDockAreaLayoutItem::operator = (const QDockAreaLayoutItem &other)
193{
194 widgetItem = other.widgetItem;
195 if (other.subinfo == 0)
196 subinfo = 0;
197 else
198 subinfo = new QDockAreaLayoutInfo(*other.subinfo);
199
200 delete placeHolderItem;
201 if (other.placeHolderItem == 0)
202 placeHolderItem = 0;
203 else
204 placeHolderItem = new QPlaceHolderItem(*other.placeHolderItem);
205
206 pos = other.pos;
207 size = other.size;
208 flags = other.flags;
209
210 return *this;
211}
212
213/******************************************************************************
214** QDockAreaLayoutInfo
215*/
216
217#ifndef QT_NO_TABBAR
218static quintptr tabId(const QDockAreaLayoutItem &item)
219{
220 if (item.widgetItem == 0)
221 return 0;
222 return reinterpret_cast<quintptr>(item.widgetItem->widget());
223}
224#endif
225
226static const int zero = 0;
227
228QDockAreaLayoutInfo::QDockAreaLayoutInfo()
229 : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
230#ifndef QT_NO_TABBAR
231 , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth)
232#endif
233{
234}
235
236QDockAreaLayoutInfo::QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos,
237 Qt::Orientation _o, int tbshape,
238 QMainWindow *window)
239 : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
240#ifndef QT_NO_TABBAR
241 , tabbed(false), tabBar(0), tabBarShape(static_cast<QTabBar::Shape>(tbshape))
242#endif
243{
244#ifdef QT_NO_TABBAR
245 Q_UNUSED(tbshape);
246#endif
247}
248
249QSize QDockAreaLayoutInfo::size() const
250{
251 return isEmpty() ? QSize(0, 0) : rect.size();
252}
253
254void QDockAreaLayoutInfo::clear()
255{
256 item_list.clear();
257 rect = QRect();
258#ifndef QT_NO_TABBAR
259 tabbed = false;
260 tabBar = 0;
261#endif
262}
263
264bool QDockAreaLayoutInfo::isEmpty() const
265{
266 return next(-1) == -1;
267}
268
269QSize QDockAreaLayoutInfo::minimumSize() const
270{
271 if (isEmpty())
272 return QSize(0, 0);
273
274 int a = 0, b = 0;
275 bool first = true;
276 for (int i = 0; i < item_list.size(); ++i) {
277 const QDockAreaLayoutItem &item = item_list.at(i);
278 if (item.skip())
279 continue;
280
281 QSize min_size = item.minimumSize();
282#ifndef QT_NO_TABBAR
283 if (tabbed) {
284 a = qMax(a, pick(o, min_size));
285 } else
286#endif
287 {
288 if (!first)
289 a += *sep;
290 a += pick(o, min_size);
291 }
292 b = qMax(b, perp(o, min_size));
293
294 first = false;
295 }
296
297 QSize result;
298 rpick(o, result) = a;
299 rperp(o, result) = b;
300
301#ifndef QT_NO_TABBAR
302 QSize tbm = tabBarMinimumSize();
303 if (!tbm.isNull()) {
304 switch (tabBarShape) {
305 case QTabBar::RoundedNorth:
306 case QTabBar::RoundedSouth:
307 case QTabBar::TriangularNorth:
308 case QTabBar::TriangularSouth:
309 result.rheight() += tbm.height();
310 result.rwidth() = qMax(tbm.width(), result.width());
311 break;
312 case QTabBar::RoundedEast:
313 case QTabBar::RoundedWest:
314 case QTabBar::TriangularEast:
315 case QTabBar::TriangularWest:
316 result.rheight() = qMax(tbm.height(), result.height());
317 result.rwidth() += tbm.width();
318 break;
319 default:
320 break;
321 }
322 }
323#endif // QT_NO_TABBAR
324
325 return result;
326}
327
328QSize QDockAreaLayoutInfo::maximumSize() const
329{
330 if (isEmpty())
331 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
332
333 int a = 0, b = QWIDGETSIZE_MAX;
334#ifndef QT_NO_TABBAR
335 if (tabbed)
336 a = QWIDGETSIZE_MAX;
337#endif
338
339 int min_perp = 0;
340
341 bool first = true;
342 for (int i = 0; i < item_list.size(); ++i) {
343 const QDockAreaLayoutItem &item = item_list.at(i);
344 if (item.skip())
345 continue;
346
347 QSize max_size = item.maximumSize();
348 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
349
350#ifndef QT_NO_TABBAR
351 if (tabbed) {
352 a = qMin(a, pick(o, max_size));
353 } else
354#endif
355 {
356 if (!first)
357 a += *sep;
358 a += pick(o, max_size);
359 }
360 b = qMin(b, perp(o, max_size));
361
362 a = qMin(a, int(QWIDGETSIZE_MAX));
363 b = qMin(b, int(QWIDGETSIZE_MAX));
364
365 first = false;
366 }
367
368 b = qMax(b, min_perp);
369
370 QSize result;
371 rpick(o, result) = a;
372 rperp(o, result) = b;
373
374#ifndef QT_NO_TABBAR
375 QSize tbh = tabBarSizeHint();
376 if (!tbh.isNull()) {
377 switch (tabBarShape) {
378 case QTabBar::RoundedNorth:
379 case QTabBar::RoundedSouth:
380 result.rheight() += tbh.height();
381 break;
382 case QTabBar::RoundedEast:
383 case QTabBar::RoundedWest:
384 result.rwidth() += tbh.width();
385 break;
386 default:
387 break;
388 }
389 }
390#endif // QT_NO_TABBAR
391
392 return result;
393}
394
395QSize QDockAreaLayoutInfo::sizeHint() const
396{
397 if (isEmpty())
398 return QSize(0, 0);
399
400 int a = 0, b = 0;
401 int min_perp = 0;
402 int max_perp = QWIDGETSIZE_MAX;
403 const QDockAreaLayoutItem *previous = 0;
404 for (int i = 0; i < item_list.size(); ++i) {
405 const QDockAreaLayoutItem &item = item_list.at(i);
406 if (item.skip())
407 continue;
408
409 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
410
411 QSize size_hint = item.sizeHint();
412 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
413 max_perp = qMin(max_perp, perp(o, item.maximumSize()));
414
415#ifndef QT_NO_TABBAR
416 if (tabbed) {
417 a = qMax(a, gap ? item.size : pick(o, size_hint));
418 } else
419#endif
420 {
421 if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
422 && !previous->hasFixedSize(o)) {
423 a += *sep;
424 }
425 a += gap ? item.size : pick(o, size_hint);
426 }
427 b = qMax(b, perp(o, size_hint));
428
429 previous = &item;
430 }
431
432 max_perp = qMax(max_perp, min_perp);
433 b = qMax(b, min_perp);
434 b = qMin(b, max_perp);
435
436 QSize result;
437 rpick(o, result) = a;
438 rperp(o, result) = b;
439
440#ifndef QT_NO_TABBAR
441 if (tabbed) {
442 QSize tbh = tabBarSizeHint();
443 switch (tabBarShape) {
444 case QTabBar::RoundedNorth:
445 case QTabBar::RoundedSouth:
446 case QTabBar::TriangularNorth:
447 case QTabBar::TriangularSouth:
448 result.rheight() += tbh.height();
449 result.rwidth() = qMax(tbh.width(), result.width());
450 break;
451 case QTabBar::RoundedEast:
452 case QTabBar::RoundedWest:
453 case QTabBar::TriangularEast:
454 case QTabBar::TriangularWest:
455 result.rheight() = qMax(tbh.height(), result.height());
456 result.rwidth() += tbh.width();
457 break;
458 default:
459 break;
460 }
461 }
462#endif // QT_NO_TABBAR
463
464 return result;
465}
466
467bool QDockAreaLayoutInfo::expansive(Qt::Orientation o) const
468{
469 for (int i = 0; i < item_list.size(); ++i) {
470 if (item_list.at(i).expansive(o))
471 return true;
472 }
473 return false;
474}
475
476/* QDockAreaLayoutInfo::maximumSize() doesn't return the real max size. For example,
477 if the layout is empty, it returns QWIDGETSIZE_MAX. This is so that empty dock areas
478 don't constrain the size of the QMainWindow, but sometimes we really need to know the
479 maximum size. Also, these functions take into account widgets that want to keep their
480 size (f.ex. when they are hidden and then shown, they should not change size).
481*/
482
483static int realMinSize(const QDockAreaLayoutInfo &info)
484{
485 int result = 0;
486 bool first = true;
487 for (int i = 0; i < info.item_list.size(); ++i) {
488 const QDockAreaLayoutItem &item = info.item_list.at(i);
489 if (item.skip())
490 continue;
491
492 int min = 0;
493 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
494 min = item.size;
495 else
496 min = pick(info.o, item.minimumSize());
497
498 if (!first)
499 result += *info.sep;
500 result += min;
501
502 first = false;
503 }
504
505 return result;
506}
507
508static int realMaxSize(const QDockAreaLayoutInfo &info)
509{
510 int result = 0;
511 bool first = true;
512 for (int i = 0; i < info.item_list.size(); ++i) {
513 const QDockAreaLayoutItem &item = info.item_list.at(i);
514 if (item.skip())
515 continue;
516
517 int max = 0;
518 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
519 max = item.size;
520 else
521 max = pick(info.o, item.maximumSize());
522
523 if (!first)
524 result += *info.sep;
525 result += max;
526
527 if (result >= QWIDGETSIZE_MAX)
528 return QWIDGETSIZE_MAX;
529
530 first = false;
531 }
532
533 return result;
534}
535
536void QDockAreaLayoutInfo::fitItems()
537{
538#ifndef QT_NO_TABBAR
539 if (tabbed) {
540 return;
541 }
542#endif
543
544 QVector<QLayoutStruct> layout_struct_list(item_list.size()*2);
545 int j = 0;
546
547 int size = pick(o, rect.size());
548 int min_size = realMinSize(*this);
549 int max_size = realMaxSize(*this);
550 int last_index = -1;
551
552 const QDockAreaLayoutItem *previous = 0;
553 for (int i = 0; i < item_list.size(); ++i) {
554 QDockAreaLayoutItem &item = item_list[i];
555 if (item.skip())
556 continue;
557
558 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
559 if (previous && !gap) {
560 if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
561 QLayoutStruct &ls = layout_struct_list[j++];
562 ls.init();
563 ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
564 ls.empty = false;
565 }
566 }
567
568 if (item.flags & QDockAreaLayoutItem::KeepSize) {
569 // Check if the item can keep its size, without violating size constraints
570 // of other items.
571
572 if (size < min_size) {
573 // There is too little space to keep this widget's size
574 item.flags &= ~QDockAreaLayoutItem::KeepSize;
575 min_size -= item.size;
576 min_size += pick(o, item.minimumSize());
577 min_size = qMax(0, min_size);
578 } else if (size > max_size) {
579 // There is too much space to keep this widget's size
580 item.flags &= ~QDockAreaLayoutItem::KeepSize;
581 max_size -= item.size;
582 max_size += pick(o, item.maximumSize());
583 max_size = qMin<int>(QWIDGETSIZE_MAX, max_size);
584 }
585 }
586
587 last_index = j;
588 QLayoutStruct &ls = layout_struct_list[j++];
589 ls.init();
590 ls.empty = false;
591 if (item.flags & QDockAreaLayoutItem::KeepSize) {
592 ls.minimumSize = ls.maximumSize = ls.sizeHint = item.size;
593 ls.expansive = false;
594 ls.stretch = 0;
595 } else {
596 ls.maximumSize = pick(o, item.maximumSize());
597 ls.expansive = item.expansive(o);
598 ls.minimumSize = pick(o, item.minimumSize());
599 ls.sizeHint = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
600 ls.stretch = ls.expansive ? ls.sizeHint : 0;
601 }
602
603 item.flags &= ~QDockAreaLayoutItem::KeepSize;
604 previous = &item;
605 }
606 layout_struct_list.resize(j);
607
608 // If there is more space than the widgets can take (due to maximum size constraints),
609 // we detect it here and stretch the last widget to take up the rest of the space.
610 if (size > max_size && last_index != -1) {
611 layout_struct_list[last_index].maximumSize = QWIDGETSIZE_MAX;
612 layout_struct_list[last_index].expansive = true;
613 }
614
615 qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
616
617 j = 0;
618 bool prev_gap = false;
619 bool first = true;
620 for (int i = 0; i < item_list.size(); ++i) {
621 QDockAreaLayoutItem &item = item_list[i];
622 if (item.skip())
623 continue;
624
625 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
626 if (!first && !gap && !prev_gap)
627 ++j;
628
629 const QLayoutStruct &ls = layout_struct_list.at(j++);
630 item.size = ls.size;
631 item.pos = ls.pos;
632
633 if (item.subinfo != 0) {
634 item.subinfo->rect = itemRect(i);
635 item.subinfo->fitItems();
636 }
637
638 prev_gap = gap;
639 first = false;
640 }
641}
642
643static QInternal::DockPosition dockPosHelper(const QRect &rect, const QPoint &_pos,
644 Qt::Orientation o,
645 bool nestingEnabled,
646 QDockAreaLayoutInfo::TabMode tabMode)
647{
648 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
649 return QInternal::DockCount;
650
651 QPoint pos = _pos - rect.topLeft();
652
653 int x = pos.x();
654 int y = pos.y();
655 int w = rect.width();
656 int h = rect.height();
657
658 if (tabMode != QDockAreaLayoutInfo::NoTabs) {
659 // is it in the center?
660 if (nestingEnabled) {
661 /* 2/3
662 +--------------+
663 | |
664 | CCCCCCCC |
665 2/3 | CCCCCCCC |
666 | CCCCCCCC |
667 | |
668 +--------------+ */
669
670 QRect center(w/6, h/6, 2*w/3, 2*h/3);
671 if (center.contains(pos))
672 return QInternal::DockCount;
673 } else if (o == Qt::Horizontal) {
674 /* 2/3
675 +--------------+
676 | CCCCCCCC |
677 | CCCCCCCC |
678 | CCCCCCCC |
679 | CCCCCCCC |
680 | CCCCCCCC |
681 +--------------+ */
682
683 if (x > w/6 && x < w*5/6)
684 return QInternal::DockCount;
685 } else {
686 /*
687 +--------------+
688 | |
689 2/3 |CCCCCCCCCCCCCC|
690 |CCCCCCCCCCCCCC|
691 | |
692 +--------------+ */
693 if (y > h/6 && y < 5*h/6)
694 return QInternal::DockCount;
695 }
696 }
697
698 // not in the center. which edge?
699 if (nestingEnabled) {
700 if (o == Qt::Horizontal) {
701 /* 1/3 1/3 1/3
702 +------------+ (we've already ruled out the center)
703 |LLLLTTTTRRRR|
704 |LLLLTTTTRRRR|
705 |LLLLBBBBRRRR|
706 |LLLLBBBBRRRR|
707 +------------+ */
708
709 if (x < w/3)
710 return QInternal::LeftDock;
711 if (x > 2*w/3)
712 return QInternal::RightDock;
713 if (y < h/2)
714 return QInternal::TopDock;
715 return QInternal::BottomDock;
716 } else {
717 /* +------------+ (we've already ruled out the center)
718 1/3 |TTTTTTTTTTTT|
719 |LLLLLLRRRRRR|
720 1/3 |LLLLLLRRRRRR|
721 1/3 |BBBBBBBBBBBB|
722 +------------+ */
723
724 if (y < h/3)
725 return QInternal::TopDock;
726 if (y > 2*h/3)
727 return QInternal::BottomDock;
728 if (x < w/2)
729 return QInternal::LeftDock;
730 return QInternal::RightDock;
731 }
732 } else {
733 if (o == Qt::Horizontal) {
734 return x < w/2
735 ? QInternal::LeftDock
736 : QInternal::RightDock;
737 } else {
738 return y < h/2
739 ? QInternal::TopDock
740 : QInternal::BottomDock;
741 }
742 }
743}
744
745QList<int> QDockAreaLayoutInfo::gapIndex(const QPoint& _pos,
746 bool nestingEnabled, TabMode tabMode) const
747{
748 QList<int> result;
749 QRect item_rect;
750 int item_index = 0;
751
752#ifndef QT_NO_TABBAR
753 if (tabbed) {
754 item_rect = tabContentRect();
755 } else
756#endif
757 {
758 int pos = pick(o, _pos);
759
760 int last = -1;
761 for (int i = 0; i < item_list.size(); ++i) {
762 const QDockAreaLayoutItem &item = item_list.at(i);
763 if (item.skip())
764 continue;
765
766 last = i;
767
768 if (item.pos + item.size < pos)
769 continue;
770
771 if (item.subinfo != 0
772#ifndef QT_NO_TABBAR
773 && !item.subinfo->tabbed
774#endif
775 ) {
776 result = item.subinfo->gapIndex(_pos, nestingEnabled,
777 tabMode);
778 result.prepend(i);
779 return result;
780 }
781
782 item_rect = itemRect(i);
783 item_index = i;
784 break;
785 }
786
787 if (item_rect.isNull()) {
788 result.append(last + 1);
789 return result;
790 }
791 }
792
793 Q_ASSERT(!item_rect.isNull());
794
795 QInternal::DockPosition dock_pos
796 = dockPosHelper(item_rect, _pos, o, nestingEnabled, tabMode);
797
798 switch (dock_pos) {
799 case QInternal::LeftDock:
800 if (o == Qt::Horizontal)
801 result << item_index;
802 else
803 result << item_index << 0; // this subinfo doesn't exist yet, but insertGap()
804 // handles this by inserting it
805 break;
806 case QInternal::RightDock:
807 if (o == Qt::Horizontal)
808 result << item_index + 1;
809 else
810 result << item_index << 1;
811 break;
812 case QInternal::TopDock:
813 if (o == Qt::Horizontal)
814 result << item_index << 0;
815 else
816 result << item_index;
817 break;
818 case QInternal::BottomDock:
819 if (o == Qt::Horizontal)
820 result << item_index << 1;
821 else
822 result << item_index + 1;
823 break;
824 case QInternal::DockCount:
825 result << (-item_index - 1) << 0; // negative item_index means "on top of"
826 // -item_index - 1, insertGap()
827 // will insert a tabbed subinfo
828 break;
829 default:
830 break;
831 }
832
833 return result;
834}
835
836static inline int shrink(QLayoutStruct &ls, int delta)
837{
838 if (ls.empty)
839 return 0;
840 int old_size = ls.size;
841 ls.size = qMax(ls.size - delta, ls.minimumSize);
842 return old_size - ls.size;
843}
844
845static inline int grow(QLayoutStruct &ls, int delta)
846{
847 if (ls.empty)
848 return 0;
849 int old_size = ls.size;
850 ls.size = qMin(ls.size + delta, ls.maximumSize);
851 return ls.size - old_size;
852}
853
854static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delta, int sep)
855{
856 // adjust sizes
857 int pos = -1;
858 for (int i = 0; i < list.size(); ++i) {
859 const QLayoutStruct &ls = list.at(i);
860 if (!ls.empty) {
861 pos = ls.pos;
862 break;
863 }
864 }
865 if (pos == -1)
866 return 0;
867
868 if (delta > 0) {
869 int growlimit = 0;
870 for (int i = 0; i<=index; ++i) {
871 const QLayoutStruct &ls = list.at(i);
872 if (ls.empty)
873 continue;
874 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
875 growlimit = QLAYOUTSIZE_MAX;
876 break;
877 }
878 growlimit += ls.maximumSize - ls.size;
879 }
880 if (delta > growlimit)
881 delta = growlimit;
882
883 int d = 0;
884 for (int i = index + 1; d < delta && i < list.count(); ++i)
885 d += shrink(list[i], delta - d);
886 delta = d;
887 d = 0;
888 for (int i = index; d < delta && i >= 0; --i)
889 d += grow(list[i], delta - d);
890 } else if (delta < 0) {
891 int growlimit = 0;
892 for (int i = index + 1; i < list.count(); ++i) {
893 const QLayoutStruct &ls = list.at(i);
894 if (ls.empty)
895 continue;
896 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
897 growlimit = QLAYOUTSIZE_MAX;
898 break;
899 }
900 growlimit += ls.maximumSize - ls.size;
901 }
902 if (-delta > growlimit)
903 delta = -growlimit;
904
905 int d = 0;
906 for (int i = index; d < -delta && i >= 0; --i)
907 d += shrink(list[i], -delta - d);
908 delta = -d;
909 d = 0;
910 for (int i = index + 1; d < -delta && i < list.count(); ++i)
911 d += grow(list[i], -delta - d);
912 }
913
914 // adjust positions
915 bool first = true;
916 for (int i = 0; i < list.size(); ++i) {
917 QLayoutStruct &ls = list[i];
918 if (ls.empty) {
919 ls.pos = pos + (first ? 0 : sep);
920 continue;
921 }
922 if (!first)
923 pos += sep;
924 ls.pos = pos;
925 pos += ls.size;
926 first = false;
927 }
928
929 return delta;
930}
931
932int QDockAreaLayoutInfo::separatorMove(int index, int delta)
933{
934#ifndef QT_NO_TABBAR
935 Q_ASSERT(!tabbed);
936#endif
937
938 QVector<QLayoutStruct> list(item_list.size());
939 for (int i = 0; i < list.size(); ++i) {
940 const QDockAreaLayoutItem &item = item_list.at(i);
941 QLayoutStruct &ls = list[i];
942 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
943 if (item.skip()) {
944 ls.empty = true;
945 } else {
946 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
947 ls.empty = false;
948 ls.pos = item.pos;
949 ls.size = item.size + separatorSpace;
950 ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace;
951 ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace;
952
953 }
954 }
955
956 //the separator space has been added to the size, so we pass 0 as a parameter
957 delta = separatorMoveHelper(list, index, delta, 0 /*separator*/);
958
959 for (int i = 0; i < list.size(); ++i) {
960 QDockAreaLayoutItem &item = item_list[i];
961 if (item.skip())
962 continue;
963 QLayoutStruct &ls = list[i];
964 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
965 item.size = ls.size - separatorSpace;
966 item.pos = ls.pos;
967 if (item.subinfo != 0) {
968 item.subinfo->rect = itemRect(i);
969 item.subinfo->fitItems();
970 }
971 }
972
973 return delta;
974}
975
976void QDockAreaLayoutInfo::unnest(int index)
977{
978 QDockAreaLayoutItem &item = item_list[index];
979 if (item.subinfo == 0)
980 return;
981 if (item.subinfo->item_list.count() > 1)
982 return;
983
984 if (item.subinfo->item_list.count() == 0) {
985 item_list.removeAt(index);
986 } else if (item.subinfo->item_list.count() == 1) {
987 QDockAreaLayoutItem &child = item.subinfo->item_list.first();
988 if (child.widgetItem != 0) {
989 item.widgetItem = child.widgetItem;
990 delete item.subinfo;
991 item.subinfo = 0;
992 } else if (child.subinfo != 0) {
993 QDockAreaLayoutInfo *tmp = item.subinfo;
994 item.subinfo = child.subinfo;
995 child.subinfo = 0;
996 tmp->item_list.clear();
997 delete tmp;
998 }
999 }
1000}
1001
1002void QDockAreaLayoutInfo::remove(const QList<int> &path)
1003{
1004 Q_ASSERT(!path.isEmpty());
1005
1006 if (path.count() > 1) {
1007 const int index = path.first();
1008 QDockAreaLayoutItem &item = item_list[index];
1009 Q_ASSERT(item.subinfo != 0);
1010 item.subinfo->remove(path.mid(1));
1011 unnest(index);
1012 } else {
1013 int index = path.first();
1014 item_list.removeAt(index);
1015 }
1016}
1017
1018QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
1019{
1020 Q_ASSERT(!path.isEmpty());
1021
1022 int index = path.first();
1023 if (index < 0)
1024 index = -index - 1;
1025
1026 if (path.count() > 1) {
1027 const QDockAreaLayoutItem &item = item_list.at(index);
1028 Q_ASSERT(item.subinfo != 0);
1029 return item.subinfo->plug(path.mid(1));
1030 }
1031
1032 QDockAreaLayoutItem &item = item_list[index];
1033
1034 Q_ASSERT(item.widgetItem != 0);
1035 Q_ASSERT(item.flags & QDockAreaLayoutItem::GapItem);
1036 item.flags &= ~QDockAreaLayoutItem::GapItem;
1037
1038 QRect result;
1039
1040#ifndef QT_NO_TABBAR
1041 if (tabbed) {
1042 } else
1043#endif
1044 {
1045 int prev = this->prev(index);
1046 int next = this->next(index);
1047
1048 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1049 item.pos += *sep;
1050 item.size -= *sep;
1051 }
1052 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1053 item.size -= *sep;
1054
1055 QPoint pos;
1056 rpick(o, pos) = item.pos;
1057 rperp(o, pos) = perp(o, rect.topLeft());
1058 QSize s;
1059 rpick(o, s) = item.size;
1060 rperp(o, s) = perp(o, rect.size());
1061 result = QRect(pos, s);
1062 }
1063
1064 return item.widgetItem;
1065}
1066
1067QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
1068{
1069 Q_ASSERT(!path.isEmpty());
1070
1071 const int index = path.first();
1072 if (path.count() > 1) {
1073 const QDockAreaLayoutItem &item = item_list.at(index);
1074 Q_ASSERT(item.subinfo != 0);
1075 return item.subinfo->unplug(path.mid(1));
1076 }
1077
1078 QDockAreaLayoutItem &item = item_list[index];
1079 int prev = this->prev(index);
1080 int next = this->next(index);
1081
1082 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
1083 item.flags |= QDockAreaLayoutItem::GapItem;
1084
1085#ifndef QT_NO_TABBAR
1086 if (tabbed) {
1087 } else
1088#endif
1089 {
1090 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1091 item.pos -= *sep;
1092 item.size += *sep;
1093 }
1094 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1095 item.size += *sep;
1096 }
1097
1098 return item.widgetItem;
1099}
1100
1101#ifndef QT_NO_TABBAR
1102
1103quintptr QDockAreaLayoutInfo::currentTabId() const
1104{
1105 if (!tabbed || tabBar == 0)
1106 return 0;
1107
1108 int index = tabBar->currentIndex();
1109 if (index == -1)
1110 return 0;
1111
1112 return qvariant_cast<quintptr>(tabBar->tabData(index));
1113}
1114
1115void QDockAreaLayoutInfo::setCurrentTab(QWidget *widget)
1116{
1117 setCurrentTabId(reinterpret_cast<quintptr>(widget));
1118}
1119
1120void QDockAreaLayoutInfo::setCurrentTabId(quintptr id)
1121{
1122 if (!tabbed || tabBar == 0)
1123 return;
1124
1125 for (int i = 0; i < tabBar->count(); ++i) {
1126 if (qvariant_cast<quintptr>(tabBar->tabData(i)) == id) {
1127 tabBar->setCurrentIndex(i);
1128 return;
1129 }
1130 }
1131}
1132
1133#endif // QT_NO_TABBAR
1134
1135static QRect dockedGeometry(QWidget *widget)
1136{
1137 int titleHeight = 0;
1138
1139 QDockWidgetLayout *layout
1140 = qobject_cast<QDockWidgetLayout*>(widget->layout());
1141 if(layout != 0 && layout->nativeWindowDeco())
1142 titleHeight = layout->titleHeight();
1143
1144 QRect result = widget->geometry();
1145 result.adjust(0, -titleHeight, 0, 0);
1146 return result;
1147}
1148
1149bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
1150{
1151 Q_ASSERT(!path.isEmpty());
1152
1153 bool insert_tabbed = false;
1154 int index = path.first();
1155 if (index < 0) {
1156 insert_tabbed = true;
1157 index = -index - 1;
1158 }
1159
1160// dump(qDebug() << "insertGap() before:" << index << tabIndex, *this, QString());
1161
1162 if (path.count() > 1) {
1163 QDockAreaLayoutItem &item = item_list[index];
1164
1165 if (item.subinfo == 0
1166#ifndef QT_NO_TABBAR
1167 || (item.subinfo->tabbed && !insert_tabbed)
1168#endif
1169 ) {
1170
1171 // this is not yet a nested layout - make it
1172
1173 QDockAreaLayoutInfo *subinfo = item.subinfo;
1174 QLayoutItem *widgetItem = item.widgetItem;
1175 QPlaceHolderItem *placeHolderItem = item.placeHolderItem;
1176 QRect r = subinfo == 0 ? widgetItem ? dockedGeometry(widgetItem->widget()) : placeHolderItem->topLevelRect : subinfo->rect;
1177
1178 Qt::Orientation opposite = o == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal;
1179#ifdef QT_NO_TABBAR
1180 const int tabBarShape = 0;
1181#endif
1182 QDockAreaLayoutInfo *new_info
1183 = new QDockAreaLayoutInfo(sep, dockPos, opposite, tabBarShape, mainWindow);
1184
1185 //item become a new top-level
1186 item.subinfo = new_info;
1187 item.widgetItem = 0;
1188 item.placeHolderItem = 0;
1189
1190 QDockAreaLayoutItem new_item
1191 = widgetItem == 0
1192 ? QDockAreaLayoutItem(subinfo)
1193 : widgetItem ? QDockAreaLayoutItem(widgetItem) : QDockAreaLayoutItem(placeHolderItem);
1194 new_item.size = pick(opposite, r.size());
1195 new_item.pos = pick(opposite, r.topLeft());
1196 new_info->item_list.append(new_item);
1197#ifndef QT_NO_TABBAR
1198 if (insert_tabbed) {
1199 new_info->tabbed = true;
1200 }
1201#endif
1202 }
1203
1204 return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
1205 }
1206
1207 // create the gap item
1208 QDockAreaLayoutItem gap_item;
1209 gap_item.flags |= QDockAreaLayoutItem::GapItem;
1210 gap_item.widgetItem = dockWidgetItem; // so minimumSize(), maximumSize() and
1211 // sizeHint() will work
1212#ifndef QT_NO_TABBAR
1213 if (!tabbed)
1214#endif
1215 {
1216 int prev = this->prev(index);
1217 int next = this->next(index - 1);
1218 // find out how much space we have in the layout
1219 int space = 0;
1220 if (isEmpty()) {
1221 // I am an empty dock area, therefore I am a top-level dock area.
1222 switch (dockPos) {
1223 case QInternal::LeftDock:
1224 case QInternal::RightDock:
1225 if (o == Qt::Vertical) {
1226 // the "size" is the height of the dock area (remember we are empty)
1227 space = pick(Qt::Vertical, rect.size());
1228 } else {
1229 space = pick(Qt::Horizontal, dockWidgetItem->widget()->size());
1230 }
1231 break;
1232 case QInternal::TopDock:
1233 case QInternal::BottomDock:
1234 default:
1235 if (o == Qt::Horizontal) {
1236 // the "size" is width of the dock area
1237 space = pick(Qt::Horizontal, rect.size());
1238 } else {
1239 space = pick(Qt::Vertical, dockWidgetItem->widget()->size());
1240 }
1241 break;
1242 }
1243 } else {
1244 for (int i = 0; i < item_list.count(); ++i) {
1245 const QDockAreaLayoutItem &item = item_list.at(i);
1246 if (item.skip())
1247 continue;
1248 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
1249 space += item.size - pick(o, item.minimumSize());
1250 }
1251 }
1252
1253 // find the actual size of the gap
1254 int gap_size = 0;
1255 int sep_size = 0;
1256 if (isEmpty()) {
1257 gap_size = space;
1258 sep_size = 0;
1259 } else {
1260 QRect r = dockedGeometry(dockWidgetItem->widget());
1261 gap_size = pick(o, r.size());
1262 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
1263 sep_size += *sep;
1264 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1265 sep_size += *sep;
1266 }
1267 if (gap_size + sep_size > space)
1268 gap_size = pick(o, gap_item.minimumSize());
1269 gap_item.size = gap_size + sep_size;
1270 }
1271
1272 // finally, insert the gap
1273 item_list.insert(index, gap_item);
1274
1275// dump(qDebug() << "insertGap() after:" << index << tabIndex, *this, QString());
1276
1277 return true;
1278}
1279
1280QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
1281{
1282 for (int i = 0; i < item_list.count(); ++i) {
1283 const QDockAreaLayoutItem &item = item_list.at(i);
1284 if (item.skip())
1285 continue;
1286
1287#ifndef QT_NO_TABBAR
1288 if (tabbed && widget == tabBar)
1289 return this;
1290#endif
1291
1292 if (item.widgetItem != 0 && item.widgetItem->widget() == widget)
1293 return this;
1294
1295 if (item.subinfo != 0) {
1296 if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
1297 return result;
1298 }
1299 }
1300
1301 return 0;
1302}
1303
1304QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(const QList<int> &path)
1305{
1306 int index = path.first();
1307 if (index < 0)
1308 index = -index - 1;
1309 if (index >= item_list.count())
1310 return this;
1311 if (path.count() == 1 || item_list[index].subinfo == 0)
1312 return this;
1313 return item_list[index].subinfo->info(path.mid(1));
1314}
1315
1316QRect QDockAreaLayoutInfo::itemRect(int index) const
1317{
1318 const QDockAreaLayoutItem &item = item_list.at(index);
1319
1320 if (item.skip())
1321 return QRect();
1322
1323 QRect result;
1324
1325#ifndef QT_NO_TABBAR
1326 if (tabbed) {
1327 if (tabId(item) == currentTabId())
1328 result = tabContentRect();
1329 } else
1330#endif
1331 {
1332 QPoint pos;
1333 rpick(o, pos) = item.pos;
1334 rperp(o, pos) = perp(o, rect.topLeft());
1335 QSize s;
1336 rpick(o, s) = item.size;
1337 rperp(o, s) = perp(o, rect.size());
1338 result = QRect(pos, s);
1339 }
1340
1341 return result;
1342}
1343
1344QRect QDockAreaLayoutInfo::itemRect(const QList<int> &path) const
1345{
1346 Q_ASSERT(!path.isEmpty());
1347
1348 const int index = path.first();
1349 if (path.count() > 1) {
1350 const QDockAreaLayoutItem &item = item_list.at(index);
1351 Q_ASSERT(item.subinfo != 0);
1352 return item.subinfo->itemRect(path.mid(1));
1353 }
1354
1355 return itemRect(index);
1356}
1357
1358QRect QDockAreaLayoutInfo::separatorRect(int index) const
1359{
1360#ifndef QT_NO_TABBAR
1361 if (tabbed)
1362 return QRect();
1363#endif
1364
1365 const QDockAreaLayoutItem &item = item_list.at(index);
1366 if (item.skip())
1367 return QRect();
1368
1369 QPoint pos = rect.topLeft();
1370 rpick(o, pos) = item.pos + item.size;
1371 QSize s = rect.size();
1372 rpick(o, s) = *sep;
1373
1374 return QRect(pos, s);
1375}
1376
1377QRect QDockAreaLayoutInfo::separatorRect(const QList<int> &path) const
1378{
1379 Q_ASSERT(!path.isEmpty());
1380
1381 const int index = path.first();
1382 if (path.count() > 1) {
1383 const QDockAreaLayoutItem &item = item_list.at(index);
1384 Q_ASSERT(item.subinfo != 0);
1385 return item.subinfo->separatorRect(path.mid(1));
1386 }
1387 return separatorRect(index);
1388}
1389
1390QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
1391{
1392#ifndef QT_NO_TABBAR
1393 if (tabbed)
1394 return QList<int>();
1395#endif
1396
1397 int pos = pick(o, _pos);
1398
1399 for (int i = 0; i < item_list.size(); ++i) {
1400 const QDockAreaLayoutItem &item = item_list.at(i);
1401 if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
1402 continue;
1403
1404 if (item.pos + item.size > pos) {
1405 if (item.subinfo != 0) {
1406 QList<int> result = item.subinfo->findSeparator(_pos);
1407 if (!result.isEmpty()) {
1408 result.prepend(i);
1409 return result;
1410 } else {
1411 return QList<int>();
1412 }
1413 }
1414 }
1415
1416 int next = this->next(i);
1417 if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1418 continue;
1419
1420 QRect sepRect = separatorRect(i);
1421 if (!sepRect.isNull() && *sep == 1)
1422 sepRect.adjust(-2, -2, 2, 2);
1423 //we also make sure we don't find a separator that's not there
1424 if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
1425 return QList<int>() << i;
1426 }
1427
1428 }
1429
1430 return QList<int>();
1431}
1432
1433QList<int> QDockAreaLayoutInfo::indexOfPlaceHolder(const QString &objectName) const
1434{
1435 for (int i = 0; i < item_list.size(); ++i) {
1436 const QDockAreaLayoutItem &item = item_list.at(i);
1437
1438 if (item.subinfo != 0) {
1439 QList<int> result = item.subinfo->indexOfPlaceHolder(objectName);
1440 if (!result.isEmpty()) {
1441 result.prepend(i);
1442 return result;
1443 }
1444 continue;
1445 }
1446
1447 if (item.placeHolderItem != 0 && item.placeHolderItem->objectName == objectName) {
1448 QList<int> result;
1449 result << i;
1450 return result;
1451 }
1452 }
1453
1454 return QList<int>();
1455}
1456
1457QList<int> QDockAreaLayoutInfo::indexOf(QWidget *widget) const
1458{
1459 for (int i = 0; i < item_list.size(); ++i) {
1460 const QDockAreaLayoutItem &item = item_list.at(i);
1461
1462 if (item.placeHolderItem != 0)
1463 continue;
1464
1465 if (item.subinfo != 0) {
1466 QList<int> result = item.subinfo->indexOf(widget);
1467 if (!result.isEmpty()) {
1468 result.prepend(i);
1469 return result;
1470 }
1471 continue;
1472 }
1473
1474 if (!(item.flags & QDockAreaLayoutItem::GapItem) && item.widgetItem->widget() == widget) {
1475 QList<int> result;
1476 result << i;
1477 return result;
1478 }
1479 }
1480
1481 return QList<int>();
1482}
1483
1484QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout() const
1485{
1486 QMainWindowLayout *result = qt_mainwindow_layout(mainWindow);
1487 Q_ASSERT(result != 0);
1488 return result;
1489}
1490
1491bool QDockAreaLayoutInfo::hasFixedSize() const
1492{
1493 return perp(o, minimumSize()) == perp(o, maximumSize());
1494}
1495
1496
1497void QDockAreaLayoutInfo::apply(bool animate)
1498{
1499 QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
1500
1501#ifndef QT_NO_TABBAR
1502 if (tabbed) {
1503 QRect tab_rect;
1504 QSize tbh = tabBarSizeHint();
1505
1506 if (!tbh.isNull()) {
1507 switch (tabBarShape) {
1508 case QTabBar::RoundedNorth:
1509 case QTabBar::TriangularNorth:
1510 tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
1511 break;
1512 case QTabBar::RoundedSouth:
1513 case QTabBar::TriangularSouth:
1514 tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
1515 rect.width(), tbh.height());
1516 break;
1517 case QTabBar::RoundedEast:
1518 case QTabBar::TriangularEast:
1519 tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
1520 tbh.width(), rect.height());
1521 break;
1522 case QTabBar::RoundedWest:
1523 case QTabBar::TriangularWest:
1524 tab_rect = QRect(rect.left(), rect.top(),
1525 tbh.width(), rect.height());
1526 break;
1527 default:
1528 break;
1529 }
1530 }
1531
1532 widgetAnimator.animate(tabBar, tab_rect, animate);
1533 }
1534#endif // QT_NO_TABBAR
1535
1536 for (int i = 0; i < item_list.size(); ++i) {
1537 QDockAreaLayoutItem &item = item_list[i];
1538
1539 if (item.flags & QDockAreaLayoutItem::GapItem)
1540 continue;
1541
1542 if (item.subinfo != 0) {
1543 item.subinfo->apply(animate);
1544 continue;
1545 }
1546
1547 if (item.skip())
1548 continue;
1549
1550 Q_ASSERT(item.widgetItem);
1551 QRect r = itemRect(i);
1552 QWidget *w = item.widgetItem->widget();
1553
1554 QRect geo = w->geometry();
1555 widgetAnimator.animate(w, r, animate);
1556 if (!w->isHidden() && w->window()->isVisible()) {
1557 QDockWidget *dw = qobject_cast<QDockWidget*>(w);
1558 if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
1559 dw->lower();
1560 emit dw->visibilityChanged(false);
1561 } else if (r.isValid()
1562 && (geo.right() < 0 || geo.bottom() < 0)) {
1563 emit dw->visibilityChanged(true);
1564 }
1565 }
1566 }
1567#ifndef QT_NO_TABBAR
1568 if (*sep == 1)
1569 updateSeparatorWidgets();
1570#endif //QT_NO_TABBAR
1571}
1572
1573static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
1574{
1575 QStyleOption opt(0);
1576 opt.state = QStyle::State_None;
1577 if (w->isEnabled())
1578 opt.state |= QStyle::State_Enabled;
1579 if (o != Qt::Horizontal)
1580 opt.state |= QStyle::State_Horizontal;
1581 if (mouse_over)
1582 opt.state |= QStyle::State_MouseOver;
1583 opt.rect = r;
1584 opt.palette = w->palette();
1585
1586 w->style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p, w);
1587}
1588
1589QRegion QDockAreaLayoutInfo::separatorRegion() const
1590{
1591 QRegion result;
1592
1593 if (isEmpty())
1594 return result;
1595#ifndef QT_NO_TABBAR
1596 if (tabbed)
1597 return result;
1598#endif
1599
1600 for (int i = 0; i < item_list.count(); ++i) {
1601 const QDockAreaLayoutItem &item = item_list.at(i);
1602
1603 if (item.skip())
1604 continue;
1605
1606 int next = this->next(i);
1607
1608 if (item.subinfo)
1609 result |= item.subinfo->separatorRegion();
1610
1611 if (next == -1)
1612 break;
1613 result |= separatorRect(i);
1614 }
1615
1616 return result;
1617}
1618
1619void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
1620 const QRegion &clip,
1621 const QPoint &mouse) const
1622{
1623 if (isEmpty())
1624 return;
1625#ifndef QT_NO_TABBAR
1626 if (tabbed)
1627 return;
1628#endif
1629
1630 for (int i = 0; i < item_list.count(); ++i) {
1631 const QDockAreaLayoutItem &item = item_list.at(i);
1632
1633 if (item.skip())
1634 continue;
1635
1636 int next = this->next(i);
1637 if ((item.flags & QDockAreaLayoutItem::GapItem)
1638 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
1639 continue;
1640
1641 if (item.subinfo) {
1642 if (clip.contains(item.subinfo->rect))
1643 item.subinfo->paintSeparators(p, widget, clip, mouse);
1644 }
1645
1646 if (next == -1)
1647 break;
1648 QRect r = separatorRect(i);
1649 if (clip.contains(r) && !item.hasFixedSize(o))
1650 paintSep(p, widget, r, o, r.contains(mouse));
1651 }
1652}
1653
1654int QDockAreaLayoutInfo::next(int index) const
1655{
1656 for (int i = index + 1; i < item_list.size(); ++i) {
1657 if (!item_list.at(i).skip())
1658 return i;
1659 }
1660 return -1;
1661}
1662
1663int QDockAreaLayoutInfo::prev(int index) const
1664{
1665 for (int i = index - 1; i >= 0; --i) {
1666 if (!item_list.at(i).skip())
1667 return i;
1668 }
1669 return -1;
1670}
1671
1672void QDockAreaLayoutInfo::tab(int index, QLayoutItem *dockWidgetItem)
1673{
1674#ifdef QT_NO_TABBAR
1675 Q_UNUSED(index);
1676 Q_UNUSED(dockWidgetItem);
1677#else
1678 if (tabbed) {
1679 item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1680 updateTabBar();
1681 setCurrentTab(dockWidgetItem->widget());
1682 } else {
1683 QDockAreaLayoutInfo *new_info
1684 = new QDockAreaLayoutInfo(sep, dockPos, o, tabBarShape, mainWindow);
1685 item_list[index].subinfo = new_info;
1686 new_info->item_list.append(item_list.at(index).widgetItem);
1687 item_list[index].widgetItem = 0;
1688 new_info->item_list.append(dockWidgetItem);
1689 new_info->tabbed = true;
1690 new_info->updateTabBar();
1691 new_info->setCurrentTab(dockWidgetItem->widget());
1692 }
1693#endif // QT_NO_TABBAR
1694}
1695
1696void QDockAreaLayoutInfo::split(int index, Qt::Orientation orientation,
1697 QLayoutItem *dockWidgetItem)
1698{
1699 if (orientation == o) {
1700 item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
1701 } else {
1702#ifdef QT_NO_TABBAR
1703 const int tabBarShape = 0;
1704#endif
1705 QDockAreaLayoutInfo *new_info
1706 = new QDockAreaLayoutInfo(sep, dockPos, orientation, tabBarShape, mainWindow);
1707 item_list[index].subinfo = new_info;
1708 new_info->item_list.append(item_list.at(index).widgetItem);
1709 item_list[index].widgetItem = 0;
1710 new_info->item_list.append(dockWidgetItem);
1711 }
1712}
1713
1714QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList<int> &path)
1715{
1716 Q_ASSERT(!path.isEmpty());
1717 const int index = path.first();
1718 if (path.count() > 1) {
1719 const QDockAreaLayoutItem &item = item_list[index];
1720 Q_ASSERT(item.subinfo != 0);
1721 return item.subinfo->item(path.mid(1));
1722 }
1723 return item_list[index];
1724}
1725
1726QLayoutItem *QDockAreaLayoutInfo::itemAt(int *x, int index) const
1727{
1728 for (int i = 0; i < item_list.count(); ++i) {
1729 const QDockAreaLayoutItem &item = item_list.at(i);
1730 if (item.placeHolderItem != 0)
1731 continue;
1732 if (item.subinfo) {
1733 if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
1734 return ret;
1735 } else if (item.widgetItem) {
1736 if ((*x)++ == index)
1737 return item.widgetItem;
1738 }
1739 }
1740 return 0;
1741}
1742
1743QLayoutItem *QDockAreaLayoutInfo::takeAt(int *x, int index)
1744{
1745 for (int i = 0; i < item_list.count(); ++i) {
1746 QDockAreaLayoutItem &item = item_list[i];
1747 if (item.placeHolderItem != 0)
1748 continue;
1749 else if (item.subinfo) {
1750 if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
1751 unnest(i);
1752 return ret;
1753 }
1754 } else if (item.widgetItem) {
1755 if ((*x)++ == index) {
1756 item.placeHolderItem = new QPlaceHolderItem(item.widgetItem->widget());
1757 QLayoutItem *ret = item.widgetItem;
1758 item.widgetItem = 0;
1759 if (item.size != -1)
1760 item.flags |= QDockAreaLayoutItem::KeepSize;
1761 return ret;
1762 }
1763 }
1764 }
1765 return 0;
1766}
1767
1768void QDockAreaLayoutInfo::deleteAllLayoutItems()
1769{
1770 for (int i = 0; i < item_list.count(); ++i) {
1771 QDockAreaLayoutItem &item= item_list[i];
1772 if (item.subinfo) {
1773 item.subinfo->deleteAllLayoutItems();
1774 } else {
1775 delete item.widgetItem;
1776 item.widgetItem = 0;
1777 }
1778 }
1779}
1780
1781void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
1782{
1783#ifndef QT_NO_TABBAR
1784 if (tabbed) {
1785 stream << (uchar) TabMarker;
1786
1787 // write the index in item_list of the widget that's currently on top.
1788 quintptr id = currentTabId();
1789 int index = -1;
1790 for (int i = 0; i < item_list.count(); ++i) {
1791 if (tabId(item_list.at(i)) == id) {
1792 index = i;
1793 break;
1794 }
1795 }
1796 stream << index;
1797 } else
1798#endif // QT_NO_TABBAR
1799 {
1800 stream << (uchar) SequenceMarker;
1801 }
1802
1803 stream << (uchar) o << item_list.count();
1804
1805 for (int i = 0; i < item_list.count(); ++i) {
1806 const QDockAreaLayoutItem &item = item_list.at(i);
1807 if (item.widgetItem != 0) {
1808 stream << (uchar) WidgetMarker;
1809 QWidget *w = item.widgetItem->widget();
1810 QString name = w->objectName();
1811 if (name.isEmpty()) {
1812 qWarning("QMainWindow::saveState(): 'objectName' not set for QDockWidget %p '%s;",
1813 w, qPrintable(w->windowTitle()));
1814 }
1815 stream << name;
1816
1817 uchar flags = 0;
1818 if (!w->isHidden())
1819 flags |= StateFlagVisible;
1820 if (w->isWindow())
1821 flags |= StateFlagFloating;
1822 stream << flags;
1823
1824 if (w->isWindow()) {
1825 stream << w->x() << w->y() << w->width() << w->height();
1826 } else {
1827 stream << item.pos << item.size << pick(o, item.minimumSize())
1828 << pick(o, item.maximumSize());
1829 }
1830 } else if (item.placeHolderItem != 0) {
1831 stream << (uchar) WidgetMarker;
1832 stream << item.placeHolderItem->objectName;
1833 uchar flags = 0;
1834 if (!item.placeHolderItem->hidden)
1835 flags |= StateFlagVisible;
1836 if (item.placeHolderItem->window)
1837 flags |= StateFlagFloating;
1838 stream << flags;
1839 if (item.placeHolderItem->window) {
1840 QRect r = item.placeHolderItem->topLevelRect;
1841 stream << r.x() << r.y() << r.width() << r.height();
1842 } else {
1843 stream << item.pos << item.size << (int)0 << (int)0;
1844 }
1845 } else if (item.subinfo != 0) {
1846 stream << (uchar) SequenceMarker << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
1847 item.subinfo->saveState(stream);
1848 }
1849 }
1850}
1851
1852static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
1853{
1854 switch (pos) {
1855 case QInternal::LeftDock: return Qt::LeftDockWidgetArea;
1856 case QInternal::RightDock: return Qt::RightDockWidgetArea;
1857 case QInternal::TopDock: return Qt::TopDockWidgetArea;
1858 case QInternal::BottomDock: return Qt::BottomDockWidgetArea;
1859 default: break;
1860 }
1861 return Qt::NoDockWidgetArea;
1862}
1863
1864static QRect constrainedRect(QRect rect, const QRect &desktop)
1865{
1866 if (desktop.isValid()) {
1867 rect.setWidth(qMin(rect.width(), desktop.width()));
1868 rect.setHeight(qMin(rect.height(), desktop.height()));
1869 rect.moveLeft(qMax(rect.left(), desktop.left()));
1870 rect.moveTop(qMax(rect.top(), desktop.top()));
1871 rect.moveRight(qMin(rect.right(), desktop.right()));
1872 rect.moveBottom(qMin(rect.bottom(), desktop.bottom()));
1873 }
1874
1875 return rect;
1876}
1877
1878bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> &widgets, bool testing)
1879{
1880 uchar marker;
1881 stream >> marker;
1882 if (marker != TabMarker && marker != SequenceMarker)
1883 return false;
1884
1885#ifndef QT_NO_TABBAR
1886 tabbed = marker == TabMarker;
1887
1888 int index = -1;
1889 if (tabbed)
1890 stream >> index;
1891#endif
1892
1893 uchar orientation;
1894 stream >> orientation;
1895 o = static_cast<Qt::Orientation>(orientation);
1896
1897 int cnt;
1898 stream >> cnt;
1899
1900 for (int i = 0; i < cnt; ++i) {
1901 uchar nextMarker;
1902 stream >> nextMarker;
1903 if (nextMarker == WidgetMarker) {
1904 QString name;
1905 uchar flags;
1906 stream >> name >> flags;
1907 if (name.isEmpty()) {
1908 int dummy;
1909 stream >> dummy >> dummy >> dummy >> dummy;
1910 continue;
1911 }
1912
1913 QDockWidget *widget = 0;
1914 for (int j = 0; j < widgets.count(); ++j) {
1915 if (widgets.at(j)->objectName() == name) {
1916 widget = widgets.takeAt(j);
1917 break;
1918 }
1919 }
1920
1921 if (widget == 0) {
1922 QPlaceHolderItem *placeHolder = new QPlaceHolderItem;
1923 QDockAreaLayoutItem item(placeHolder);
1924
1925 placeHolder->objectName = name;
1926 placeHolder->window = flags & StateFlagFloating;
1927 placeHolder->hidden = !(flags & StateFlagVisible);
1928 if (placeHolder->window) {
1929 int x, y, w, h;
1930 stream >> x >> y >> w >> h;
1931 placeHolder->topLevelRect = QRect(x, y, w, h);
1932 } else {
1933 int dummy;
1934 stream >> item.pos >> item.size >> dummy >> dummy;
1935 }
1936 if (item.size != -1)
1937 item.flags |= QDockAreaLayoutItem::KeepSize;
1938 if (!testing)
1939 item_list.append(item);
1940 } else {
1941 QDockAreaLayoutItem item(new QDockWidgetItem(widget));
1942 if (flags & StateFlagFloating) {
1943 bool drawer = false;
1944#ifdef Q_WS_MAC // drawer support
1945 extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
1946 extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp
1947 drawer = qt_mac_is_macdrawer(widget);
1948#endif
1949
1950 if (!testing) {
1951 widget->hide();
1952 if (!drawer)
1953 widget->setFloating(true);
1954 }
1955
1956 int x, y, w, h;
1957 stream >> x >> y >> w >> h;
1958
1959#ifdef Q_WS_MAC // drawer support
1960 if (drawer) {
1961 mainWindow->window()->createWinId();
1962 widget->window()->createWinId();
1963 qt_mac_set_drawer_preferred_edge(widget, toDockWidgetArea(dockPos));
1964 } else
1965#endif
1966 if (!testing) {
1967 QRect r(x, y, w, h);
1968 QDesktopWidget *desktop = QApplication::desktop();
1969 if (desktop->isVirtualDesktop())
1970 r = constrainedRect(r, desktop->screenGeometry(desktop->screenNumber(r.topLeft())));
1971 else
1972 r = constrainedRect(r, desktop->screenGeometry(widget));
1973 widget->move(r.topLeft());
1974 widget->resize(r.size());
1975 }
1976
1977 if (!testing) {
1978 widget->setVisible(flags & StateFlagVisible);
1979 item_list.append(item);
1980 }
1981 } else {
1982 int dummy;
1983 stream >> item.pos >> item.size >> dummy >> dummy;
1984 if (!testing) {
1985 item_list.append(item);
1986 widget->setFloating(false);
1987 widget->setVisible(flags & StateFlagVisible);
1988 emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
1989 }
1990 }
1991 if (testing) {
1992 //was it is not really added to the layout, we need to delete the object here
1993 delete item.widgetItem;
1994 }
1995 }
1996 } else if (nextMarker == SequenceMarker) {
1997 int dummy;
1998#ifdef QT_NO_TABBAR
1999 const int tabBarShape = 0;
2000#endif
2001 QDockAreaLayoutItem item(new QDockAreaLayoutInfo(sep, dockPos, o,
2002 tabBarShape, mainWindow));
2003 stream >> item.pos >> item.size >> dummy >> dummy;
2004 //we need to make sure the element is in the list so the dock widget can eventually be docked correctly
2005 if (!testing)
2006 item_list.append(item);
2007
2008 //here we need to make sure we change the item in the item_list
2009 QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
2010
2011 if (!lastItem.subinfo->restoreState(stream, widgets, testing))
2012 return false;
2013
2014 } else {
2015 return false;
2016 }
2017 }
2018
2019#ifndef QT_NO_TABBAR
2020 if (!testing && tabbed && index >= 0 && index < item_list.count()) {
2021 updateTabBar();
2022 setCurrentTabId(tabId(item_list.at(index)));
2023 }
2024 if (!testing && *sep == 1)
2025 updateSeparatorWidgets();
2026#endif
2027
2028 return true;
2029}
2030
2031#ifndef QT_NO_TABBAR
2032void QDockAreaLayoutInfo::updateSeparatorWidgets() const
2033{
2034 if (tabbed) {
2035 separatorWidgets.clear();
2036 return;
2037 }
2038
2039 int j = 0;
2040 for (int i = 0; i < item_list.count(); ++i) {
2041 const QDockAreaLayoutItem &item = item_list.at(i);
2042
2043 if (item.skip())
2044 continue;
2045
2046 int next = this->next(i);
2047 if ((item.flags & QDockAreaLayoutItem::GapItem)
2048 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
2049 continue;
2050
2051 if (item.subinfo) {
2052 item.subinfo->updateSeparatorWidgets();
2053 }
2054
2055 if (next == -1)
2056 break;
2057
2058 QWidget *sepWidget;
2059 if (j < separatorWidgets.size() && separatorWidgets.at(j)) {
2060 sepWidget = separatorWidgets.at(j);
2061 } else {
2062 sepWidget = mainWindowLayout()->getSeparatorWidget();
2063 separatorWidgets.append(sepWidget);
2064 }
2065 j++;
2066
2067#ifndef QT_MAC_USE_COCOA
2068 sepWidget->raise();
2069#endif
2070 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
2071 sepWidget->setGeometry(sepRect);
2072 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
2073 sepWidget->show();
2074 }
2075
2076 for (int k = j; k < separatorWidgets.size(); ++k) {
2077 separatorWidgets[k]->hide();
2078 }
2079 separatorWidgets.resize(j);
2080 Q_ASSERT(separatorWidgets.size() == j);
2081}
2082#endif //QT_NO_TABBAR
2083
2084#ifndef QT_NO_TABBAR
2085//returns whether the tabbar is visible or not
2086bool QDockAreaLayoutInfo::updateTabBar() const
2087{
2088 if (!tabbed)
2089 return false;
2090
2091 QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
2092
2093 if (that->tabBar == 0) {
2094 that->tabBar = mainWindowLayout()->getTabBar();
2095 that->tabBar->setShape(static_cast<QTabBar::Shape>(tabBarShape));
2096 that->tabBar->setDrawBase(true);
2097 }
2098
2099 bool blocked = tabBar->blockSignals(true);
2100 bool gap = false;
2101
2102 int tab_idx = 0;
2103 bool changed = false;
2104 for (int i = 0; i < item_list.count(); ++i) {
2105 const QDockAreaLayoutItem &item = item_list.at(i);
2106 if (item.skip())
2107 continue;
2108 if (item.flags & QDockAreaLayoutItem::GapItem) {
2109 gap = true;
2110 continue;
2111 }
2112 if (item.widgetItem == 0)
2113 continue;
2114
2115 QDockWidget *dw = qobject_cast<QDockWidget*>(item.widgetItem->widget());
2116 QString title = dw->d_func()->fixedWindowTitle;
2117 quintptr id = tabId(item);
2118 if (tab_idx == tabBar->count()) {
2119 tabBar->insertTab(tab_idx, title);
2120#ifndef QT_NO_TOOLTIP
2121 tabBar->setTabToolTip(tab_idx, title);
2122#endif
2123 tabBar->setTabData(tab_idx, id);
2124 changed = true;
2125 } else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
2126 if (tab_idx + 1 < tabBar->count()
2127 && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
2128 tabBar->removeTab(tab_idx);
2129 else {
2130 tabBar->insertTab(tab_idx, title);
2131#ifndef QT_NO_TOOLTIP
2132 tabBar->setTabToolTip(tab_idx, title);
2133#endif
2134 tabBar->setTabData(tab_idx, id);
2135 }
2136 changed = true;
2137 }
2138
2139 if (title != tabBar->tabText(tab_idx)) {
2140 tabBar->setTabText(tab_idx, title);
2141#ifndef QT_NO_TOOLTIP
2142 tabBar->setTabToolTip(tab_idx, title);
2143#endif
2144 changed = true;
2145 }
2146
2147 ++tab_idx;
2148 }
2149
2150 while (tab_idx < tabBar->count()) {
2151 tabBar->removeTab(tab_idx);
2152 changed = true;
2153 }
2154
2155 tabBar->blockSignals(blocked);
2156
2157 //returns if the tabbar is visible or not
2158 return ( (gap ? 1 : 0) + tabBar->count()) > 1;
2159}
2160
2161void QDockAreaLayoutInfo::setTabBarShape(int shape)
2162{
2163 if (shape == tabBarShape)
2164 return;
2165 tabBarShape = shape;
2166 if (tabBar != 0)
2167 tabBar->setShape(static_cast<QTabBar::Shape>(shape));
2168
2169 for (int i = 0; i < item_list.count(); ++i) {
2170 QDockAreaLayoutItem &item = item_list[i];
2171 if (item.subinfo != 0)
2172 item.subinfo->setTabBarShape(shape);
2173 }
2174}
2175
2176QSize QDockAreaLayoutInfo::tabBarMinimumSize() const
2177{
2178 if (!updateTabBar())
2179 return QSize(0, 0);
2180
2181 return tabBar->minimumSizeHint();
2182}
2183
2184QSize QDockAreaLayoutInfo::tabBarSizeHint() const
2185{
2186 if (!updateTabBar())
2187 return QSize(0, 0);
2188
2189 return tabBar->sizeHint();
2190}
2191
2192QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars() const
2193{
2194 QSet<QTabBar*> result;
2195
2196 if (tabbed) {
2197 updateTabBar();
2198 result.insert(tabBar);
2199 }
2200
2201 for (int i = 0; i < item_list.count(); ++i) {
2202 const QDockAreaLayoutItem &item = item_list.at(i);
2203 if (item.subinfo != 0)
2204 result += item.subinfo->usedTabBars();
2205 }
2206
2207 return result;
2208}
2209
2210// returns a set of all used separator widgets for this dockarelayout info
2211// and all subinfos
2212QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
2213{
2214 QSet<QWidget*> result;
2215
2216 for (int i = 0; i < separatorWidgets.count(); ++i)
2217 result << separatorWidgets.at(i);
2218
2219 for (int i = 0; i < item_list.count(); ++i) {
2220 const QDockAreaLayoutItem &item = item_list.at(i);
2221 if (item.subinfo != 0)
2222 result += item.subinfo->usedSeparatorWidgets();
2223 }
2224
2225 return result;
2226}
2227
2228QRect QDockAreaLayoutInfo::tabContentRect() const
2229{
2230 if (!tabbed)
2231 return QRect();
2232
2233 QRect result = rect;
2234 QSize tbh = tabBarSizeHint();
2235
2236 if (!tbh.isNull()) {
2237 switch (tabBarShape) {
2238 case QTabBar::RoundedNorth:
2239 case QTabBar::TriangularNorth:
2240 result.adjust(0, tbh.height(), 0, 0);
2241 break;
2242 case QTabBar::RoundedSouth:
2243 case QTabBar::TriangularSouth:
2244 result.adjust(0, 0, 0, -tbh.height());
2245 break;
2246 case QTabBar::RoundedEast:
2247 case QTabBar::TriangularEast:
2248 result.adjust(0, 0, -tbh.width(), 0);
2249 break;
2250 case QTabBar::RoundedWest:
2251 case QTabBar::TriangularWest:
2252 result.adjust(tbh.width(), 0, 0, 0);
2253 break;
2254 default:
2255 break;
2256 }
2257 }
2258
2259 return result;
2260}
2261#endif // QT_NO_TABBAR
2262
2263/******************************************************************************
2264** QDockAreaLayout
2265*/
2266
2267QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true)
2268{
2269 mainWindow = win;
2270 sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, win);
2271#ifndef QT_NO_TABBAR
2272 const int tabShape = QTabBar::RoundedSouth;
2273#else
2274 const int tabShape = 0;
2275#endif
2276 docks[QInternal::LeftDock]
2277 = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
2278 docks[QInternal::RightDock]
2279 = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
2280 docks[QInternal::TopDock]
2281 = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
2282 docks[QInternal::BottomDock]
2283 = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
2284 centralWidgetItem = 0;
2285
2286
2287 corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
2288 corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
2289 corners[Qt::BottomLeftCorner] = Qt::BottomDockWidgetArea;
2290 corners[Qt::BottomRightCorner] = Qt::BottomDockWidgetArea;
2291}
2292
2293bool QDockAreaLayout::isValid() const
2294{
2295 return rect.isValid();
2296}
2297
2298void QDockAreaLayout::saveState(QDataStream &stream) const
2299{
2300 stream << (uchar) DockWidgetStateMarker;
2301 int cnt = 0;
2302 for (int i = 0; i < QInternal::DockCount; ++i) {
2303 if (!docks[i].item_list.isEmpty())
2304 ++cnt;
2305 }
2306 stream << cnt;
2307 for (int i = 0; i < QInternal::DockCount; ++i) {
2308 if (docks[i].item_list.isEmpty())
2309 continue;
2310 stream << i << docks[i].rect.size();
2311 docks[i].saveState(stream);
2312 }
2313
2314 stream << centralWidgetRect.size();
2315
2316 for (int i = 0; i < 4; ++i)
2317 stream << static_cast<int>(corners[i]);
2318}
2319
2320bool QDockAreaLayout::restoreState(QDataStream &stream, const QList<QDockWidget*> &_dockwidgets, bool testing)
2321{
2322 QList<QDockWidget*> dockwidgets = _dockwidgets;
2323
2324 int cnt;
2325 stream >> cnt;
2326 for (int i = 0; i < cnt; ++i) {
2327 int pos;
2328 stream >> pos;
2329 QSize size;
2330 stream >> size;
2331 if (!testing) {
2332 docks[pos].rect = QRect(QPoint(0, 0), size);
2333 }
2334 if (!docks[pos].restoreState(stream, dockwidgets, testing)) {
2335 stream.setStatus(QDataStream::ReadCorruptData);
2336 return false;
2337 }
2338 }
2339
2340 QSize size;
2341 stream >> size;
2342 centralWidgetRect = QRect(QPoint(0, 0), size);
2343
2344 bool ok = stream.status() == QDataStream::Ok;
2345
2346 if (ok) {
2347 int cornerData[4];
2348 for (int i = 0; i < 4; ++i)
2349 stream >> cornerData[i];
2350 if (stream.status() == QDataStream::Ok) {
2351 for (int i = 0; i < 4; ++i)
2352 corners[i] = static_cast<Qt::DockWidgetArea>(cornerData[i]);
2353 }
2354
2355 if (!testing)
2356 fallbackToSizeHints = false;
2357 }
2358
2359 return ok;
2360}
2361
2362QList<int> QDockAreaLayout::indexOfPlaceHolder(const QString &objectName) const
2363{
2364 for (int i = 0; i < QInternal::DockCount; ++i) {
2365 QList<int> result = docks[i].indexOfPlaceHolder(objectName);
2366 if (!result.isEmpty()) {
2367 result.prepend(i);
2368 return result;
2369 }
2370 }
2371 return QList<int>();
2372}
2373
2374QList<int> QDockAreaLayout::indexOf(QWidget *dockWidget) const
2375{
2376 for (int i = 0; i < QInternal::DockCount; ++i) {
2377 QList<int> result = docks[i].indexOf(dockWidget);
2378 if (!result.isEmpty()) {
2379 result.prepend(i);
2380 return result;
2381 }
2382 }
2383 return QList<int>();
2384}
2385
2386QList<int> QDockAreaLayout::gapIndex(const QPoint &pos) const
2387{
2388 QMainWindow::DockOptions opts = mainWindow->dockOptions();
2389 bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
2390 QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs;
2391#ifndef QT_NO_TABBAR
2392 if (opts & QMainWindow::AllowTabbedDocks
2393 || opts & QMainWindow::VerticalTabs)
2394 tabMode = QDockAreaLayoutInfo::AllowTabs;
2395 if (opts & QMainWindow::ForceTabbedDocks)
2396 tabMode = QDockAreaLayoutInfo::ForceTabs;
2397
2398 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
2399 nestingEnabled = false;
2400#endif
2401
2402
2403 for (int i = 0; i < QInternal::DockCount; ++i) {
2404 const QDockAreaLayoutInfo &info = docks[i];
2405
2406 if (!info.isEmpty() && info.rect.contains(pos)) {
2407 QList<int> result
2408 = docks[i].gapIndex(pos, nestingEnabled, tabMode);
2409 if (!result.isEmpty())
2410 result.prepend(i);
2411 return result;
2412 }
2413 }
2414
2415 for (int i = 0; i < QInternal::DockCount; ++i) {
2416 const QDockAreaLayoutInfo &info = docks[i];
2417
2418 if (info.isEmpty()) {
2419 QRect r;
2420 switch (i) {
2421 case QInternal::LeftDock:
2422 r = QRect(rect.left(), rect.top(), EmptyDropAreaSize, rect.height());
2423 break;
2424 case QInternal::RightDock:
2425 r = QRect(rect.right() - EmptyDropAreaSize, rect.top(),
2426 EmptyDropAreaSize, rect.height());
2427 break;
2428 case QInternal::TopDock:
2429 r = QRect(rect.left(), rect.top(), rect.width(), EmptyDropAreaSize);
2430 break;
2431 case QInternal::BottomDock:
2432 r = QRect(rect.left(), rect.bottom() - EmptyDropAreaSize,
2433 rect.width(), EmptyDropAreaSize);
2434 break;
2435 }
2436 if (r.contains(pos)) {
2437 if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
2438 //in case of ForceTabbedDocks, we pass -1 in order to force the gap to be tabbed
2439 //it mustn't be completely empty otherwise it won't work
2440 return QList<int>() << i << -1 << 0;
2441 } else {
2442 return QList<int>() << i << 0;
2443 }
2444 }
2445 }
2446 }
2447
2448 return QList<int>();
2449}
2450
2451QList<int> QDockAreaLayout::findSeparator(const QPoint &pos) const
2452{
2453 QList<int> result;
2454 for (int i = 0; i < QInternal::DockCount; ++i) {
2455 const QDockAreaLayoutInfo &info = docks[i];
2456 if (info.isEmpty())
2457 continue;
2458 QRect rect = separatorRect(i);
2459 if (!rect.isNull() && sep == 1)
2460 rect.adjust(-2, -2, 2, 2);
2461 if (rect.contains(pos) && !info.hasFixedSize()) {
2462 result << i;
2463 break;
2464 } else if (info.rect.contains(pos)) {
2465 result = docks[i].findSeparator(pos);
2466 if (!result.isEmpty()) {
2467 result.prepend(i);
2468 break;
2469 }
2470 }
2471 }
2472
2473 return result;
2474}
2475
2476QDockAreaLayoutInfo *QDockAreaLayout::info(QWidget *widget)
2477{
2478 for (int i = 0; i < QInternal::DockCount; ++i) {
2479 if (QDockAreaLayoutInfo *result = docks[i].info(widget))
2480 return result;
2481 }
2482
2483 return 0;
2484}
2485
2486QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path)
2487{
2488 Q_ASSERT(!path.isEmpty());
2489 const int index = path.first();
2490 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2491
2492 if (path.count() == 1)
2493 return &docks[index];
2494
2495 return docks[index].info(path.mid(1));
2496}
2497
2498const QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path) const
2499{
2500 return const_cast<QDockAreaLayout*>(this)->info(path);
2501}
2502
2503QDockAreaLayoutItem &QDockAreaLayout::item(const QList<int> &path)
2504{
2505 Q_ASSERT(!path.isEmpty());
2506 const int index = path.first();
2507 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2508 return docks[index].item(path.mid(1));
2509}
2510
2511QRect QDockAreaLayout::itemRect(const QList<int> &path) const
2512{
2513 Q_ASSERT(!path.isEmpty());
2514 const int index = path.first();
2515 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2516 return docks[index].itemRect(path.mid(1));
2517}
2518
2519QRect QDockAreaLayout::separatorRect(int index) const
2520{
2521 const QDockAreaLayoutInfo &dock = docks[index];
2522 if (dock.isEmpty())
2523 return QRect();
2524 QRect r = dock.rect;
2525 switch (index) {
2526 case QInternal::LeftDock:
2527 return QRect(r.right() + 1, r.top(), sep, r.height());
2528 case QInternal::RightDock:
2529 return QRect(r.left() - sep, r.top(), sep, r.height());
2530 case QInternal::TopDock:
2531 return QRect(r.left(), r.bottom() + 1, r.width(), sep);
2532 case QInternal::BottomDock:
2533 return QRect(r.left(), r.top() - sep, r.width(), sep);
2534 default:
2535 break;
2536 }
2537 return QRect();
2538}
2539
2540QRect QDockAreaLayout::separatorRect(const QList<int> &path) const
2541{
2542 Q_ASSERT(!path.isEmpty());
2543
2544 const int index = path.first();
2545 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2546
2547 if (path.count() == 1)
2548 return separatorRect(index);
2549 else
2550 return docks[index].separatorRect(path.mid(1));
2551}
2552
2553bool QDockAreaLayout::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
2554{
2555 Q_ASSERT(!path.isEmpty());
2556 const int index = path.first();
2557 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2558 return docks[index].insertGap(path.mid(1), dockWidgetItem);
2559}
2560
2561QLayoutItem *QDockAreaLayout::plug(const QList<int> &path)
2562{
2563 Q_ASSERT(!path.isEmpty());
2564 const int index = path.first();
2565 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2566 return docks[index].plug(path.mid(1));
2567}
2568
2569QLayoutItem *QDockAreaLayout::unplug(const QList<int> &path)
2570{
2571 Q_ASSERT(!path.isEmpty());
2572 const int index = path.first();
2573 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2574 return docks[index].unplug(path.mid(1));
2575}
2576
2577void QDockAreaLayout::remove(const QList<int> &path)
2578{
2579 Q_ASSERT(!path.isEmpty());
2580 const int index = path.first();
2581 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2582 docks[index].remove(path.mid(1));
2583}
2584
2585static inline int qMin(int i1, int i2, int i3) { return qMin(i1, qMin(i2, i3)); }
2586static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
2587
2588void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
2589 QVector<QLayoutStruct> *_hor_struct_list)
2590{
2591 QSize center_hint(0, 0);
2592 QSize center_min(0, 0);
2593 const bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
2594 if (have_central) {
2595 center_hint = centralWidgetRect.size();
2596 if (!center_hint.isValid())
2597 center_hint = centralWidgetItem->sizeHint();
2598 center_min = centralWidgetItem->minimumSize();
2599 }
2600
2601 QRect center_rect = rect;
2602 if (!docks[QInternal::LeftDock].isEmpty())
2603 center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
2604 if (!docks[QInternal::TopDock].isEmpty())
2605 center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
2606 if (!docks[QInternal::RightDock].isEmpty())
2607 center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
2608 if (!docks[QInternal::BottomDock].isEmpty())
2609 center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
2610
2611 QSize left_hint = docks[QInternal::LeftDock].size();
2612 if (left_hint.isNull() || fallbackToSizeHints)
2613 left_hint = docks[QInternal::LeftDock].sizeHint();
2614 QSize left_min = docks[QInternal::LeftDock].minimumSize();
2615 QSize left_max = docks[QInternal::LeftDock].maximumSize();
2616 left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
2617
2618 QSize right_hint = docks[QInternal::RightDock].size();
2619 if (right_hint.isNull() || fallbackToSizeHints)
2620 right_hint = docks[QInternal::RightDock].sizeHint();
2621 QSize right_min = docks[QInternal::RightDock].minimumSize();
2622 QSize right_max = docks[QInternal::RightDock].maximumSize();
2623 right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
2624
2625 QSize top_hint = docks[QInternal::TopDock].size();
2626 if (top_hint.isNull() || fallbackToSizeHints)
2627 top_hint = docks[QInternal::TopDock].sizeHint();
2628 QSize top_min = docks[QInternal::TopDock].minimumSize();
2629 QSize top_max = docks[QInternal::TopDock].maximumSize();
2630 top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
2631
2632 QSize bottom_hint = docks[QInternal::BottomDock].size();
2633 if (bottom_hint.isNull() || fallbackToSizeHints)
2634 bottom_hint = docks[QInternal::BottomDock].sizeHint();
2635 QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
2636 QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
2637 bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
2638
2639 fallbackToSizeHints = false;
2640
2641 if (_ver_struct_list != 0) {
2642 QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
2643 ver_struct_list.resize(3);
2644
2645 // top --------------------------------------------------
2646 ver_struct_list[0].init();
2647 ver_struct_list[0].stretch = 0;
2648 ver_struct_list[0].sizeHint = top_hint.height();
2649 ver_struct_list[0].minimumSize = top_min.height();
2650 ver_struct_list[0].maximumSize = top_max.height();
2651 ver_struct_list[0].expansive = false;
2652 ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
2653 ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
2654 ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
2655
2656 // center --------------------------------------------------
2657 ver_struct_list[1].init();
2658 ver_struct_list[1].stretch = center_hint.height();
2659
2660 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2661 || docks[QInternal::TopDock].isEmpty();
2662 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2663 || docks[QInternal::BottomDock].isEmpty();
2664 bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2665 || docks[QInternal::TopDock].isEmpty();
2666 bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
2667 || docks[QInternal::BottomDock].isEmpty();
2668
2669 int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
2670 int right = (tr_significant && br_significant) ? right_hint.height() : 0;
2671 ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
2672
2673 left = (tl_significant && bl_significant) ? left_min.height() : 0;
2674 right = (tr_significant && br_significant) ? right_min.height() : 0;
2675 ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
2676 ver_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
2677 ver_struct_list[1].expansive = have_central;
2678 ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
2679 && !have_central
2680 && docks[QInternal::RightDock].isEmpty();
2681 ver_struct_list[1].pos = center_rect.top();
2682 ver_struct_list[1].size = center_rect.height();
2683
2684 // bottom --------------------------------------------------
2685 ver_struct_list[2].init();
2686 ver_struct_list[2].stretch = 0;
2687 ver_struct_list[2].sizeHint = bottom_hint.height();
2688 ver_struct_list[2].minimumSize = bottom_min.height();
2689 ver_struct_list[2].maximumSize = bottom_max.height();
2690 ver_struct_list[2].expansive = false;
2691 ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
2692 ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
2693 ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
2694
2695 for (int i = 0; i < 3; ++i) {
2696 ver_struct_list[i].sizeHint
2697 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
2698 }
2699 }
2700
2701 if (_hor_struct_list != 0) {
2702 QVector<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
2703 hor_struct_list.resize(3);
2704
2705 // left --------------------------------------------------
2706 hor_struct_list[0].init();
2707 hor_struct_list[0].stretch = 0;
2708 hor_struct_list[0].sizeHint = left_hint.width();
2709 hor_struct_list[0].minimumSize = left_min.width();
2710 hor_struct_list[0].maximumSize = left_max.width();
2711 hor_struct_list[0].expansive = false;
2712 hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
2713 hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
2714 hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
2715
2716 // center --------------------------------------------------
2717 hor_struct_list[1].init();
2718 hor_struct_list[1].stretch = center_hint.width();
2719
2720 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
2721 || docks[QInternal::LeftDock].isEmpty();
2722 bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
2723 || docks[QInternal::RightDock].isEmpty();
2724 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
2725 || docks[QInternal::LeftDock].isEmpty();
2726 bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
2727 || docks[QInternal::RightDock].isEmpty();
2728
2729 int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
2730 int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
2731 hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
2732
2733 top = (tl_significant && tr_significant) ? top_min.width() : 0;
2734 bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
2735 hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
2736
2737 hor_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
2738 hor_struct_list[1].expansive = have_central;
2739 hor_struct_list[1].empty = !have_central;
2740 hor_struct_list[1].pos = center_rect.left();
2741 hor_struct_list[1].size = center_rect.width();
2742
2743 // right --------------------------------------------------
2744 hor_struct_list[2].init();
2745 hor_struct_list[2].stretch = 0;
2746 hor_struct_list[2].sizeHint = right_hint.width();
2747 hor_struct_list[2].minimumSize = right_min.width();
2748 hor_struct_list[2].maximumSize = right_max.width();
2749 hor_struct_list[2].expansive = false;
2750 hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
2751 hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
2752 hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
2753
2754 for (int i = 0; i < 3; ++i) {
2755 hor_struct_list[i].sizeHint
2756 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
2757 }
2758 }
2759}
2760
2761void QDockAreaLayout::setGrid(QVector<QLayoutStruct> *ver_struct_list,
2762 QVector<QLayoutStruct> *hor_struct_list)
2763{
2764
2765 // top ---------------------------------------------------
2766
2767 if (!docks[QInternal::TopDock].isEmpty()) {
2768 QRect r = docks[QInternal::TopDock].rect;
2769 if (hor_struct_list != 0) {
2770 r.setLeft(corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2771 || docks[QInternal::LeftDock].isEmpty()
2772 ? rect.left() : hor_struct_list->at(1).pos);
2773 r.setRight(corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2774 || docks[QInternal::RightDock].isEmpty()
2775 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
2776 }
2777 if (ver_struct_list != 0) {
2778 r.setTop(rect.top());
2779 r.setBottom(ver_struct_list->at(1).pos - sep - 1);
2780 }
2781 docks[QInternal::TopDock].rect = r;
2782 docks[QInternal::TopDock].fitItems();
2783 }
2784
2785 // bottom ---------------------------------------------------
2786
2787 if (!docks[QInternal::BottomDock].isEmpty()) {
2788 QRect r = docks[QInternal::BottomDock].rect;
2789 if (hor_struct_list != 0) {
2790 r.setLeft(corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2791 || docks[QInternal::LeftDock].isEmpty()
2792 ? rect.left() : hor_struct_list->at(1).pos);
2793 r.setRight(corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
2794 || docks[QInternal::RightDock].isEmpty()
2795 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
2796 }
2797 if (ver_struct_list != 0) {
2798 r.setTop(ver_struct_list->at(2).pos);
2799 r.setBottom(rect.bottom());
2800 }
2801 docks[QInternal::BottomDock].rect = r;
2802 docks[QInternal::BottomDock].fitItems();
2803 }
2804
2805 // left ---------------------------------------------------
2806
2807 if (!docks[QInternal::LeftDock].isEmpty()) {
2808 QRect r = docks[QInternal::LeftDock].rect;
2809 if (hor_struct_list != 0) {
2810 r.setLeft(rect.left());
2811 r.setRight(hor_struct_list->at(1).pos - sep - 1);
2812 }
2813 if (ver_struct_list != 0) {
2814 r.setTop(corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
2815 || docks[QInternal::TopDock].isEmpty()
2816 ? rect.top() : ver_struct_list->at(1).pos);
2817 r.setBottom(corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
2818 || docks[QInternal::BottomDock].isEmpty()
2819 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
2820 }
2821 docks[QInternal::LeftDock].rect = r;
2822 docks[QInternal::LeftDock].fitItems();
2823 }
2824
2825 // right ---------------------------------------------------
2826
2827 if (!docks[QInternal::RightDock].isEmpty()) {
2828 QRect r = docks[QInternal::RightDock].rect;
2829 if (hor_struct_list != 0) {
2830 r.setLeft(hor_struct_list->at(2).pos);
2831 r.setRight(rect.right());
2832 }
2833 if (ver_struct_list != 0) {
2834 r.setTop(corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
2835 || docks[QInternal::TopDock].isEmpty()
2836 ? rect.top() : ver_struct_list->at(1).pos);
2837 r.setBottom(corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
2838 || docks[QInternal::BottomDock].isEmpty()
2839 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
2840 }
2841 docks[QInternal::RightDock].rect = r;
2842 docks[QInternal::RightDock].fitItems();
2843 }
2844
2845 // center ---------------------------------------------------
2846
2847 if (hor_struct_list != 0) {
2848 centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
2849 centralWidgetRect.setWidth(hor_struct_list->at(1).size);
2850 }
2851 if (ver_struct_list != 0) {
2852 centralWidgetRect.setTop(ver_struct_list->at(1).pos);
2853 centralWidgetRect.setHeight(ver_struct_list->at(1).size);
2854 }
2855}
2856
2857void QDockAreaLayout::fitLayout()
2858{
2859 QVector<QLayoutStruct> ver_struct_list(3);
2860 QVector<QLayoutStruct> hor_struct_list(3);
2861 getGrid(&ver_struct_list, &hor_struct_list);
2862
2863 qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
2864 qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
2865
2866 setGrid(&ver_struct_list, &hor_struct_list);
2867}
2868
2869void QDockAreaLayout::clear()
2870{
2871 for (int i = 0; i < QInternal::DockCount; ++i)
2872 docks[i].clear();
2873
2874 rect = QRect();
2875 centralWidgetRect = QRect();
2876}
2877
2878QSize QDockAreaLayout::sizeHint() const
2879{
2880 int left_sep = 0;
2881 int right_sep = 0;
2882 int top_sep = 0;
2883 int bottom_sep = 0;
2884
2885 if (centralWidgetItem != 0) {
2886 left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
2887 right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
2888 top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
2889 bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
2890 }
2891
2892 QSize left = docks[QInternal::LeftDock].sizeHint() + QSize(left_sep, 0);
2893 QSize right = docks[QInternal::RightDock].sizeHint() + QSize(right_sep, 0);
2894 QSize top = docks[QInternal::TopDock].sizeHint() + QSize(0, top_sep);
2895 QSize bottom = docks[QInternal::BottomDock].sizeHint() + QSize(0, bottom_sep);
2896 QSize center = centralWidgetItem == 0 ? QSize(0, 0) : centralWidgetItem->sizeHint();
2897
2898 int row1 = top.width();
2899 int row2 = left.width() + center.width() + right.width();
2900 int row3 = bottom.width();
2901 int col1 = left.height();
2902 int col2 = top.height() + center.height() + bottom.height();
2903 int col3 = right.height();
2904
2905 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
2906 row1 += left.width();
2907 else
2908 col1 += top.height();
2909
2910 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
2911 row1 += right.width();
2912 else
2913 col3 += top.height();
2914