Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qdockarealayout.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "QtWidgets/qapplication.h"
6#include "QtWidgets/qwidget.h"
7#if QT_CONFIG(tabbar)
8#include "QtWidgets/qtabbar.h"
9#endif
10#include "QtWidgets/qstyle.h"
11#include "QtWidgets/qapplication.h"
12#include "QtCore/qvariant.h"
13#include "qdockarealayout_p.h"
14#include "qdockwidget.h"
15#include "qmainwindow.h"
16#include "qwidgetanimator_p.h"
17#include "qmainwindowlayout_p.h"
18#include "qmenu_p.h"
19#include "qdockwidget_p.h"
20#include <private/qlayoutengine_p.h>
21
22#include <qpainter.h>
23#include <qstyleoption.h>
24
26
27Q_LOGGING_CATEGORY(lcQpaDockWidgets, "qt.widgets.dockwidgets");
28
29// qmainwindow.cpp
31
33
34/******************************************************************************
35** QPlaceHolderItem
36*/
37
39{
40 objectName = w->objectName();
41 hidden = w->isHidden();
42 window = w->isWindow();
43 if (window)
44 topLevelRect = w->geometry();
45}
46
47/******************************************************************************
48** QDockAreaLayoutItem
49*/
50
52 : widgetItem(_widgetItem), subinfo(nullptr), placeHolderItem(nullptr), pos(0), size(-1), flags(NoFlags)
53{
54}
55
57 : widgetItem(nullptr), subinfo(_subinfo), placeHolderItem(nullptr), pos(0), size(-1), flags(NoFlags)
58{
59}
60
62 : widgetItem(nullptr), subinfo(nullptr), placeHolderItem(_placeHolderItem), pos(0), size(-1), flags(NoFlags)
63{
64}
65
67 : widgetItem(other.widgetItem), subinfo(nullptr), placeHolderItem(nullptr), pos(other.pos),
69{
70 if (other.subinfo != nullptr)
71 subinfo = new QDockAreaLayoutInfo(*other.subinfo);
72 else if (other.placeHolderItem != nullptr)
73 placeHolderItem = new QPlaceHolderItem(*other.placeHolderItem);
74}
75
77{
78 delete subinfo;
79 delete placeHolderItem;
80}
81
83{
84 if (placeHolderItem != nullptr)
85 return true;
86
87 if (flags & GapItem)
88 return false;
89
90 if (widgetItem != nullptr)
91 return widgetItem->isEmpty();
92
93 if (subinfo != nullptr) {
94 for (int i = 0; i < subinfo->item_list.size(); ++i) {
95 if (!subinfo->item_list.at(i).skip())
96 return false;
97 }
98 }
99
100 return true;
101}
102
104{
105 if (widgetItem)
107 if (subinfo != nullptr)
108 return subinfo->minimumSize();
109 return QSize(0, 0);
110}
111
113{
114 if (widgetItem)
116 if (subinfo != nullptr)
117 return subinfo->maximumSize();
119}
120
122{
123 return perp(o, minimumSize()) == perp(o, maximumSize());
124}
125
127{
128 if ((flags & GapItem) || placeHolderItem != nullptr)
129 return false;
130 if (widgetItem != nullptr)
131 return ((widgetItem->expandingDirections() & o) == o);
132 if (subinfo != nullptr)
133 return subinfo->expansive(o);
134 return false;
135}
136
138{
139 if (placeHolderItem != nullptr)
140 return QSize(0, 0);
141 if (widgetItem)
143 if (subinfo != nullptr)
144 return subinfo->sizeHint();
145 return QSize(-1, -1);
146}
147
150{
151 if (this == &other)
152 return *this;
153
154 widgetItem = other.widgetItem;
155 delete subinfo;
156 if (other.subinfo == nullptr)
157 subinfo = nullptr;
158 else
159 subinfo = new QDockAreaLayoutInfo(*other.subinfo);
160
161 delete placeHolderItem;
162 if (other.placeHolderItem == nullptr)
163 placeHolderItem = nullptr;
164 else
165 placeHolderItem = new QPlaceHolderItem(*other.placeHolderItem);
166
167 pos = other.pos;
168 size = other.size;
169 flags = other.flags;
170
171 return *this;
172}
173
174#ifndef QT_NO_DEBUG_STREAM
176{
177 QDebugStateSaver saver(dbg);
178 dbg.nospace();
179 dbg << "QDockAreaLayoutItem(" << static_cast<const void *>(&item) << "->";
180 if (item.widgetItem)
181 dbg << "widgetItem(" << item.widgetItem->widget() << ")";
182 else if (item.subinfo)
183 dbg << "subInfo(" << item.subinfo << ")";
184 else if (item.placeHolderItem)
185 dbg << "placeHolderItem(" << item.placeHolderItem << ")";
186 dbg << ")";
187 return dbg;
188}
189#endif // QT_NO_DEBUG_STREAM
190
191/******************************************************************************
192** QDockAreaLayoutInfo
193*/
194
195#if QT_CONFIG(tabbar)
196static quintptr tabId(const QDockAreaLayoutItem &item)
197{
198 if (item.widgetItem == nullptr)
199 return 0;
200 return reinterpret_cast<quintptr>(item.widgetItem->widget());
201}
202#endif
203
204static const int zero = 0;
205
207 : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(nullptr)
208#if QT_CONFIG(tabbar)
209 , tabbed(false), tabBar(nullptr), tabBarShape(QTabBar::RoundedSouth)
210#endif
211{
212}
213
215 Qt::Orientation _o, int tbshape,
217 : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
218#if QT_CONFIG(tabbar)
219 , tabbed(false), tabBar(nullptr), tabBarShape(static_cast<QTabBar::Shape>(tbshape))
220#endif
221{
222#if !QT_CONFIG(tabbar)
223 Q_UNUSED(tbshape);
224#endif
225}
226
228{
229 return isEmpty() ? QSize(0, 0) : rect.size();
230}
231
233{
235 rect = QRect();
236#if QT_CONFIG(tabbar)
237 tabbed = false;
238 tabBar = nullptr;
239#endif
240}
241
243{
244 return next(-1) == -1;
245}
246
248{
249 for (const QDockAreaLayoutItem &item : item_list) {
250 if (!item.placeHolderItem)
251 return false;
252 }
253
254 return true;
255}
256
258{
259 if (isEmpty())
260 return QSize(0, 0);
261
262 int a = 0, b = 0;
263 bool first = true;
264 for (int i = 0; i < item_list.size(); ++i) {
266 if (item.skip())
267 continue;
268
269 QSize min_size = item.minimumSize();
270#if QT_CONFIG(tabbar)
271 if (tabbed) {
272 a = qMax(a, pick(o, min_size));
273 } else
274#endif
275 {
276 if (!first)
277 a += *sep;
278 a += pick(o, min_size);
279 }
280 b = qMax(b, perp(o, min_size));
281
282 first = false;
283 }
284
286 rpick(o, result) = a;
287 rperp(o, result) = b;
288
289#if QT_CONFIG(tabbar)
290 QSize tbm = tabBarMinimumSize();
291 if (!tbm.isNull()) {
292 switch (tabBarShape) {
297 result.rheight() += tbm.height();
298 result.rwidth() = qMax(tbm.width(), result.width());
299 break;
304 result.rheight() = qMax(tbm.height(), result.height());
305 result.rwidth() += tbm.width();
306 break;
307 default:
308 break;
309 }
310 }
311#endif // QT_CONFIG(tabbar)
312
313 return result;
314}
315
317{
318 if (isEmpty())
320
321 int a = 0, b = QWIDGETSIZE_MAX;
322#if QT_CONFIG(tabbar)
323 if (tabbed)
325#endif
326
327 int min_perp = 0;
328
329 bool first = true;
330 for (int i = 0; i < item_list.size(); ++i) {
332 if (item.skip())
333 continue;
334
335 QSize max_size = item.maximumSize();
336 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
337
338#if QT_CONFIG(tabbar)
339 if (tabbed) {
340 a = qMin(a, pick(o, max_size));
341 } else
342#endif
343 {
344 if (!first)
345 a += *sep;
346 a += pick(o, max_size);
347 }
348 b = qMin(b, perp(o, max_size));
349
350 a = qMin(a, int(QWIDGETSIZE_MAX));
351 b = qMin(b, int(QWIDGETSIZE_MAX));
352
353 first = false;
354 }
355
356 b = qMax(b, min_perp);
357
359 rpick(o, result) = a;
360 rperp(o, result) = b;
361
362#if QT_CONFIG(tabbar)
363 QSize tbh = tabBarSizeHint();
364 if (!tbh.isNull()) {
365 switch (tabBarShape) {
368 result.rheight() += tbh.height();
369 break;
372 result.rwidth() += tbh.width();
373 break;
374 default:
375 break;
376 }
377 }
378#endif // QT_CONFIG(tabbar)
379
380 return result;
381}
382
384{
385 if (isEmpty())
386 return QSize(0, 0);
387
388 int a = 0, b = 0;
389 int min_perp = 0;
390 int max_perp = QWIDGETSIZE_MAX;
391 const QDockAreaLayoutItem *previous = nullptr;
392 for (int i = 0; i < item_list.size(); ++i) {
394 if (item.skip())
395 continue;
396
398
399 QSize size_hint = item.sizeHint();
400 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
401 max_perp = qMin(max_perp, perp(o, item.maximumSize()));
402
403#if QT_CONFIG(tabbar)
404 if (tabbed) {
405 a = qMax(a, gap ? item.size : pick(o, size_hint));
406 } else
407#endif
408 {
409 if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
410 && !previous->hasFixedSize(o)) {
411 a += *sep;
412 }
413 a += gap ? item.size : pick(o, size_hint);
414 }
415 b = qMax(b, perp(o, size_hint));
416
417 previous = &item;
418 }
419
420 max_perp = qMax(max_perp, min_perp);
421 b = qMax(b, min_perp);
422 b = qMin(b, max_perp);
423
425 rpick(o, result) = a;
426 rperp(o, result) = b;
427
428#if QT_CONFIG(tabbar)
429 if (tabbed) {
430 QSize tbh = tabBarSizeHint();
431 switch (tabBarShape) {
436 result.rheight() += tbh.height();
437 result.rwidth() = qMax(tbh.width(), result.width());
438 break;
443 result.rheight() = qMax(tbh.height(), result.height());
444 result.rwidth() += tbh.width();
445 break;
446 default:
447 break;
448 }
449 }
450#endif // QT_CONFIG(tabbar)
451
452 return result;
453}
454
456{
457 for (int i = 0; i < item_list.size(); ++i) {
458 if (item_list.at(i).expansive(o))
459 return true;
460 }
461 return false;
462}
463
464/* QDockAreaLayoutInfo::maximumSize() doesn't return the real max size. For example,
465 if the layout is empty, it returns QWIDGETSIZE_MAX. This is so that empty dock areas
466 don't constrain the size of the QMainWindow, but sometimes we really need to know the
467 maximum size. Also, these functions take into account widgets that want to keep their
468 size (f.ex. when they are hidden and then shown, they should not change size).
469*/
470
472{
473 int result = 0;
474 bool first = true;
475 for (int i = 0; i < info.item_list.size(); ++i) {
476 const QDockAreaLayoutItem &item = info.item_list.at(i);
477 if (item.skip())
478 continue;
479
480 int min = 0;
481 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
482 min = item.size;
483 else
484 min = pick(info.o, item.minimumSize());
485
486 if (!first)
487 result += *info.sep;
488 result += min;
489
490 first = false;
491 }
492
493 return result;
494}
495
497{
498 int result = 0;
499 bool first = true;
500 for (int i = 0; i < info.item_list.size(); ++i) {
501 const QDockAreaLayoutItem &item = info.item_list.at(i);
502 if (item.skip())
503 continue;
504
505 int max = 0;
506 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
507 max = item.size;
508 else
509 max = pick(info.o, item.maximumSize());
510
511 if (!first)
512 result += *info.sep;
513 result += max;
514
515 if (result >= QWIDGETSIZE_MAX)
516 return QWIDGETSIZE_MAX;
517
518 first = false;
519 }
520
521 return result;
522}
523
525{
526#if QT_CONFIG(tabbar)
527 if (tabbed) {
528 return;
529 }
530#endif
531
532 QList<QLayoutStruct> layout_struct_list(item_list.size() * 2);
533 int j = 0;
534
535 int size = pick(o, rect.size());
536 int min_size = realMinSize(*this);
537 int max_size = realMaxSize(*this);
538 int last_index = -1;
539
540 const QDockAreaLayoutItem *previous = nullptr;
541 for (int i = 0; i < item_list.size(); ++i) {
543 if (item.skip())
544 continue;
545
547 if (previous && !gap) {
548 if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
549 QLayoutStruct &ls = layout_struct_list[j++];
550 ls.init();
551 ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
552 ls.empty = false;
553 }
554 }
555
557 // Check if the item can keep its size, without violating size constraints
558 // of other items.
559
560 if (size < min_size) {
561 // There is too little space to keep this widget's size
562 item.flags &= ~QDockAreaLayoutItem::KeepSize;
563 min_size -= item.size;
564 min_size += pick(o, item.minimumSize());
565 min_size = qMax(0, min_size);
566 } else if (size > max_size) {
567 // There is too much space to keep this widget's size
568 item.flags &= ~QDockAreaLayoutItem::KeepSize;
569 max_size -= item.size;
570 max_size += pick(o, item.maximumSize());
571 max_size = qMin<int>(QWIDGETSIZE_MAX, max_size);
572 }
573 }
574
575 last_index = j;
576 QLayoutStruct &ls = layout_struct_list[j++];
577 ls.init();
578 ls.empty = false;
580 ls.minimumSize = ls.maximumSize = ls.sizeHint = item.size;
581 ls.expansive = false;
582 ls.stretch = 0;
583 } else {
584 ls.maximumSize = pick(o, item.maximumSize());
585 ls.expansive = item.expansive(o);
586 ls.minimumSize = pick(o, item.minimumSize());
587 ls.sizeHint = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
588 ls.stretch = ls.expansive ? ls.sizeHint : 0;
589 }
590
591 item.flags &= ~QDockAreaLayoutItem::KeepSize;
592 previous = &item;
593 }
594 layout_struct_list.resize(j);
595
596 // If there is more space than the widgets can take (due to maximum size constraints),
597 // we detect it here and stretch the last widget to take up the rest of the space.
598 if (size > max_size && last_index != -1) {
599 layout_struct_list[last_index].maximumSize = QWIDGETSIZE_MAX;
600 layout_struct_list[last_index].expansive = true;
601 }
602
603 qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
604
605 j = 0;
606 bool prev_gap = false;
607 bool first = true;
608 for (int i = 0; i < item_list.size(); ++i) {
610 if (item.skip())
611 continue;
612
614 if (!first && !gap && !prev_gap)
615 ++j;
616
617 const QLayoutStruct &ls = layout_struct_list.at(j++);
618 item.size = ls.size;
619 item.pos = ls.pos;
620
621 if (item.subinfo != nullptr) {
622 item.subinfo->rect = itemRect(i);
623 item.subinfo->fitItems();
624 }
625
626 prev_gap = gap;
627 first = false;
628 }
629}
630
633 bool nestingEnabled,
635{
636 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
638
639 QPoint pos = _pos - rect.topLeft();
640
641 int x = pos.x();
642 int y = pos.y();
643 int w = rect.width();
644 int h = rect.height();
645
646 if (tabMode != QDockAreaLayoutInfo::NoTabs) {
647 // is it in the center?
648 if (nestingEnabled) {
649 /* 2/3
650 +--------------+
651 | |
652 | CCCCCCCC |
653 2/3 | CCCCCCCC |
654 | CCCCCCCC |
655 | |
656 +--------------+ */
657
658 QRect center(w/6, h/6, 2*w/3, 2*h/3);
659 if (center.contains(pos))
661 } else if (o == Qt::Horizontal) {
662 /* 2/3
663 +--------------+
664 | CCCCCCCC |
665 | CCCCCCCC |
666 | CCCCCCCC |
667 | CCCCCCCC |
668 | CCCCCCCC |
669 +--------------+ */
670
671 if (x > w/6 && x < w*5/6)
673 } else {
674 /*
675 +--------------+
676 | |
677 2/3 |CCCCCCCCCCCCCC|
678 |CCCCCCCCCCCCCC|
679 | |
680 +--------------+ */
681 if (y > h/6 && y < 5*h/6)
683 }
684 }
685
686 // not in the center. which edge?
687 if (nestingEnabled) {
688 if (o == Qt::Horizontal) {
689 /* 1/3 1/3 1/3
690 +------------+ (we've already ruled out the center)
691 |LLLLTTTTRRRR|
692 |LLLLTTTTRRRR|
693 |LLLLBBBBRRRR|
694 |LLLLBBBBRRRR|
695 +------------+ */
696
697 if (x < w/3)
698 return QInternal::LeftDock;
699 if (x > 2*w/3)
701 if (y < h/2)
702 return QInternal::TopDock;
704 } else {
705 /* +------------+ (we've already ruled out the center)
706 1/3 |TTTTTTTTTTTT|
707 |LLLLLLRRRRRR|
708 1/3 |LLLLLLRRRRRR|
709 1/3 |BBBBBBBBBBBB|
710 +------------+ */
711
712 if (y < h/3)
713 return QInternal::TopDock;
714 if (y > 2*h/3)
716 if (x < w/2)
717 return QInternal::LeftDock;
719 }
720 } else {
721 if (o == Qt::Horizontal) {
722 return x < w/2
725 } else {
726 return y < h/2
729 }
730 }
731}
732
734 bool nestingEnabled, TabMode tabMode) const
735{
737 QRect item_rect;
738 int item_index = 0;
739
740#if QT_CONFIG(tabbar)
741 if (tabbed) {
742 item_rect = tabContentRect();
743 } else
744#endif
745 {
746 int pos = pick(o, _pos);
747
748 int last = -1;
749 for (int i = 0; i < item_list.size(); ++i) {
751 if (item.skip())
752 continue;
753
754 last = i;
755
756 if (item.pos + item.size < pos)
757 continue;
758
759 if (item.subinfo != nullptr
760#if QT_CONFIG(tabbar)
761 && !item.subinfo->tabbed
762#endif
763 ) {
764 result = item.subinfo->gapIndex(_pos, nestingEnabled,
765 tabMode);
766 result.prepend(i);
767 return result;
768 }
769
770 item_rect = itemRect(i);
771 item_index = i;
772 break;
773 }
774
775 if (item_rect.isNull()) {
776 result.append(last + 1);
777 return result;
778 }
779 }
780
781 Q_ASSERT(!item_rect.isNull());
782
784 = dockPosHelper(item_rect, _pos, o, nestingEnabled, tabMode);
785
786 switch (dock_pos) {
788 if (o == Qt::Horizontal)
789 result << item_index;
790 else
791 result << item_index << 0; // this subinfo doesn't exist yet, but insertGap()
792 // handles this by inserting it
793 break;
795 if (o == Qt::Horizontal)
796 result << item_index + 1;
797 else
798 result << item_index << 1;
799 break;
801 if (o == Qt::Horizontal)
802 result << item_index << 0;
803 else
804 result << item_index;
805 break;
807 if (o == Qt::Horizontal)
808 result << item_index << 1;
809 else
810 result << item_index + 1;
811 break;
813 result << (-item_index - 1) << 0; // negative item_index means "on top of"
814 // -item_index - 1, insertGap()
815 // will insert a tabbed subinfo
816 break;
817 default:
818 break;
819 }
820
821 return result;
822}
823
824static inline int shrink(QLayoutStruct &ls, int delta)
825{
826 if (ls.empty)
827 return 0;
828 int old_size = ls.size;
829 ls.size = qMax(ls.size - delta, ls.minimumSize);
830 return old_size - ls.size;
831}
832
833static inline int grow(QLayoutStruct &ls, int delta)
834{
835 if (ls.empty)
836 return 0;
837 int old_size = ls.size;
838 ls.size = qMin(ls.size + delta, ls.maximumSize);
839 return ls.size - old_size;
840}
841
842static int separatorMoveHelper(QList<QLayoutStruct> &list, int index, int delta, int sep)
843{
844 // adjust sizes
845 int pos = -1;
846 for (int i = 0; i < list.size(); ++i) {
847 const QLayoutStruct &ls = list.at(i);
848 if (!ls.empty) {
849 pos = ls.pos;
850 break;
851 }
852 }
853 if (pos == -1)
854 return 0;
855
856 if (delta > 0) {
857 int growlimit = 0;
858 for (int i = 0; i<=index; ++i) {
859 const QLayoutStruct &ls = list.at(i);
860 if (ls.empty)
861 continue;
862 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
863 growlimit = QLAYOUTSIZE_MAX;
864 break;
865 }
866 growlimit += ls.maximumSize - ls.size;
867 }
868 if (delta > growlimit)
869 delta = growlimit;
870
871 int d = 0;
872 for (int i = index + 1; d < delta && i < list.size(); ++i)
873 d += shrink(list[i], delta - d);
874 delta = d;
875 d = 0;
876 for (int i = index; d < delta && i >= 0; --i)
877 d += grow(list[i], delta - d);
878 } else if (delta < 0) {
879 int growlimit = 0;
880 for (int i = index + 1; i < list.size(); ++i) {
881 const QLayoutStruct &ls = list.at(i);
882 if (ls.empty)
883 continue;
884 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
885 growlimit = QLAYOUTSIZE_MAX;
886 break;
887 }
888 growlimit += ls.maximumSize - ls.size;
889 }
890 if (-delta > growlimit)
891 delta = -growlimit;
892
893 int d = 0;
894 for (int i = index; d < -delta && i >= 0; --i)
895 d += shrink(list[i], -delta - d);
896 delta = -d;
897 d = 0;
898 for (int i = index + 1; d < -delta && i < list.size(); ++i)
899 d += grow(list[i], -delta - d);
900 }
901
902 // adjust positions
903 bool first = true;
904 for (int i = 0; i < list.size(); ++i) {
905 QLayoutStruct &ls = list[i];
906 if (ls.empty) {
907 ls.pos = pos + (first ? 0 : sep);
908 continue;
909 }
910 if (!first)
911 pos += sep;
912 ls.pos = pos;
913 pos += ls.size;
914 first = false;
915 }
916
917 return delta;
918}
919
921{
922#if QT_CONFIG(tabbar)
923 Q_ASSERT(!tabbed);
924#endif
925
927 for (int i = 0; i < list.size(); ++i) {
929 QLayoutStruct &ls = list[i];
931 if (item.skip()) {
932 ls.empty = true;
933 } else {
934 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
935 ls.empty = false;
936 ls.pos = item.pos;
937 ls.size = item.size + separatorSpace;
938 ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace;
939 ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace;
940
941 }
942 }
943
944 //the separator space has been added to the size, so we pass 0 as a parameter
945 delta = separatorMoveHelper(list, index, delta, 0 /*separator*/);
946
947 for (int i = 0; i < list.size(); ++i) {
949 if (item.skip())
950 continue;
951 QLayoutStruct &ls = list[i];
952 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
953 item.size = ls.size - separatorSpace;
954 item.pos = ls.pos;
955 if (item.subinfo != nullptr) {
956 item.subinfo->rect = itemRect(i);
957 item.subinfo->fitItems();
958 }
959 }
960
961 return delta;
962}
963
965{
967 if (item.subinfo == nullptr)
968 return;
969 if (item.subinfo->item_list.size() > 1)
970 return;
971
972 if (item.subinfo->item_list.size() == 0) {
974 } else if (item.subinfo->item_list.size() == 1) {
975 QDockAreaLayoutItem &child = item.subinfo->item_list.first();
976 if (child.widgetItem != nullptr) {
977 item.widgetItem = child.widgetItem;
978 delete item.subinfo;
979 item.subinfo = nullptr;
980 } else if (child.subinfo != nullptr) {
981 QDockAreaLayoutInfo *tmp = item.subinfo;
982 item.subinfo = child.subinfo;
983 child.subinfo = nullptr;
984 tmp->item_list.clear();
985 delete tmp;
986 }
987 }
988}
989
991{
992 Q_ASSERT(!path.isEmpty());
993
994 if (path.size() > 1) {
995 const int index = path.first();
997 Q_ASSERT(item.subinfo != nullptr);
998 item.subinfo->remove(path.mid(1));
999 unnest(index);
1000 } else {
1001 int index = path.first();
1003 }
1004}
1005
1007{
1008 Q_ASSERT(!path.isEmpty());
1009
1010 int index = path.first();
1011 if (index < 0)
1012 index = -index - 1;
1013
1014 if (path.size() > 1) {
1016 Q_ASSERT(item.subinfo != nullptr);
1017 return item.subinfo->plug(path.mid(1));
1018 }
1019
1021
1022 Q_ASSERT(item.widgetItem != nullptr);
1024 item.flags &= ~QDockAreaLayoutItem::GapItem;
1025 return item.widgetItem;
1026}
1027
1029{
1030 Q_ASSERT(!path.isEmpty());
1031
1032 const int index = path.first();
1033 if (path.size() > 1) {
1035 Q_ASSERT(item.subinfo != nullptr);
1036 return item.subinfo->unplug(path.mid(1));
1037 }
1038
1040 int prev = this->prev(index);
1041 int next = this->next(index);
1042
1045
1046#if QT_CONFIG(tabbar)
1047 if (tabbed) {
1048 } else
1049#endif
1050 {
1052 item.pos -= *sep;
1053 item.size += *sep;
1054 }
1056 item.size += *sep;
1057 }
1058
1059 return item.widgetItem;
1060}
1061
1062#if QT_CONFIG(tabbar)
1063
1064quintptr QDockAreaLayoutInfo::currentTabId() const
1065{
1066 if (!tabbed || tabBar == nullptr)
1067 return 0;
1068
1069 int index = tabBar->currentIndex();
1070 if (index == -1)
1071 return 0;
1072
1073 return qvariant_cast<quintptr>(tabBar->tabData(index));
1074}
1075
1076void QDockAreaLayoutInfo::setCurrentTab(QWidget *widget)
1077{
1078 setCurrentTabId(reinterpret_cast<quintptr>(widget));
1079}
1080
1081void QDockAreaLayoutInfo::setCurrentTabId(quintptr id)
1082{
1083 if (!tabbed || tabBar == nullptr)
1084 return;
1085
1086 for (int i = 0; i < tabBar->count(); ++i) {
1087 if (qvariant_cast<quintptr>(tabBar->tabData(i)) == id) {
1088 tabBar->setCurrentIndex(i);
1089 return;
1090 }
1091 }
1092}
1093
1094#endif // QT_CONFIG(tabbar)
1095
1097{
1098 int titleHeight = 0;
1099
1101 = qobject_cast<QDockWidgetLayout*>(widget->layout());
1102 if (layout && layout->nativeWindowDeco())
1103 titleHeight = layout->titleHeight();
1104
1106 result.adjust(0, -titleHeight, 0, 0);
1107 return result;
1108}
1109
1111{
1112 // empty path has no gap item
1113 if (path.isEmpty())
1114 return false;
1115
1116 // Index -1 isn't a gap
1117 // Index out of range points at a position to be created. That isn't a gap either.
1118 const int index = path.constFirst();
1119 if (index < 0 || index >= item_list.count())
1120 return false;
1121
1123}
1124
1126{
1127 Q_ASSERT(!path.isEmpty());
1128
1129 bool insert_tabbed = false;
1130 int index = path.first();
1131 if (index < 0) {
1132 insert_tabbed = true;
1133 index = -index - 1;
1134 }
1135
1136// dump(qDebug() << "insertGap() before:" << index << tabIndex, *this, QString());
1137
1138 if (path.size() > 1) {
1140
1141 if (item.subinfo == nullptr
1142#if QT_CONFIG(tabbar)
1143 || (item.subinfo->tabbed && !insert_tabbed)
1144#endif
1145 ) {
1146
1147 // this is not yet a nested layout - make it
1148
1149 QDockAreaLayoutInfo *subinfo = item.subinfo;
1150 QLayoutItem *widgetItem = item.widgetItem;
1151 QPlaceHolderItem *placeHolderItem = item.placeHolderItem;
1152 QRect r = subinfo == nullptr ? widgetItem ? dockedGeometry(widgetItem->widget()) : placeHolderItem->topLevelRect : subinfo->rect;
1153
1155#if !QT_CONFIG(tabbar)
1156 const int tabBarShape = 0;
1157#endif
1158 QDockAreaLayoutInfo *new_info
1159 = new QDockAreaLayoutInfo(sep, dockPos, opposite, tabBarShape, mainWindow);
1160
1161 //item become a new top-level
1162 item.subinfo = new_info;
1163 item.widgetItem = nullptr;
1164 item.placeHolderItem = nullptr;
1165
1166 QDockAreaLayoutItem new_item
1167 = widgetItem == nullptr
1168 ? QDockAreaLayoutItem(subinfo)
1169 : widgetItem ? QDockAreaLayoutItem(widgetItem) : QDockAreaLayoutItem(placeHolderItem);
1170 new_item.size = pick(opposite, r.size());
1171 new_item.pos = pick(opposite, r.topLeft());
1172 new_info->item_list.append(new_item);
1173#if QT_CONFIG(tabbar)
1174 if (insert_tabbed) {
1175 new_info->tabbed = true;
1176 }
1177#endif
1178 }
1179
1180 return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
1181 }
1182
1183 // create the gap item
1184 QDockAreaLayoutItem gap_item;
1186 gap_item.widgetItem = dockWidgetItem; // so minimumSize(), maximumSize() and
1187 // sizeHint() will work
1188#if QT_CONFIG(tabbar)
1189 if (!tabbed)
1190#endif
1191 {
1192 int prev = this->prev(index);
1193 int next = this->next(index - 1);
1194 // find out how much space we have in the layout
1195 int space = 0;
1196 if (isEmpty()) {
1197 // I am an empty dock area, therefore I am a top-level dock area.
1198 switch (dockPos) {
1201 if (o == Qt::Vertical) {
1202 // the "size" is the height of the dock area (remember we are empty)
1203 space = pick(Qt::Vertical, rect.size());
1204 } else {
1205 space = pick(Qt::Horizontal, dockWidgetItem->widget()->size());
1206 }
1207 break;
1208 case QInternal::TopDock:
1210 default:
1211 if (o == Qt::Horizontal) {
1212 // the "size" is width of the dock area
1213 space = pick(Qt::Horizontal, rect.size());
1214 } else {
1215 space = pick(Qt::Vertical, dockWidgetItem->widget()->size());
1216 }
1217 break;
1218 }
1219 } else {
1220 for (int i = 0; i < item_list.size(); ++i) {
1222 if (item.skip())
1223 continue;
1225 "QDockAreaLayoutInfo::insertGap", "inserting two gaps after each other");
1226 space += item.size - pick(o, item.minimumSize());
1227 qCDebug(lcQpaDockWidgets) << "Item space:" << item.flags << this;
1228 }
1229 }
1230
1231 // find the actual size of the gap
1232 int gap_size = 0;
1233 int sep_size = 0;
1234 if (isEmpty()) {
1235 gap_size = space;
1236 sep_size = 0;
1237 } else {
1238 QRect r = dockedGeometry(dockWidgetItem->widget());
1239 gap_size = pick(o, r.size());
1241 sep_size += *sep;
1243 sep_size += *sep;
1244 }
1245 if (gap_size + sep_size > space)
1246 gap_size = pick(o, gap_item.minimumSize());
1247 gap_item.size = gap_size + sep_size;
1248 }
1249
1250 // finally, insert the gap
1251 item_list.insert(index, gap_item);
1252 qCDebug(lcQpaDockWidgets) << "Insert gap after:" << index << this;
1253
1254 return true;
1255}
1256
1258{
1259 for (int i = 0; i < item_list.size(); ++i) {
1261 if (item.skip())
1262 continue;
1263
1264#if QT_CONFIG(tabbar)
1265 if (tabbed && widget == tabBar)
1266 return this;
1267#endif
1268
1269 if (item.widgetItem != nullptr && item.widgetItem->widget() == widget)
1270 return this;
1271
1272 if (item.subinfo != nullptr) {
1273 if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
1274 return result;
1275 }
1276 }
1277
1278 return nullptr;
1279}
1280
1282{
1283 int index = path.first();
1284 if (index < 0)
1285 index = -index - 1;
1286 if (index >= item_list.size())
1287 return this;
1288 if (path.size() == 1 || item_list[index].subinfo == nullptr)
1289 return this;
1290 return item_list[index].subinfo->info(path.mid(1));
1291}
1292
1294{
1296
1297 if (item.skip())
1298 return QRect();
1299
1300 if (isGap && !(item.flags & QDockAreaLayoutItem::GapItem))
1301 return QRect();
1302
1303 QRect result;
1304
1305#if QT_CONFIG(tabbar)
1306 if (tabbed) {
1307 if (isGap || tabId(item) == currentTabId())
1308 result = tabContentRect();
1309 } else
1310#endif
1311 {
1312 int pos = item.pos;
1313 int size = item.size;
1314
1315 if (isGap) {
1316 int prev = this->prev(index);
1317 int next = this->next(index);
1319 pos += *sep;
1320 size -= *sep;
1321 }
1323 size -= *sep;
1324 }
1325
1326 QPoint p;
1327 rpick(o, p) = pos;
1328 rperp(o, p) = perp(o, rect.topLeft());
1329 QSize s;
1330 rpick(o, s) = size;
1331 rperp(o, s) = perp(o, rect.size());
1332 result = QRect(p, s);
1333 }
1334
1335 return result;
1336}
1337
1339{
1340 Q_ASSERT(!path.isEmpty());
1341
1342 const int index = path.first();
1343 if (path.size() > 1) {
1345 Q_ASSERT(item.subinfo != nullptr);
1346 return item.subinfo->itemRect(path.mid(1));
1347 }
1348
1349 return itemRect(index);
1350}
1351
1353{
1354#if QT_CONFIG(tabbar)
1355 if (tabbed)
1356 return QRect();
1357#endif
1358
1360 if (item.skip())
1361 return QRect();
1362
1363 QPoint pos = rect.topLeft();
1364 rpick(o, pos) = item.pos + item.size;
1365 QSize s = rect.size();
1366 rpick(o, s) = *sep;
1367
1368 return QRect(pos, s);
1369}
1370
1372{
1373 Q_ASSERT(!path.isEmpty());
1374
1375 const int index = path.first();
1376 if (path.size() > 1) {
1378 Q_ASSERT(item.subinfo != nullptr);
1379 return item.subinfo->separatorRect(path.mid(1));
1380 }
1381 return separatorRect(index);
1382}
1383
1385{
1386#if QT_CONFIG(tabbar)
1387 if (tabbed)
1388 return QList<int>();
1389#endif
1390
1391 int pos = pick(o, _pos);
1392
1393 for (int i = 0; i < item_list.size(); ++i) {
1395 if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
1396 continue;
1397
1398 if (item.pos + item.size > pos) {
1399 if (item.subinfo != nullptr) {
1400 QList<int> result = item.subinfo->findSeparator(_pos);
1401 if (!result.isEmpty()) {
1402 result.prepend(i);
1403 return result;
1404 } else {
1405 return QList<int>();
1406 }
1407 }
1408 }
1409
1410 int next = this->next(i);
1411 if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1412 continue;
1413
1414 QRect sepRect = separatorRect(i);
1415 if (!sepRect.isNull() && *sep == 1)
1416 sepRect.adjust(-2, -2, 2, 2);
1417 //we also make sure we don't find a separator that's not there
1418 if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
1419 return QList<int>() << i;
1420 }
1421
1422 }
1423
1424 return QList<int>();
1425}
1426
1428{
1429 for (int i = 0; i < item_list.size(); ++i) {
1431
1432 if (item.subinfo != nullptr) {
1433 QList<int> result = item.subinfo->indexOfPlaceHolder(objectName);
1434 if (!result.isEmpty()) {
1435 result.prepend(i);
1436 return result;
1437 }
1438 continue;
1439 }
1440
1441 if (item.placeHolderItem != nullptr && item.placeHolderItem->objectName == objectName) {
1443 result << i;
1444 return result;
1445 }
1446 }
1447
1448 return QList<int>();
1449}
1450
1452{
1453 for (int i = 0; i < item_list.size(); ++i) {
1455
1456 if (item.placeHolderItem != nullptr)
1457 continue;
1458
1459 if (item.subinfo != nullptr) {
1460 QList<int> result = item.subinfo->indexOf(widget);
1461 if (!result.isEmpty()) {
1462 result.prepend(i);
1463 return result;
1464 }
1465 continue;
1466 }
1467
1468 if (!(item.flags & QDockAreaLayoutItem::GapItem) && item.widgetItem && item.widgetItem->widget() == widget) {
1470 result << i;
1471 return result;
1472 }
1473 }
1474
1475 return QList<int>();
1476}
1477
1479{
1481 Q_ASSERT(result != nullptr);
1482 return result;
1483}
1484
1486{
1487 return perp(o, minimumSize()) == perp(o, maximumSize());
1488}
1489
1494{
1495 QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
1496
1497#if QT_CONFIG(tabbar)
1498 if (tabbed) {
1499 QRect tab_rect;
1500 QSize tbh = tabBarSizeHint();
1501
1502 if (!tbh.isNull()) {
1503 switch (tabBarShape) {
1506 tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
1507 break;
1510 tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
1511 rect.width(), tbh.height());
1512 break;
1515 tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
1516 tbh.width(), rect.height());
1517 break;
1520 tab_rect = QRect(rect.left(), rect.top(),
1521 tbh.width(), rect.height());
1522 break;
1523 default:
1524 break;
1525 }
1526 }
1527
1528 widgetAnimator.animate(tabBar, tab_rect, animate);
1529 }
1530#endif // QT_CONFIG(tabbar)
1531
1532 QDockWidget *activated = nullptr;
1533
1534 for (int i = 0; i < item_list.size(); ++i) {
1536
1538 continue;
1539
1540 if (item.subinfo != nullptr) {
1541 item.subinfo->apply(animate);
1542 continue;
1543 }
1544
1545 if (item.skip())
1546 continue;
1547
1548 Q_ASSERT(item.widgetItem);
1549 QRect r = itemRect(i);
1550 QWidget *w = item.widgetItem->widget();
1551
1552 QRect geo = w->geometry();
1553 widgetAnimator.animate(w, r, animate);
1554 if (!w->isHidden() && w->window()->isVisible()) {
1555 QDockWidget *dw = qobject_cast<QDockWidget*>(w);
1556 if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
1557 dw->lower();
1558 emit dw->visibilityChanged(false);
1559 } else if (r.isValid()
1560 && (geo.right() < 0 || geo.bottom() < 0)) {
1561 emit dw->visibilityChanged(true);
1562 activated = dw;
1563 }
1564 }
1565 }
1566#if QT_CONFIG(tabbar)
1567 if (*sep == 1)
1568 updateSeparatorWidgets();
1569#endif // QT_CONFIG(tabbar)
1570
1571 return activated;
1572}
1573
1574static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
1575{
1576 QStyleOption opt(0);
1578 if (w->isEnabled())
1580 if (o != Qt::Horizontal)
1582 if (mouse_over)
1584 opt.rect = r;
1585 opt.palette = w->palette();
1586
1587 w->style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p, w);
1588}
1589
1591{
1593
1594 if (isEmpty())
1595 return result;
1596#if QT_CONFIG(tabbar)
1597 if (tabbed)
1598 return result;
1599#endif
1600
1601 for (int i = 0; i < item_list.size(); ++i) {
1603
1604 if (item.skip())
1605 continue;
1606
1607 int next = this->next(i);
1608
1609 if (item.subinfo)
1610 result |= item.subinfo->separatorRegion();
1611
1612 if (next == -1)
1613 break;
1615 }
1616
1617 return result;
1618}
1619
1621 const QRegion &clip,
1622 const QPoint &mouse) const
1623{
1624 if (isEmpty())
1625 return;
1626#if QT_CONFIG(tabbar)
1627 if (tabbed)
1628 return;
1629#endif
1630
1631 for (int i = 0; i < item_list.size(); ++i) {
1633
1634 if (item.skip())
1635 continue;
1636
1637 int next = this->next(i);
1640 continue;
1641
1642 if (item.subinfo) {
1643 if (clip.contains(item.subinfo->rect))
1644 item.subinfo->paintSeparators(p, widget, clip, mouse);
1645 }
1646
1647 if (next == -1)
1648 break;
1650 if (clip.contains(r) && !item.hasFixedSize(o))
1651 paintSep(p, widget, r, o, r.contains(mouse));
1652 }
1653}
1654
1656{
1657 for (int i = index + 1; i < item_list.size(); ++i) {
1658 if (!item_list.at(i).skip())
1659 return i;
1660 }
1661 return -1;
1662}
1663
1665{
1666 for (int i = index - 1; i >= 0; --i) {
1667 if (!item_list.at(i).skip())
1668 return i;
1669 }
1670 return -1;
1671}
1672
1673#if QT_CONFIG(tabbar)
1674void QDockAreaLayoutInfo::tab(int index, QLayoutItem *dockWidgetItem)
1675{
1676 if (tabbed) {
1677 item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1678 updateTabBar();
1679 setCurrentTab(dockWidgetItem->widget());
1680 } else {
1681 QDockAreaLayoutInfo *new_info
1682 = new QDockAreaLayoutInfo(sep, dockPos, o, tabBarShape, mainWindow);
1683 item_list[index].subinfo = new_info;
1685 item_list[index].widgetItem = nullptr;
1686 new_info->item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1687 new_info->tabbed = true;
1688 new_info->updateTabBar();
1689 new_info->setCurrentTab(dockWidgetItem->widget());
1690 }
1691}
1692#endif // QT_CONFIG(tabbar)
1693
1695 QLayoutItem *dockWidgetItem)
1696{
1697 if (orientation == o) {
1698 item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
1699 } else {
1700#if !QT_CONFIG(tabbar)
1701 const int tabBarShape = 0;
1702#endif
1703 QDockAreaLayoutInfo *new_info
1704 = new QDockAreaLayoutInfo(sep, dockPos, orientation, tabBarShape, mainWindow);
1705 item_list[index].subinfo = new_info;
1707 item_list[index].widgetItem = nullptr;
1708 new_info->item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1709 }
1710}
1711
1713{
1714 Q_ASSERT(!path.isEmpty());
1715 const int index = path.first();
1716 if (path.size() > 1) {
1718 Q_ASSERT(item.subinfo != nullptr);
1719 return item.subinfo->item(path.mid(1));
1720 }
1721 return item_list[index];
1722}
1723
1725{
1726 for (int i = 0; i < item_list.size(); ++i) {
1728 if (item.placeHolderItem != nullptr)
1729 continue;
1730 if (item.subinfo) {
1731 if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
1732 return ret;
1733 } else if (item.widgetItem) {
1734 if ((*x)++ == index)
1735 return item.widgetItem;
1736 }
1737 }
1738 return nullptr;
1739}
1740
1742{
1743 for (int i = 0; i < item_list.size(); ++i) {
1745 if (item.placeHolderItem != nullptr)
1746 continue;
1747 else if (item.subinfo) {
1748 if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
1749 unnest(i);
1750 return ret;
1751 }
1752 } else if (item.widgetItem) {
1753 if ((*x)++ == index) {
1754 item.placeHolderItem = new QPlaceHolderItem(item.widgetItem->widget());
1755 QLayoutItem *ret = item.widgetItem;
1756 item.widgetItem = nullptr;
1757 if (item.size != -1)
1759 return ret;
1760 }
1761 }
1762 }
1763 return nullptr;
1764}
1765
1767{
1768 for (int i = 0; i < item_list.size(); ++i) {
1770 if (item.subinfo) {
1771 item.subinfo->deleteAllLayoutItems();
1772 } else {
1773 delete item.widgetItem;
1774 item.widgetItem = nullptr;
1775 }
1776 }
1777}
1778
1780{
1781#if QT_CONFIG(tabbar)
1782 if (tabbed) {
1783 stream << (uchar) TabMarker;
1784
1785 // write the index in item_list of the widget that's currently on top.
1786 quintptr id = currentTabId();
1787 int index = -1;
1788 for (int i = 0; i < item_list.size(); ++i) {
1789 if (tabId(item_list.at(i)) == id) {
1790 index = i;
1791 break;
1792 }
1793 }
1794 stream << index;
1795 } else
1796#endif // QT_CONFIG(tabbar)
1797 {
1799 }
1800
1801 stream << (uchar) o << int(item_list.size());
1802
1803 for (int i = 0; i < item_list.size(); ++i) {
1805 if (item.widgetItem != nullptr) {
1807 QWidget *w = item.widgetItem->widget();
1808 QString name = w->objectName();
1809 if (Q_UNLIKELY(name.isEmpty())) {
1810 qWarning("QMainWindow::saveState(): 'objectName' not set for QDockWidget %p '%ls;",
1811 w, qUtf16Printable(w->windowTitle()));
1812 }
1813 stream << name;
1814
1815 uchar flags = 0;
1816 if (!w->isHidden())
1818 if (w->isWindow())
1820 stream << flags;
1821
1822 if (w->isWindow()) {
1823 const QRect geometry = w->geometry();
1824 stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
1825 } else {
1826 stream << item.pos << item.size << pick(o, item.minimumSize())
1827 << pick(o, item.maximumSize());
1828 }
1829 } else if (item.placeHolderItem != nullptr) {
1831 stream << item.placeHolderItem->objectName;
1832 uchar flags = 0;
1833 if (!item.placeHolderItem->hidden)
1835 if (item.placeHolderItem->window)
1837 stream << flags;
1838 if (item.placeHolderItem->window) {
1839 QRect r = item.placeHolderItem->topLevelRect;
1840 stream << r.x() << r.y() << r.width() << r.height();
1841 } else {
1842 stream << item.pos << item.size << (int)0 << (int)0;
1843 }
1844 } else if (item.subinfo != nullptr) {
1845 stream << (uchar) SequenceMarker << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
1846 item.subinfo->saveState(stream);
1847 }
1848 }
1849}
1850
1852{
1853 switch (pos) {
1858 default: break;
1859 }
1860 return Qt::NoDockWidgetArea;
1861}
1862
1864{
1865 uchar marker;
1866 stream >> marker;
1868 return false;
1869
1870#if QT_CONFIG(tabbar)
1871 tabbed = marker == TabMarker;
1872
1873 int index = -1;
1874 if (tabbed)
1875 stream >> index;
1876#endif
1877
1878 uchar orientation;
1879 stream >> orientation;
1880 o = static_cast<Qt::Orientation>(orientation);
1881
1882 int cnt;
1883 stream >> cnt;
1884
1885 for (int i = 0; i < cnt; ++i) {
1886 uchar nextMarker;
1887 stream >> nextMarker;
1888 if (nextMarker == WidgetMarker) {
1889 QString name;
1890 uchar flags;
1891 stream >> name >> flags;
1892 if (name.isEmpty()) {
1893 int dummy;
1894 stream >> dummy >> dummy >> dummy >> dummy;
1895 continue;
1896 }
1897
1898 QDockWidget *widget = nullptr;
1899 for (int j = 0; j < widgets.size(); ++j) {
1900 if (widgets.at(j)->objectName() == name) {
1902 break;
1903 }
1904 }
1905
1906 if (widget == nullptr) {
1907 QPlaceHolderItem *placeHolder = new QPlaceHolderItem;
1908 QDockAreaLayoutItem item(placeHolder);
1909
1910 placeHolder->objectName = name;
1911 placeHolder->window = flags & StateFlagFloating;
1912 placeHolder->hidden = !(flags & StateFlagVisible);
1913 if (placeHolder->window) {
1914 int x, y, w, h;
1915 stream >> x >> y >> w >> h;
1916 placeHolder->topLevelRect = QRect(x, y, w, h);
1917 } else {
1918 int dummy;
1919 stream >> item.pos >> item.size >> dummy >> dummy;
1920 }
1921 if (item.size != -1)
1923 if (!testing)
1925 } else {
1927 if (flags & StateFlagFloating) {
1928 bool drawer = false;
1929
1930 if (!testing) {
1931 widget->hide();
1932 if (!drawer)
1933 widget->setFloating(true);
1934 }
1935
1936 int x, y, w, h;
1937 stream >> x >> y >> w >> h;
1938
1939 if (!testing)
1941
1942 if (!testing) {
1945 }
1946 } else {
1947 int dummy;
1948 stream >> item.pos >> item.size >> dummy >> dummy;
1949 if (!testing) {
1951 widget->setFloating(false);
1953 emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
1954 }
1955 }
1956 if (testing) {
1957 //was it is not really added to the layout, we need to delete the object here
1958 delete item.widgetItem;
1959 }
1960 }
1961 } else if (nextMarker == SequenceMarker) {
1962 int dummy;
1963#if !QT_CONFIG(tabbar)
1964 const int tabBarShape = 0;
1965#endif
1967 tabBarShape, mainWindow));
1968 stream >> item.pos >> item.size >> dummy >> dummy;
1969 //we need to make sure the element is in the list so the dock widget can eventually be docked correctly
1970 if (!testing)
1972
1973 //here we need to make sure we change the item in the item_list
1974 QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
1975
1976 if (!lastItem.subinfo->restoreState(stream, widgets, testing))
1977 return false;
1978
1979 } else {
1980 return false;
1981 }
1982 }
1983
1984#if QT_CONFIG(tabbar)
1985 if (!testing && tabbed && index >= 0 && index < item_list.size()) {
1986 updateTabBar();
1987 setCurrentTabId(tabId(item_list.at(index)));
1988 }
1989 if (!testing && *sep == 1)
1990 updateSeparatorWidgets();
1991#endif
1992
1993 return true;
1994}
1995
1996#if QT_CONFIG(tabbar)
1997void QDockAreaLayoutInfo::updateSeparatorWidgets() const
1998{
1999 if (tabbed) {
2001 return;
2002 }
2003
2004 int j = 0;
2005 for (int i = 0; i < item_list.size(); ++i) {
2007
2008 if (item.skip())
2009 continue;
2010
2011 int next = this->next(i);
2014 continue;
2015
2016 if (item.subinfo) {
2017 item.subinfo->updateSeparatorWidgets();
2018 }
2019
2020 if (next == -1)
2021 break;
2022
2023 QWidget *sepWidget;
2024 if (j < separatorWidgets.size()) {
2025 sepWidget = separatorWidgets.at(j);
2026 if (!sepWidget) {
2027 qWarning("QDockAreaLayoutInfo::updateSeparatorWidgets: null separator widget");
2028 sepWidget = mainWindowLayout()->getSeparatorWidget();
2029 separatorWidgets[j] = sepWidget;
2030 }
2031 } else {
2032 sepWidget = mainWindowLayout()->getSeparatorWidget();
2033 separatorWidgets.append(sepWidget);
2034 }
2035 j++;
2036
2037 Q_ASSERT(sepWidget);
2038 sepWidget->raise();
2039
2040 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
2041 sepWidget->setGeometry(sepRect);
2042 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
2043 sepWidget->show();
2044 }
2045
2046 for (int k = j; k < separatorWidgets.size(); ++k) {
2047 separatorWidgets[k]->hide();
2048 }
2050}
2051
2057void QDockAreaLayoutInfo::reparentWidgets(QWidget *parent)
2058{
2059 if (tabBar)
2060 tabBar->setParent(parent);
2061
2062 for (int i = 0; i < item_list.size(); ++i) {
2065 continue;
2066 if (item.subinfo)
2067 item.subinfo->reparentWidgets(parent);
2068 if (item.widgetItem) {
2069 QWidget *w = item.widgetItem->widget();
2070 if (qobject_cast<QDockWidgetGroupWindow *>(w))
2071 continue;
2072 if (w->parent() != parent) {
2073 bool hidden = w->isHidden();
2074 w->setParent(parent, w->windowFlags());
2075 if (!hidden)
2076 w->show();
2077 }
2078 }
2079 }
2080}
2081
2082//returns whether the tabbar is visible or not
2083bool QDockAreaLayoutInfo::updateTabBar() const
2084{
2085 if (!tabbed)
2086 return false;
2087
2088 QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
2089
2090 if (that->tabBar == nullptr) {
2091 that->tabBar = mainWindowLayout()->getTabBar();
2092 that->tabBar->setShape(static_cast<QTabBar::Shape>(tabBarShape));
2093 that->tabBar->setDrawBase(true);
2094 }
2095
2096 const QSignalBlocker blocker(tabBar);
2097 bool gap = false;
2098
2099 const quintptr oldCurrentId = currentTabId();
2100
2101 int tab_idx = 0;
2102 for (int i = 0; i < item_list.size(); ++i) {
2104 if (item.skip())
2105 continue;
2107 gap = true;
2108 continue;
2109 }
2110 if (item.widgetItem == nullptr)
2111 continue;
2112
2113 QDockWidget *dw = qobject_cast<QDockWidget*>(item.widgetItem->widget());
2114 QString title = dw->d_func()->fixedWindowTitle;
2115 quintptr id = tabId(item);
2116 if (tab_idx == tabBar->count()) {
2117 tabBar->insertTab(tab_idx, title);
2118#if QT_CONFIG(tooltip)
2119 tabBar->setTabToolTip(tab_idx, title);
2120#endif
2121 tabBar->setTabData(tab_idx, id);
2122 } else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
2123 if (tab_idx + 1 < tabBar->count()
2124 && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
2125 tabBar->removeTab(tab_idx);
2126 else {
2127 tabBar->insertTab(tab_idx, title);
2128#if QT_CONFIG(tooltip)
2129 tabBar->setTabToolTip(tab_idx, title);
2130#endif
2131 tabBar->setTabData(tab_idx, id);
2132 }
2133 }
2134
2135 if (title != tabBar->tabText(tab_idx)) {
2136 tabBar->setTabText(tab_idx, title);
2137#if QT_CONFIG(tooltip)
2138 tabBar->setTabToolTip(tab_idx, title);
2139#endif
2140 }
2141
2142 ++tab_idx;
2143 }
2144
2145 while (tab_idx < tabBar->count()) {
2146 tabBar->removeTab(tab_idx);
2147 }
2148
2149 if (oldCurrentId > 0 && currentTabId() != oldCurrentId)
2150 that->setCurrentTabId(oldCurrentId);
2151
2152 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(tabBar->parent()))
2153 dwgw->adjustFlags();
2154
2155 //returns if the tabbar is visible or not
2156 return ( (gap ? 1 : 0) + tabBar->count()) > 1;
2157}
2158
2159void QDockAreaLayoutInfo::setTabBarShape(int shape)
2160{
2161 if (shape == tabBarShape)
2162 return;
2163 tabBarShape = shape;
2164 if (tabBar != nullptr)
2165 tabBar->setShape(static_cast<QTabBar::Shape>(shape));
2166
2167 for (int i = 0; i < item_list.size(); ++i) {
2169 if (item.subinfo != nullptr)
2170 item.subinfo->setTabBarShape(shape);
2171 }
2172}
2173
2174QSize QDockAreaLayoutInfo::tabBarMinimumSize() const
2175{
2176 if (!updateTabBar())
2177 return QSize(0, 0);
2178
2179 return tabBar->minimumSizeHint();
2180}
2181
2182QSize QDockAreaLayoutInfo::tabBarSizeHint() const
2183{
2184 if (!updateTabBar())
2185 return QSize(0, 0);
2186
2187 return tabBar->sizeHint();
2188}
2189
2190QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars() const
2191{
2193
2194 if (tabbed) {
2195 updateTabBar();
2196 result.insert(tabBar);
2197 }
2198
2199 for (int i = 0; i < item_list.size(); ++i) {
2201 if (item.subinfo != nullptr)
2202 result += item.subinfo->usedTabBars();
2203 }
2204
2205 return result;
2206}
2207
2208// returns a set of all used separator widgets for this dockarelayout info
2209// and all subinfos
2210QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
2211{
2213 const int numSeparatorWidgets = separatorWidgets.size();
2214 result.reserve(numSeparatorWidgets);
2215
2216 for (int i = 0; i < numSeparatorWidgets; ++i)
2218
2219 for (int i = 0; i < item_list.size(); ++i) {
2221 if (item.subinfo != nullptr)
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) {
2240 result.adjust(0, tbh.height(), 0, 0);
2241 break;
2244 result.adjust(0, 0, 0, -tbh.height());
2245 break;
2248 result.adjust(0, 0, -tbh.width(), 0);
2249 break;
2252 result.adjust(tbh.width(), 0, 0, 0);
2253 break;
2254 default:
2255 break;
2256 }
2257 }
2258
2259 return result;
2260}
2261
2262int QDockAreaLayoutInfo::tabIndexToListIndex(int tabIndex) const
2263{
2264 Q_ASSERT(tabbed && tabBar);
2265 quintptr data = qvariant_cast<quintptr>(tabBar->tabData(tabIndex));
2266 for (int i = 0; i < item_list.size(); ++i) {
2267 if (tabId(item_list.at(i)) == data)
2268 return i;
2269 }
2270 return -1;
2271}
2272
2273void QDockAreaLayoutInfo::moveTab(int from, int to)
2274{
2275 item_list.move(tabIndexToListIndex(from), tabIndexToListIndex(to));
2276}
2277#endif // QT_CONFIG(tabbar)
2278
2279/******************************************************************************
2280** QDockAreaLayout
2281*/
2282
2284{
2285 mainWindow = win;
2287#if QT_CONFIG(tabbar)
2288 const int tabShape = QTabBar::RoundedSouth;
2289#else
2290 const int tabShape = 0;
2291#endif
2300 centralWidgetItem = nullptr;
2301
2302
2307}
2308
2310{
2311 return rect.isValid();
2312}
2313
2315{
2317 int cnt = 0;
2318 for (int i = 0; i < QInternal::DockCount; ++i) {
2319 if (!docks[i].item_list.isEmpty())
2320 ++cnt;
2321 }
2322 stream << cnt;
2323 for (int i = 0; i < QInternal::DockCount; ++i) {
2324 if (docks[i].item_list.isEmpty())
2325 continue;
2326 stream << i << docks[i].rect.size();
2328 }
2329
2331
2332 for (int i = 0; i < 4; ++i)
2333 stream << static_cast<int>(corners[i]);
2334}
2335
2337{
2338 QList<QDockWidget*> dockwidgets = _dockwidgets;
2339
2340 int cnt;
2341 stream >> cnt;
2342 for (int i = 0; i < cnt; ++i) {
2343 int pos;
2344 stream >> pos;
2345 QSize size;
2346 stream >> size;
2347 if (!testing) {
2348 docks[pos].rect = QRect(QPoint(0, 0), size);
2349 }
2350 if (!docks[pos].restoreState(stream, dockwidgets, testing)) {
2352 return false;
2353 }
2354 }
2355
2356 QSize size;
2357 stream >> size;
2359
2360 bool ok = stream.status() == QDataStream::Ok;
2361
2362 if (ok) {
2363 int cornerData[4];
2364 for (int i = 0; i < 4; ++i)
2365 stream >> cornerData[i];
2366 if (stream.status() == QDataStream::Ok) {
2367 for (int i = 0; i < 4; ++i)
2368 corners[i] = static_cast<Qt::DockWidgetArea>(cornerData[i]);
2369 }
2370
2371 if (!testing)
2372 fallbackToSizeHints = false;
2373 }
2374
2375 return ok;
2376}
2377
2379{
2380 for (int i = 0; i < QInternal::DockCount; ++i) {
2382 if (!result.isEmpty()) {
2383 result.prepend(i);
2384 return result;
2385 }
2386 }
2387 return QList<int>();
2388}
2389
2391{
2392 for (int i = 0; i < QInternal::DockCount; ++i) {
2394 if (!result.isEmpty()) {
2395 result.prepend(i);
2396 return result;
2397 }
2398 }
2399 return QList<int>();
2400}
2401
2402QList<int> QDockAreaLayout::gapIndex(const QPoint &pos, bool disallowTabs) const
2403{
2404 QMainWindow::DockOptions opts = mainWindow->dockOptions();
2405 bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
2407#if QT_CONFIG(tabbar)
2408 if (!disallowTabs) {
2413
2414 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
2415 nestingEnabled = false;
2416 }
2417#endif
2418
2419
2420 for (int i = 0; i < QInternal::DockCount; ++i) {
2421 const QDockAreaLayoutInfo &info = docks[i];
2422
2423 if (!info.isEmpty() && info.rect.contains(pos)) {
2425 = docks[i].gapIndex(pos, nestingEnabled, tabMode);
2426 if (!result.isEmpty())
2427 result.prepend(i);
2428 return result;
2429 }
2430 }
2431
2432 for (int i = 0; i < QInternal::DockCount; ++i) {
2433 const QDockAreaLayoutInfo &info = docks[i];
2434
2435 if (info.isEmpty()) {
2436 const QRect r = gapRect(static_cast<QInternal::DockPosition>(i));
2437 if (r.contains(pos)) {
2438 if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
2439 //in case of ForceTabbedDocks, we pass -1 in order to force the gap to be tabbed
2440 //it mustn't be completely empty otherwise it won't work
2441 return QList<int>() << i << -1 << 0;
2442 } else {
2443 return QList<int>() << i << 0;
2444 }
2445 }
2446 }
2447 }
2448
2449 return QList<int>();
2450}
2451
2453{
2454 Q_ASSERT_X(mainWindow, "QDockAreaLayout::gapRect", "Called without valid mainWindow pointer.");
2455
2456 // Determine gap size depending on MainWindow size (QTBUG-101657)
2457 const QSize gapSize = (mainWindow->size()/2).boundedTo(QSize(EmptyDropAreaSize, EmptyDropAreaSize));
2458
2459 // Warn if main window is too small to create proper docks.
2460 // Do not fail because this can be triggered by a user making MainWindow too small
2461 if (mainWindow->height() < (2 * sep)) {
2462 qCWarning(lcQpaDockWidgets,
2463 "QDockAreaLayout::gapRect: Main window height %i is too small. Docking will not be possible.",
2464 mainWindow->height());
2465
2466 }
2467 if (mainWindow->width() < (2 * sep)) {
2468 qCWarning(lcQpaDockWidgets,
2469 "QDockAreaLayout::gapRect: Main window width %i is too small. Docking will not be possible.",
2470 mainWindow->width());
2471 }
2472
2473 // Calculate rectangle of requested dock
2474 switch (dockPos) {
2476 return QRect(rect.left(), rect.top(), gapSize.width(), rect.height());
2478 return QRect(rect.right() - gapSize.width(), rect.top(), gapSize.width(), rect.height());
2479 case QInternal::TopDock:
2480 return QRect(rect.left(), rect.top(), rect.width(), gapSize.height());
2482 return QRect(rect.left(), rect.bottom() - gapSize.height(), rect.width(), gapSize.height());
2484 break;
2485 }
2486 return QRect();
2487}
2488
2490{
2492 for (int i = 0; i < QInternal::DockCount; ++i) {
2493 const QDockAreaLayoutInfo &info = docks[i];
2494 if (info.isEmpty())
2495 continue;
2497 if (!rect.isNull() && sep == 1)
2498 rect.adjust(-2, -2, 2, 2);
2499 if (rect.contains(pos) && !info.hasFixedSize()) {
2500 result << i;
2501 break;
2502 } else if (info.rect.contains(pos)) {
2504 if (!result.isEmpty()) {
2505 result.prepend(i);
2506 break;
2507 }
2508 }
2509 }
2510
2511 return result;
2512}
2513
2515{
2516 for (int i = 0; i < QInternal::DockCount; ++i) {
2518 return result;
2519 }
2520
2521 return nullptr;
2522}
2523
2525{
2526 Q_ASSERT(!path.isEmpty());
2527 const int index = path.first();
2529
2530 if (path.size() == 1)
2531 return &docks[index];
2532
2533 return docks[index].info(path.mid(1));
2534}
2535
2537{
2538 return const_cast<QDockAreaLayout*>(this)->info(path);
2539}
2540
2542{
2543 Q_ASSERT(!path.isEmpty());
2544 const int index = path.first();
2546 return docks[index].item(path.mid(1));
2547}
2548
2550{
2551 Q_ASSERT(!path.isEmpty());
2552 const int index = path.first();
2554 return docks[index].itemRect(path.mid(1));
2555}
2556
2558{
2559 const QDockAreaLayoutInfo &dock = docks[index];
2560 if (dock.isEmpty())
2561 return QRect();
2562 QRect r = dock.rect;
2563 switch (index) {
2565 return QRect(r.right() + 1, r.top(), sep, r.height());
2567 return QRect(r.left() - sep, r.top(), sep, r.height());
2568 case QInternal::TopDock:
2569 return QRect(r.left(), r.bottom() + 1, r.width(), sep);
2571 return QRect(r.left(), r.top() - sep, r.width(), sep);
2572 default:
2573 break;
2574 }
2575 return QRect();
2576}
2577
2579{
2580 Q_ASSERT(!path.isEmpty());
2581
2582 const int index = path.first();
2584
2585 if (path.size() == 1)
2586 return separatorRect(index);
2587 else
2588 return docks[index].separatorRect(path.mid(1));
2589}
2590
2592{
2593 Q_ASSERT(!path.isEmpty());
2594 const int index = path.first();
2596 return docks[index].insertGap(path.mid(1), dockWidgetItem);
2597}
2598
2600{
2601#if QT_CONFIG(tabbar)
2602 Q_ASSERT(!path.isEmpty());
2603 const int index = path.first();
2605 QLayoutItem *item = docks[index].plug(path.mid(1));
2606 docks[index].reparentWidgets(mainWindow);
2607 return item;
2608#else
2609 return nullptr;
2610#endif
2611}
2612
2614{
2615 Q_ASSERT(!path.isEmpty());
2616 const int index = path.first();
2618 return docks[index].unplug(path.mid(1));
2619}
2620
2622{
2623 Q_ASSERT(!path.isEmpty());
2624 const int index = path.first();
2626 docks[index].remove(path.mid(1));
2627}
2628
2630{
2632 if (!index.isEmpty())
2633 remove(index);
2634 const auto groups =
2635 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
2636 for (QDockWidgetGroupWindow *dwgw : groups) {
2637 index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
2638 if (!index.isEmpty()) {
2639 dwgw->layoutInfo()->remove(index);
2640 dwgw->destroyOrHideIfEmpty();
2641 }
2642 }
2643}
2644
2645static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
2646
2648 QList<QLayoutStruct> *_hor_struct_list)
2649{
2650 QSize center_hint(0, 0);
2651 QSize center_min(0, 0);
2652 QSize center_max(0, 0);
2653 const bool have_central = centralWidgetItem != nullptr && !centralWidgetItem->isEmpty();
2654 if (have_central) {
2655 center_hint = centralWidgetRect.size();
2656 if (!center_hint.isValid())
2657 center_hint = centralWidgetItem->sizeHint();
2658 center_min = centralWidgetItem->minimumSize();
2659 center_max = centralWidgetItem->maximumSize();
2660 }
2661
2662 QRect center_rect = rect;
2663 if (!docks[QInternal::LeftDock].isEmpty())
2664 center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
2665 if (!docks[QInternal::TopDock].isEmpty())
2666 center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
2667 if (!docks[QInternal::RightDock].isEmpty())
2668 center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
2669 if (!docks[QInternal::BottomDock].isEmpty())
2671
2672 QSize left_hint = docks[QInternal::LeftDock].size();
2673 if (left_hint.isNull() || fallbackToSizeHints)
2674 left_hint = docks[QInternal::LeftDock].sizeHint();
2677 left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
2678
2679 QSize right_hint = docks[QInternal::RightDock].size();
2680 if (right_hint.isNull() || fallbackToSizeHints)
2681 right_hint = docks[QInternal::RightDock].sizeHint();
2684 right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
2685
2686 QSize top_hint = docks[QInternal::TopDock].size();
2687 if (top_hint.isNull() || fallbackToSizeHints)
2688 top_hint = docks[QInternal::TopDock].sizeHint();
2691 top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
2692
2693 QSize bottom_hint = docks[QInternal::BottomDock].size();
2694 if (bottom_hint.isNull() || fallbackToSizeHints)
2695 bottom_hint = docks[QInternal::BottomDock].sizeHint();
2698 bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
2699
2700 if (_ver_struct_list != nullptr) {
2701 QList<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
2702 ver_struct_list.resize(3);
2703
2704 // top --------------------------------------------------
2705 ver_struct_list[0].init();
2706 ver_struct_list[0].stretch = 0;
2707 ver_struct_list[0].sizeHint = top_hint.height();
2708 ver_struct_list[0].minimumSize = top_min.height();
2709 ver_struct_list[0].maximumSize = top_max.height();
2710 ver_struct_list[0].expansive = false;
2711 ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
2712 ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
2713 ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
2714
2715 // center --------------------------------------------------
2716 ver_struct_list[1].init();
2717 ver_struct_list[1].stretch = center_hint.height();
2718
2719 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2721 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2723 bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2727
2728 int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
2729 int right = (tr_significant && br_significant) ? right_hint.height() : 0;
2730 ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
2731
2732 left = (tl_significant && bl_significant) ? left_min.height() : 0;
2733 right = (tr_significant && br_significant) ? right_min.height() : 0;
2734 ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
2735 ver_struct_list[1].maximumSize = center_max.height();
2736 ver_struct_list[1].expansive = have_central;
2737 ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
2738 && !have_central
2740 ver_struct_list[1].pos = center_rect.top();
2741 ver_struct_list[1].size = center_rect.height();
2742
2743 // bottom --------------------------------------------------
2744 ver_struct_list[2].init();
2745 ver_struct_list[2].stretch = 0;
2746 ver_struct_list[2].sizeHint = bottom_hint.height();
2747 ver_struct_list[2].minimumSize = bottom_min.height();
2748 ver_struct_list[2].maximumSize = bottom_max.height();
2749 ver_struct_list[2].expansive = false;
2750 ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
2751 ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
2752 ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
2753
2754 for (int i = 0; i < 3; ++i) {
2755 ver_struct_list[i].sizeHint
2756 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
2757 }
2758 if (have_central && ver_struct_list[0].empty && ver_struct_list[2].empty)
2759 ver_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2760 }
2761
2762 if (_hor_struct_list != nullptr) {
2763 QList<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
2764 hor_struct_list.resize(3);
2765
2766 // left --------------------------------------------------
2767 hor_struct_list[0].init();
2768 hor_struct_list[0].stretch = 0;
2769 hor_struct_list[0].sizeHint = left_hint.width();
2770 hor_struct_list[0].minimumSize = left_min.width();
2771 hor_struct_list[0].maximumSize = left_max.width();
2772 hor_struct_list[0].expansive = false;
2773 hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
2774 hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
2775 hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
2776
2777 // center --------------------------------------------------
2778 hor_struct_list[1].init();
2779 hor_struct_list[1].stretch = center_hint.width();
2780
2781 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
2783 bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
2785 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
2787 bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
2789
2790 int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
2791 int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
2792 hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
2793
2794 top = (tl_significant && tr_significant) ? top_min.width() : 0;
2795 bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
2796 hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
2797
2798 hor_struct_list[1].maximumSize = center_max.width();
2799 hor_struct_list[1].expansive = have_central;
2800 hor_struct_list[1].empty = !have_central;
2801 hor_struct_list[1].pos = center_rect.left();
2802 hor_struct_list[1].size = center_rect.width();
2803
2804 // right --------------------------------------------------
2805 hor_struct_list[2].init();
2806 hor_struct_list[2].stretch = 0;
2807 hor_struct_list[2].sizeHint = right_hint.width();
2808 hor_struct_list[2].minimumSize = right_min.width();
2809 hor_struct_list[2].maximumSize = right_max.width();
2810 hor_struct_list[2].expansive = false;
2811 hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
2812 hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
2813 hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
2814
2815 for (int i = 0; i < 3; ++i) {
2816 hor_struct_list[i].sizeHint
2817 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
2818 }
2819 if (have_central && hor_struct_list[0].empty && hor_struct_list[2].empty)
2820 hor_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2821
2822 }
2823}
2824
2826 QList<QLayoutStruct> *hor_struct_list)
2827{
2828
2829 // top ---------------------------------------------------
2830
2831 if (!docks[QInternal::TopDock].isEmpty()) {
2833 if (hor_struct_list != nullptr) {
2835 || docks[QInternal::LeftDock].isEmpty()
2836 ? rect.left() : hor_struct_list->at(1).pos);
2838 || docks[QInternal::RightDock].isEmpty()
2839 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
2840 }
2841 if (ver_struct_list != nullptr) {
2842 r.setTop(rect.top());
2843 r.setBottom(ver_struct_list->at(1).pos - sep - 1);
2844 }
2847 }
2848
2849 // bottom ---------------------------------------------------
2850
2851 if (!docks[QInternal::BottomDock].isEmpty()) {
2853 if (hor_struct_list != nullptr) {
2855 || docks[QInternal::LeftDock].isEmpty()
2856 ? rect.left() : hor_struct_list->at(1).pos);
2858 || docks[QInternal::RightDock].isEmpty()
2859 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
2860 }
2861 if (ver_struct_list != nullptr) {
2862 r.setTop(ver_struct_list->at(2).pos);
2863 r.setBottom(rect.bottom());
2864 }
2867 }
2868
2869 // left ---------------------------------------------------
2870
2871 if (!docks[QInternal::LeftDock].isEmpty()) {
2873 if (hor_struct_list != nullptr) {
2874 r.setLeft(rect.left());
2875 r.setRight(hor_struct_list->at(1).pos - sep - 1);
2876 }
2877 if (ver_struct_list != nullptr) {
2879 || docks[QInternal::TopDock].isEmpty()
2880 ? rect.top() : ver_struct_list->at(1).pos);
2882 || docks[QInternal::BottomDock].isEmpty()
2883 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
2884 }
2887 }
2888
2889 // right ---------------------------------------------------
2890
2891 if (!docks[QInternal::RightDock].isEmpty()) {
2893 if (hor_struct_list != nullptr) {
2894 r.setLeft(hor_struct_list->at(2).pos);
2895 r.setRight(rect.right());
2896 }
2897 if (ver_struct_list != nullptr) {
2899 || docks[QInternal::TopDock].isEmpty()
2900 ? rect.top() : ver_struct_list->at(1).pos);
2902 || docks[QInternal::BottomDock].isEmpty()
2903 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
2904 }
2907 }
2908
2909 // center ---------------------------------------------------
2910
2911 if (hor_struct_list != nullptr) {
2912 centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
2913 centralWidgetRect.setWidth(hor_struct_list->at(1).size);
2914 }
2915 if (ver_struct_list != nullptr) {
2916 centralWidgetRect.setTop(ver_struct_list->at(1).pos);
2917 centralWidgetRect.setHeight(ver_struct_list->at(1).size);
2918 }
2919}
2920
2922{
2923 QList<QLayoutStruct> ver_struct_list(3);
2924 QList<QLayoutStruct> hor_struct_list(3);
2925 getGrid(&ver_struct_list, &hor_struct_list);
2926
2927 qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
2928 qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
2929
2930 setGrid(&ver_struct_list, &hor_struct_list);
2931}
2932
2934{
2935 for (int i = 0; i < QInternal::DockCount; ++i)
2936 docks[i].clear();
2937
2938 rect = QRect();
2940}
2941
2942template<typename SizePMF, typename CenterPMF>
2943QSize QDockAreaLayout::size_helper(SizePMF sizeFn, CenterPMF centerFn) const
2944{
2945 int left_sep = 0;
2946 int right_sep = 0;
2947 int top_sep = 0;
2948 int bottom_sep = 0;
2949
2950 if (centralWidgetItem != nullptr) {
2951 left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
2952 right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
2953 top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
2954 bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
2955 }
2956
2957 const QSize left = (docks[QInternal::LeftDock].*sizeFn)() + QSize(left_sep, 0);
2958 const QSize right = (docks[QInternal::RightDock].*sizeFn)() + QSize(right_sep, 0);
2959 const QSize top = (docks[QInternal::TopDock].*sizeFn)() + QSize(0, top_sep);
2960 const QSize bottom = (docks[QInternal::BottomDock].*sizeFn)() + QSize(0, bottom_sep);
2961 const QSize center = centralWidgetItem == nullptr
2962 ? QSize(0, 0) : (centralWidgetItem->*centerFn)();
2963
2964 int row1 = top.width();
2965 int row2 = left.width() + center.width() + right.width();
2966 int row3 = bottom.width();
2967 int col1 = left.height();
2968 int col2 = top.height() + center.height() + bottom.height();
2969 int col3 = right.height();
2970
2972 row1 += left.width();
2973 else
2974 col1 += top.height();
2975
2977 row1 += right.width();
2978 else
2979 col3 += top.height();
2980
2982 row3 += left.width();
2983 else
2984 col1 += bottom.height();
2985
2987 row3 += right.width();
2988 else
2989 col3 += bottom.height();
2990
2991 return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
2992}
2993
2995{
2997}
2998
3000{
3002}
3003
3010{
3012}
3013
3021{
3022 QScreen *screen = nullptr;
3023 if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1)
3025 if (!screen)
3026 screen = widget->screen();
3027
3028 const QRect screenRect = screen->geometry();
3029 if (screenRect.isValid()) {
3030 rect.setWidth(qMin(rect.width(), screenRect.width()));
3031 rect.setHeight(qMin(rect.height(), screenRect.height()));
3032 rect.moveLeft(qMax(rect.left(), screenRect.left()));
3033 rect.moveTop(qMax(rect.top(), screenRect.top()));
3034 rect.moveRight(qMin(rect.right(), screenRect.right()));
3035 rect.moveBottom(qMin(rect.bottom(), screenRect.bottom()));
3036 }
3037
3038 return rect;
3039}
3040
3042{
3043 QDockAreaLayoutItem *item = nullptr;
3044 const auto groups =
3045 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
3046 for (QDockWidgetGroupWindow *dwgw : groups) {
3047 QList<int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
3048 if (!index.isEmpty()) {
3049 dockWidget->setParent(dwgw);
3050 item = const_cast<QDockAreaLayoutItem *>(&dwgw->layoutInfo()->item(index));
3051 break;
3052 }
3053 }
3054 if (!item) {
3056 if (index.isEmpty())
3057 return false;
3058 item = const_cast<QDockAreaLayoutItem *>(&this->item(index));
3059 }
3060
3061 QPlaceHolderItem *placeHolder = item->placeHolderItem;
3062 Q_ASSERT(placeHolder != nullptr);
3063
3064 item->widgetItem = new QDockWidgetItem(dockWidget);
3065
3066 if (placeHolder->window) {
3067 const QRect r = constrainedRect(placeHolder->topLevelRect, dockWidget);
3068 dockWidget->d_func()->setWindowState(true, true, r);
3069 }
3070 dockWidget->setVisible(!placeHolder->hidden);
3071
3072 item->placeHolderItem = nullptr;
3073 delete placeHolder;
3074
3075 return true;
3076}
3077
3079 Qt::Orientation orientation)
3080{
3081 QLayoutItem *dockWidgetItem = new QDockWidgetItem(dockWidget);
3083 if (orientation == info.o || info.item_list.size() <= 1) {
3084 // empty dock areas, or dock areas containing exactly one widget can have their orientation
3085 // switched.
3086 info.o = orientation;
3087
3088 QDockAreaLayoutItem new_item(dockWidgetItem);
3089 info.item_list.append(new_item);
3090#if QT_CONFIG(tabbar)
3091 if (info.tabbed && !new_item.skip()) {
3092 info.updateTabBar();
3093 info.setCurrentTabId(tabId(new_item));
3094 }
3095#endif
3096 } else {
3097#if QT_CONFIG(tabbar)
3098 int tbshape = info.tabBarShape;
3099#else
3100 int tbshape = 0;
3101#endif
3102 QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
3104 new_info.item_list.append(QDockAreaLayoutItem(dockWidgetItem));
3105 info = new_info;
3106 }
3107
3109}
3110
3111#if QT_CONFIG(tabbar)
3112void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
3113{
3114 const QList<int> path = indexOf(first);
3115 if (path.isEmpty())
3116 return;
3117
3118 QDockAreaLayoutInfo *info = this->info(path);
3119 Q_ASSERT(info != nullptr);
3120 info->tab(path.last(), new QDockWidgetItem(second));
3121
3122 removePlaceHolder(second->objectName());
3123}
3124#endif // QT_CONFIG(tabbar)
3125
3128{
3129 if (Q_UNLIKELY(docks.size() != sizes.size())) {
3130 qWarning("QMainWidget::resizeDocks: size of the lists are not the same");
3131 return;
3132 }
3133 int count = docks.size();
3134 fallbackToSizeHints = false;
3135 for (int i = 0; i < count; ++i) {
3137 if (Q_UNLIKELY(path.isEmpty())) {
3138 qWarning("QMainWidget::resizeDocks: one QDockWidget is not part of the layout");
3139 continue;
3140 }
3141 int size = sizes[i];
3142 if (Q_UNLIKELY(size <= 0)) {
3143 qWarning("QMainWidget::resizeDocks: all sizes need to be larger than 0");
3144 size = 1;
3145 }
3146
3147 while (path.size() > 1) {
3148 QDockAreaLayoutInfo *info = this->info(path);
3149#if QT_CONFIG(tabbar)
3150 if (!info->tabbed && info->o == o) {
3151 info->item_list[path.constLast()].size = size;
3152 int totalSize = 0;
3153 for (const QDockAreaLayoutItem &item : std::as_const(info->item_list)) {
3154 if (!item.skip()) {
3155 if (totalSize != 0)
3156 totalSize += sep;
3157 totalSize += item.size == -1 ? pick(o, item.sizeHint()) : item.size;
3158 }
3159 }
3160 size = totalSize;
3161 }
3162#endif // QT_CONFIG(tabbar)
3163 path.removeLast();
3164 }
3165
3166 const int dockNum = path.constFirst();
3167 Q_ASSERT(dockNum < QInternal::DockCount);
3168 QRect &r = this->docks[dockNum].rect;
3169 QSize s = r.size();
3170 rpick(o, s) = size;
3171 r.setSize(s);
3172 }
3173}
3174
3177 Qt::Orientation orientation)
3178{
3179 const QList<int> path = indexOf(after);
3180 if (path.isEmpty())
3181 return;
3182
3183 QDockAreaLayoutInfo *info = this->info(path);
3184 Q_ASSERT(info != nullptr);
3185 info->split(path.last(), orientation, new QDockWidgetItem(dockWidget));
3186
3188}
3189
3190void QDockAreaLayout::apply(bool animate)
3191{
3193
3194 for (int i = 0; i < QInternal::DockCount; ++i)
3195 docks[i].apply(animate);
3196 if (centralWidgetItem != nullptr && !centralWidgetItem->isEmpty()) {
3198 animate);
3199 }
3200#if QT_CONFIG(tabbar)
3201 if (sep == 1)
3202 updateSeparatorWidgets();
3203#endif // QT_CONFIG(tabbar)
3204}
3205
3207 const QRegion &clip,
3208 const QPoint &mouse) const
3209{
3210 for (int i = 0; i < QInternal::DockCount; ++i) {
3211 const QDockAreaLayoutInfo &dock = docks[i];
3212 if (dock.isEmpty())
3213 continue;
3215 if (clip.contains(r) && !dock.hasFixedSize()) {
3216 Qt::Orientation opposite = dock.o == Qt::Horizontal
3218 paintSep(p, widget, r, opposite, r.contains(mouse));
3219 }
3220 if (clip.contains(dock.rect))
3221 dock.paintSeparators(p, widget, clip, mouse);
3222 }
3223}
3224
3226{
3228
3229 for (int i = 0; i < QInternal::DockCount; ++i) {
3230 const QDockAreaLayoutInfo &dock = docks[i];
3231 if (dock.isEmpty())
3232 continue;
3234 result |= dock.separatorRegion();
3235 }
3236
3237 return result;
3238}
3239
3240int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &origin,
3241 const QPoint &dest)
3242{
3243 int delta = 0;
3244 int index = separator.last();
3245
3246 if (separator.size() > 1) {
3247 QDockAreaLayoutInfo *info = this->info(separator);
3248 delta = pick(info->o, dest - origin);
3249 if (delta != 0)
3250 delta = info->separatorMove(index, delta);
3251 info->apply(false);
3252 return delta;
3253 }
3254
3256
3258 getGrid(nullptr, &list);
3259 else
3260 getGrid(&list, nullptr);
3261
3262 int sep_index = index == QInternal::LeftDock || index == QInternal::TopDock
3263 ? 0 : 1;
3266 : Qt::Vertical;
3267
3268 delta = pick(o, dest - origin);
3269 delta = separatorMoveHelper(list, sep_index, delta, sep);
3270
3271 fallbackToSizeHints = false;
3272
3274 setGrid(nullptr, &list);
3275 else
3276 setGrid(&list, nullptr);
3277
3278 apply(false);
3279
3280 return delta;
3281}
3282
3283int QDockAreaLayoutInfo::separatorMove(const QList<int> &separator, const QPoint &origin,
3284 const QPoint &dest)
3285{
3286 int delta = 0;
3287 int index = separator.last();
3288 QDockAreaLayoutInfo *info = this->info(separator);
3289 delta = pick(info->o, dest - origin);
3290 if (delta != 0)
3291 delta = info->separatorMove(index, delta);
3292 info->apply(false);
3293 return delta;
3294}
3295
3296#if QT_CONFIG(tabbar)
3297// Sets the correct positions for the separator widgets
3298// Allocates new separator widgets with getSeparatorWidget
3299void QDockAreaLayout::updateSeparatorWidgets() const
3300{
3301 int j = 0;
3302
3303 for (int i = 0; i < QInternal::DockCount; ++i) {
3304 const QDockAreaLayoutInfo &dock = docks[i];
3305 if (dock.isEmpty())
3306 continue;
3307
3308 QWidget *sepWidget;
3309 if (j < separatorWidgets.size()) {
3310 sepWidget = separatorWidgets.at(j);
3311 if (!sepWidget) {
3312 qWarning("QDockAreaLayout::updateSeparatorWidgets: null separator widget");
3313 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3314 separatorWidgets[j] = sepWidget;
3315 }
3316 } else {
3317 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3318 separatorWidgets.append(sepWidget);
3319 }
3320 j++;
3321
3322 Q_ASSERT(sepWidget);
3323 sepWidget->raise();
3324
3325 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
3326 sepWidget->setGeometry(sepRect);
3327 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
3328 sepWidget->show();
3329 }
3330 for (int i = j; i < separatorWidgets.size(); ++i)
3332
3334}
3335#endif // QT_CONFIG(tabbar)
3336
3338{
3339 Q_ASSERT(x != nullptr);
3340
3341 for (int i = 0; i < QInternal::DockCount; ++i) {
3342 const QDockAreaLayoutInfo &dock = docks[i];
3343 if (QLayoutItem *ret = dock.itemAt(x, index))
3344 return ret;
3345 }
3346
3347 if (centralWidgetItem && (*x)++ == index)
3348 return centralWidgetItem;
3349
3350 return nullptr;
3351}
3352
3354{
3355 Q_ASSERT(x != nullptr);
3356
3357 for (int i = 0; i < QInternal::DockCount; ++i) {
3358 QDockAreaLayoutInfo &dock = docks[i];
3359 if (QLayoutItem *ret = dock.takeAt(x, index))
3360 return ret;
3361 }
3362
3363 if (centralWidgetItem && (*x)++ == index) {
3365 centralWidgetItem = nullptr;
3366 return ret;
3367 }
3368
3369 return nullptr;
3370}
3371
3373{
3374 for (int i = 0; i < QInternal::DockCount; ++i)
3376}
3377
3378#if QT_CONFIG(tabbar)
3379QSet<QTabBar*> QDockAreaLayout::usedTabBars() const
3380{
3382 for (int i = 0; i < QInternal::DockCount; ++i) {
3383 const QDockAreaLayoutInfo &dock = docks[i];
3384 result += dock.usedTabBars();
3385 }
3386 return result;
3387}
3388
3389// Returns the set of all used separator widgets
3390QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
3391{
3393 const int numSeparators = separatorWidgets.size();
3394 result.reserve(numSeparators);
3395 for (int i = 0; i < numSeparators; ++i)
3397 for (int i = 0; i < QInternal::DockCount; ++i) {
3398 const QDockAreaLayoutInfo &dock = docks[i];
3399 result += dock.usedSeparatorWidgets();
3400 }
3401 return result;
3402}
3403#endif
3404
3406{
3407 const QDockAreaLayoutInfo *info = this->info(path);
3408 if (info == nullptr)
3409 return QRect();
3410 int index = path.last();
3411 if (index < 0 || index >= info->item_list.size())
3412 return QRect();
3413 return info->itemRect(index, true);
3414}
3415
3417{
3419 if (path.isEmpty())
3420 return;
3421 QDockAreaLayoutItem &item = this->item(path);
3422 if (item.size != -1)
3424}
3425
3427{
3429 if (isValid())
3430 fitLayout();
3431}
3432
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
\inmodule QtCore
QLayoutItem * plug(const QList< int > &path)
void split(int index, Qt::Orientation orientation, QLayoutItem *dockWidgetItem)
QMainWindowLayout * mainWindowLayout() const
QLayoutItem * takeAt(int *x, int index)
bool expansive(Qt::Orientation o) const
bool restoreState(QDataStream &stream, QList< QDockWidget * > &widgets, bool testing)
QRect separatorRect(int index) const
QDockWidget * apply(bool animate)
QInternal::DockPosition dockPos
QDockAreaLayoutItem & item(const QList< int > &path)
int next(int idx) const
bool onlyHasPlaceholders() const
void saveState(QDataStream &stream) const
void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip, const QPoint &mouse) const
QLayoutItem * itemAt(int *x, int index) const
QList< int > indexOf(QWidget *widget) const
QList< QDockAreaLayoutItem > item_list
bool insertGap(const QList< int > &path, QLayoutItem *dockWidgetItem)
QLayoutItem * unplug(const QList< int > &path)
QRect itemRect(int index, bool isGap=false) const
QList< int > findSeparator(const QPoint &pos) const
void remove(const QList< int > &path)
int separatorMove(int index, int delta)
QList< int > indexOfPlaceHolder(const QString &objectName) const
QDockAreaLayoutInfo * info(const QList< int > &path)
QRegion separatorRegion() const
QList< QWidget * > separatorWidgets
QList< int > gapIndex(const QPoint &pos, bool nestingEnabled, TabMode tabMode) const
int prev(int idx) const
bool hasGapItem(const QList< int > &path) const
QRect itemRect(const QList< int > &path) const
QSize size_helper(SizePMF sizeFn, CenterPMF centerFn) const
QLayoutItem * centralWidgetItem
QLayoutItem * itemAt(int *x, int index) const
QLayoutItem * unplug(const QList< int > &path)
QLayoutItem * plug(const QList< int > &path)
QList< int > gapIndex(const QPoint &pos, bool disallowTabs) const
QDockAreaLayoutInfo * info(const QList< int > &path)
void splitDockWidget(QDockWidget *after, QDockWidget *dockWidget, Qt::Orientation orientation)
QList< int > findSeparator(const QPoint &pos) const
bool restoreDockWidget(QDockWidget *dockWidget)
void setGrid(QList< QLayoutStruct > *ver_struct_list, QList< QLayoutStruct > *hor_struct_list)
QSize minimumSize() const
bool restoreState(QDataStream &stream, const QList< QDockWidget * > &widgets, bool testing=false)
void resizeDocks(const QList< QDockWidget * > &docks, const QList< int > &sizes, Qt::Orientation o)
QRect gapRect(const QList< int > &path) const
QDockAreaLayout(QMainWindow *win)
QSize sizeHint() const
void addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget, Qt::Orientation orientation)
void keepSize(QDockWidget *w)
QList< int > indexOfPlaceHolder(const QString &objectName) const
void remove(const QList< int > &path)
QDockAreaLayoutItem & item(const QList< int > &path)
QSize minimumStableSize() const
static QRect constrainedRect(QRect rect, QWidget *widget)
QRect separatorRect(int index) const
void removePlaceHolder(const QString &name)
void getGrid(QList< QLayoutStruct > *ver_struct_list, QList< QLayoutStruct > *hor_struct_list)
QMainWindow * mainWindow
QDockAreaLayoutInfo docks[4]
QRegion separatorRegion() const
int separatorMove(const QList< int > &separator, const QPoint &origin, const QPoint &dest)
Qt::DockWidgetArea corners[4]
bool insertGap(const QList< int > &path, QLayoutItem *dockWidgetItem)
void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip, const QPoint &mouse) const
void apply(bool animate)
QLayoutItem * takeAt(int *x, int index)
QList< QWidget * > separatorWidgets
void saveState(QDataStream &stream) const
QList< int > indexOf(QWidget *dockWidget) const
The QDockWidget class provides a widget that can be docked inside a QMainWindow or floated as a top-l...
Definition qdockwidget.h:20
void visibilityChanged(bool visible)
qint64 size() const
Returns the file size in bytes.
void show()
Shows the item (items are visible by default).
QPointF pos() const
Returns the position of the item in parent coordinates.
QGraphicsWidget * window() const
qreal x() const
This convenience function is equivalent to calling pos().x().
GraphicsItemFlags flags() const
Returns this item's flags.
QScreen * primaryScreen
the primary (or default) screen of the application.
static QScreen * screenAt(const QPoint &point)
Returns the screen at point, or \nullptr if outside of any screen.
The QLayoutItem class provides an abstract item that a QLayout manipulates.
Definition qlayoutitem.h:25
virtual Qt::Orientations expandingDirections() const =0
Returns whether this layout item can make use of more space than sizeHint().
virtual QSize minimumSize() const =0
Implemented in subclasses to return the minimum size of this item.
virtual bool isEmpty() const =0
Implemented in subclasses to return whether this item is empty, i.e.
virtual QSize maximumSize() const =0
Implemented in subclasses to return the maximum size of this item.
virtual QWidget * widget() const
If this item manages a QWidget, returns that widget.
virtual QSize sizeHint() const =0
Implemented in subclasses to return the preferred size of this item.
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
T & last()
Definition qlist.h:631
void removeAt(qsizetype i)
Definition qlist.h:573
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:471
bool empty() const noexcept
Definition qlist.h:682
T takeAt(qsizetype i)
Definition qlist.h:592
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void move(qsizetype from, qsizetype to)
Definition qlist.h:593
qsizetype count() const noexcept
Definition qlist.h:387
void prepend(rvalue_ref t)
Definition qlist.h:456
void resize(qsizetype size)
Definition qlist.h:392
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
QWidgetAnimator widgetAnimator
The QMainWindow class provides a main application window.
Definition qmainwindow.h:25
DockOptions dockOptions
the docking behavior of QMainWindow
Definition qmainwindow.h:40
QString objectName
the name of this object
Definition qobject.h:94
QList< T > findChildren(const QString &aName, Qt::FindChildOptions options=Qt::FindChildrenRecursively) const
Returns all children of this object with the given name that can be cast to type T,...
Definition qobject.h:140
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:372
constexpr void moveBottom(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's bottom edge at the given y coordinate.
Definition qrect.h:297
constexpr void moveRight(int pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's right edge at the given x coordinate.
Definition qrect.h:291
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:169
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:163
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:181
constexpr void setRight(int pos) noexcept
Sets the right edge of the rectangle to the given x coordinate.
Definition qrect.h:196
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:369
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
constexpr void moveLeft(int pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's left edge at the given x coordinate.
Definition qrect.h:285
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
Definition qrect.h:199
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:851
constexpr void setLeft(int pos) noexcept
Sets the left edge of the rectangle to the given x coordinate.
Definition qrect.h:190
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr void setWidth(int w) noexcept
Sets the width of the rectangle to the given width.
Definition qrect.h:380
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:241
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
Definition qrect.h:383
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
Definition qrect.h:288
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
Definition qrect.h:193
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
bool contains(const QPoint &p) const
Returns true if the region contains the point p; otherwise returns false.
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
QRect geometry
the screen's geometry in pixels
Definition qscreen.h:45
Definition qset.h:18
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:443
\inmodule QtCore
Definition qsize.h:25
constexpr QSize boundedTo(const QSize &) const noexcept
Returns a size holding the minimum width and height of this size and the given otherSize.
Definition qsize.h:196
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr QSize grownBy(QMargins m) const noexcept
Definition qsize.h:49
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition qsize.h:191
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:120
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
The QStyleOption class stores the parameters used by QStyle functions.
QStyle::State state
QPalette palette
@ State_MouseOver
Definition qstyle.h:80
@ State_Enabled
Definition qstyle.h:67
@ State_Horizontal
Definition qstyle.h:74
@ State_None
Definition qstyle.h:66
@ PM_DockWidgetSeparatorExtent
Definition qstyle.h:435
@ PE_IndicatorDockWidgetResizeHandle
Definition qstyle.h:132
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
Returns the value of the given pixel metric.
The QTabBar class provides a tab bar, e.g.
Definition qtabbar.h:19
Shape
This enum type lists the built-in shapes supported by QTabBar.
Definition qtabbar.h:42
@ RoundedSouth
Definition qtabbar.h:42
@ RoundedNorth
Definition qtabbar.h:42
@ TriangularEast
Definition qtabbar.h:43
@ RoundedWest
Definition qtabbar.h:42
@ TriangularSouth
Definition qtabbar.h:43
@ RoundedEast
Definition qtabbar.h:42
@ TriangularWest
Definition qtabbar.h:43
@ TriangularNorth
Definition qtabbar.h:43
void animate(QWidget *widget, const QRect &final_geometry, bool animate)
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setGeometry(int x, int y, int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:886
void raise()
Raises this widget to the top of the parent widget's stack.
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
void setMask(const QBitmap &)
Causes only the pixels of the widget for which bitmap has a corresponding 1 bit to be visible.
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition qwidget.h:106
QLayout * layout() const
Returns the layout manager that is installed on this widget, or \nullptr if no layout manager is inst...
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
void hide()
Hides the widget.
Definition qwidget.cpp:8209
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
void setWindowState(Qt::WindowStates state)
Sets the window state to windowState.
Definition qwidget.cpp:2944
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7956
virtual void setVisible(bool visible)
Definition qwidget.cpp:8329
void lower()
Lowers the widget to the bottom of the parent widget's stack.
QStyle * style() const
Definition qwidget.cpp:2607
QScreen * screen() const
Returns the screen the widget is on.
Definition qwidget.cpp:2503
QMargins contentsMargins() const
The contentsMargins function returns the widget's contents margins.
Definition qwidget.cpp:7740
QOpenGLWidget * widget
[1]
rect
[4]
QStyleOptionButton opt
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
@ BottomLeftCorner
@ TopRightCorner
@ TopLeftCorner
@ BottomRightCorner
DockWidgetArea
@ BottomDockWidgetArea
@ NoDockWidgetArea
@ RightDockWidgetArea
@ LeftDockWidgetArea
@ TopDockWidgetArea
Orientation
Definition qnamespace.h:97
@ Horizontal
Definition qnamespace.h:98
@ Vertical
Definition qnamespace.h:99
@ FindDirectChildrenOnly
#define Q_UNLIKELY(x)
static int grow(QLayoutStruct &ls, int delta)
@ StateFlagVisible
@ StateFlagFloating
static QRect dockedGeometry(QWidget *widget)
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
static int realMinSize(const QDockAreaLayoutInfo &info)
QDebug operator<<(QDebug dbg, const QDockAreaLayoutItem &item)
static int qMax(int i1, int i2, int i3)
static int shrink(QLayoutStruct &ls, int delta)
static const int zero
static int separatorMoveHelper(QList< QLayoutStruct > &list, int index, int delta, int sep)
static QInternal::DockPosition dockPosHelper(const QRect &rect, const QPoint &_pos, Qt::Orientation o, bool nestingEnabled, QDockAreaLayoutInfo::TabMode tabMode)
QMainWindowLayout * qt_mainwindow_layout(const QMainWindow *window)
static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
static int realMaxSize(const QDockAreaLayoutInfo &info)
static int pick(bool vertical, const QSize &size)
static int perp(bool vertical, const QSize &size)
EGLStreamKHR stream
void qGeomCalc(QList< QLayoutStruct > &chain, int start, int count, int pos, int space, int spacer)
QT_BEGIN_NAMESPACE constexpr int QLAYOUTSIZE_MAX
Definition qlayoutitem.h:16
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
return ret
static int & rperp(Qt::Orientation o, QPoint &pos)
Definition qmenu_p.h:59
static int & rpick(Qt::Orientation o, QPoint &pos)
Definition qmenu_p.h:44
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLsizei GLuint * groups
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint left
GLint GLint bottom
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
const GLchar * marker
GLuint name
GLint first
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
static constexpr QChar sep
#define qUtf16Printable(string)
Definition qstring.h:1403
QScreen * screen
[1]
Definition main.cpp:29
#define QT_CONFIG(feature)
#define emit
#define Q_UNUSED(x)
unsigned char uchar
Definition qtypes.h:27
size_t quintptr
Definition qtypes.h:72
#define QWIDGETSIZE_MAX
Definition qwidget.h:930
QWidget * win
Definition settings.cpp:6
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFileInfo info(fileName)
[8]
QList< QWidget * > widgets
[11]
QObject::connect nullptr
QVBoxLayout * layout
QString title
[35]
QSharedPointer< T > other(t)
[5]
QGraphicsItem * item
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QDockWidget * dockWidget
[0]
QPlaceHolderItem * placeHolderItem
QDockAreaLayoutItem(QLayoutItem *_widgetItem=nullptr)
bool expansive(Qt::Orientation o) const
bool hasFixedSize(Qt::Orientation o) const
QDockAreaLayoutInfo * subinfo
QDockAreaLayoutItem & operator=(const QDockAreaLayoutItem &other)
void init(int stretchFactor=0, int minSize=0)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent