Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qmainwindowlayout.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
6
7#if QT_CONFIG(dockwidget)
8#include "qdockarealayout_p.h"
9#include "qdockwidget.h"
10#include "qdockwidget_p.h"
11#endif
12#if QT_CONFIG(toolbar)
13#include "qtoolbar_p.h"
14#include "qtoolbar.h"
15#include "qtoolbarlayout_p.h"
16#endif
17#include "qmainwindow.h"
18#include "qwidgetanimator_p.h"
19#if QT_CONFIG(rubberband)
20#include "qrubberband.h"
21#endif
22#if QT_CONFIG(tabbar)
23#include "qtabbar_p.h"
24#endif
25
26#include <qapplication.h>
27#if QT_CONFIG(draganddrop)
28#include <qdrag.h>
29#endif
30#include <qmimedata.h>
31#if QT_CONFIG(statusbar)
32#include <qstatusbar.h>
33#endif
34#include <qstring.h>
35#include <qstyle.h>
36#include <qstylepainter.h>
37#include <qvarlengtharray.h>
38#include <qstack.h>
39#include <qmap.h>
40#include <qtimer.h>
41#include <qpointer.h>
42
43#ifndef QT_NO_DEBUG_STREAM
44# include <qdebug.h>
45# include <qtextstream.h>
46#endif
47
48#include <private/qmenu_p.h>
49#include <private/qapplication_p.h>
50#include <private/qlayoutengine_p.h>
51#include <private/qwidgetresizehandler_p.h>
52
53#include <QScopedValueRollback>
54
56
57using namespace Qt::StringLiterals;
58
60
61/******************************************************************************
62** debug
63*/
64
65#if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM)
66
67static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent);
68
69static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QString indent)
70{
71 qout << indent << "QDockAreaLayoutItem: "
72 << "pos: " << item.pos << " size:" << item.size
74 << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) << '\n';
75 indent += " "_L1;
76 if (item.widgetItem != nullptr) {
77 qout << indent << "widget: "
78 << item.widgetItem->widget()->metaObject()->className()
79 << " \"" << item.widgetItem->widget()->windowTitle() << "\"\n";
80 } else if (item.subinfo != nullptr) {
81 qout << indent << "subinfo:\n";
82 dumpLayout(qout, *item.subinfo, indent + " "_L1);
83 } else if (item.placeHolderItem != nullptr) {
84 QRect r = item.placeHolderItem->topLevelRect;
85 qout << indent << "placeHolder: "
86 << "pos: " << item.pos << " size:" << item.size
88 << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize)
89 << " objectName:" << item.placeHolderItem->objectName
90 << " hidden:" << item.placeHolderItem->hidden
91 << " window:" << item.placeHolderItem->window
92 << " rect:" << r.x() << ',' << r.y() << ' '
93 << r.width() << 'x' << r.height() << '\n';
94 }
95}
96
97static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent)
98{
99 const QSize minSize = layout.minimumSize();
100 qout << indent << "QDockAreaLayoutInfo: "
101 << layout.rect.left() << ','
102 << layout.rect.top() << ' '
103 << layout.rect.width() << 'x'
104 << layout.rect.height()
105 << " min size: " << minSize.width() << ',' << minSize.height()
106 << " orient:" << layout.o
107#if QT_CONFIG(tabbar)
108 << " tabbed:" << layout.tabbed
109 << " tbshape:" << layout.tabBarShape
110#endif
111 << '\n';
112
113 indent += " "_L1;
114
115 for (int i = 0; i < layout.item_list.size(); ++i) {
116 qout << indent << "Item: " << i << '\n';
117 dumpLayout(qout, layout.item_list.at(i), indent + " "_L1);
118 }
119}
120
121static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout)
122{
123 qout << "QDockAreaLayout: "
124 << layout.rect.left() << ','
125 << layout.rect.top() << ' '
126 << layout.rect.width() << 'x'
127 << layout.rect.height() << '\n';
128
129 qout << "TopDockArea:\n";
130 dumpLayout(qout, layout.docks[QInternal::TopDock], " "_L1);
131 qout << "LeftDockArea:\n";
132 dumpLayout(qout, layout.docks[QInternal::LeftDock], " "_L1);
133 qout << "RightDockArea:\n";
134 dumpLayout(qout, layout.docks[QInternal::RightDock], " "_L1);
135 qout << "BottomDockArea:\n";
136 dumpLayout(qout, layout.docks[QInternal::BottomDock], " "_L1);
137}
138
140{
141 QString s;
142 QTextStream str(&s);
143 dumpLayout(str, layout);
144 debug << s;
145 return debug;
146}
147
149{
150 debug << layout->layoutState.dockAreaLayout;
151 return debug;
152}
153
154#endif // QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG)
155
156/******************************************************************************
157 ** QDockWidgetGroupWindow
158 */
159// QDockWidgetGroupWindow is the floating window containing several QDockWidgets floating together.
160// (QMainWindow::GroupedDragging feature)
161// QDockWidgetGroupLayout is the layout of that window and use a QDockAreaLayoutInfo to layout
162// the QDockWidgets inside it.
163// If there is only one QDockWidgets, or all QDockWidgets are tabbed together, it is equivalent
164// of a floating QDockWidget (the title of the QDockWidget is the title of the window). But if there
165// are nested QDockWidget, an additional title bar is there.
166#if QT_CONFIG(dockwidget)
167class QDockWidgetGroupLayout : public QLayout,
168 public QMainWindowLayoutSeparatorHelper<QDockWidgetGroupLayout>
169{
170 QWidgetResizeHandler *resizer;
171public:
172 QDockWidgetGroupLayout(QDockWidgetGroupWindow* parent) : QLayout(parent) {
174 resizer = new QWidgetResizeHandler(parent);
175 }
176 ~QDockWidgetGroupLayout() {
177 layoutState.deleteAllLayoutItems();
178 }
179
180 void addItem(QLayoutItem*) override { Q_UNREACHABLE(); }
181 int count() const override { return 0; }
182 QLayoutItem* itemAt(int index) const override
183 {
184 int x = 0;
185 return layoutState.itemAt(&x, index);
186 }
187 QLayoutItem* takeAt(int index) override
188 {
189 int x = 0;
190 QLayoutItem *ret = layoutState.takeAt(&x, index);
191 if (savedState.rect.isValid() && ret->widget()) {
192 // we need to remove the item also from the saved state to prevent crash
193 QList<int> path = savedState.indexOf(ret->widget());
194 if (!path.isEmpty())
195 savedState.remove(path);
196 // Also, the item may be contained several times as a gap item.
197 path = layoutState.indexOf(ret->widget());
198 if (!path.isEmpty())
199 layoutState.remove(path);
200 }
201 return ret;
202 }
203 QSize sizeHint() const override
204 {
205 int fw = frameWidth();
206 return layoutState.sizeHint() + QSize(fw, fw);
207 }
208 QSize minimumSize() const override
209 {
210 int fw = frameWidth();
211 return layoutState.minimumSize() + QSize(fw, fw);
212 }
213 QSize maximumSize() const override
214 {
215 int fw = frameWidth();
216 return layoutState.maximumSize() + QSize(fw, fw);
217 }
218 void setGeometry(const QRect&r) override
219 {
220 groupWindow()->destroyOrHideIfEmpty();
221 QDockAreaLayoutInfo *li = dockAreaLayoutInfo();
222 if (li->isEmpty())
223 return;
224 int fw = frameWidth();
225#if QT_CONFIG(tabbar)
226 li->reparentWidgets(parentWidget());
227#endif
228 li->rect = r.adjusted(fw, fw, -fw, -fw);
229 li->fitItems();
230 li->apply(false);
231 if (savedState.rect.isValid())
232 savedState.rect = li->rect;
233 resizer->setEnabled(!nativeWindowDeco());
234 }
235
236 QDockAreaLayoutInfo *dockAreaLayoutInfo() { return &layoutState; }
237
238 bool nativeWindowDeco() const
239 {
240 return groupWindow()->hasNativeDecos();
241 }
242
243 int frameWidth() const
244 {
245 return nativeWindowDeco() ? 0 :
247 }
248
249 QDockWidgetGroupWindow *groupWindow() const
250 {
251 return static_cast<QDockWidgetGroupWindow *>(parent());
252 }
253
254 QDockAreaLayoutInfo layoutState;
255 QDockAreaLayoutInfo savedState;
256};
257
258bool QDockWidgetGroupWindow::event(QEvent *e)
259{
260 auto lay = static_cast<QDockWidgetGroupLayout *>(layout());
261 if (lay && lay->windowEvent(e))
262 return true;
263
264 switch (e->type()) {
265 case QEvent::Close:
266#if QT_CONFIG(tabbar)
267 // Forward the close to the QDockWidget just as if its close button was pressed
268 if (QDockWidget *dw = activeTabbedDockWidget()) {
269 dw->close();
270 adjustFlags();
271 }
272#endif
273 return true;
274 case QEvent::Move:
275#if QT_CONFIG(tabbar)
276 // Let QDockWidgetPrivate::moseEvent handle the dragging
277 if (QDockWidget *dw = activeTabbedDockWidget())
278 static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->moveEvent(static_cast<QMoveEvent*>(e));
279#endif
280 return true;
285#if QT_CONFIG(tabbar)
286 // Let the QDockWidgetPrivate of the currently visible dock widget handle the drag and drop
287 if (QDockWidget *dw = activeTabbedDockWidget())
288 static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->nonClientAreaMouseEvent(static_cast<QMouseEvent*>(e));
289#endif
290 return true;
292 if (qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
293 adjustFlags();
294 break;
296 // We might need to show the widget again
297 destroyOrHideIfEmpty();
298 break;
299 case QEvent::Resize:
300 updateCurrentGapRect();
301 emit resized();
302 default:
303 break;
304 }
305 return QWidget::event(e);
306}
307
308void QDockWidgetGroupWindow::paintEvent(QPaintEvent *)
309{
310 QDockWidgetGroupLayout *lay = static_cast<QDockWidgetGroupLayout *>(layout());
311 bool nativeDeco = lay->nativeWindowDeco();
312
313 if (!nativeDeco) {
314 QStyleOptionFrame framOpt;
315 framOpt.initFrom(this);
316 QStylePainter p(this);
317 p.drawPrimitive(QStyle::PE_FrameDockWidget, framOpt);
318 }
319}
320
321QDockAreaLayoutInfo *QDockWidgetGroupWindow::layoutInfo() const
322{
323 return static_cast<QDockWidgetGroupLayout *>(layout())->dockAreaLayoutInfo();
324}
325
326#if QT_CONFIG(tabbar)
332const QDockAreaLayoutInfo *QDockWidgetGroupWindow::tabLayoutInfo() const
333{
334 const QDockAreaLayoutInfo *info = layoutInfo();
335 while (info && !info->tabbed) {
336 // There should be only one tabbed subinfo otherwise we are not a floating tab but a real
337 // window
338 const QDockAreaLayoutInfo *next = nullptr;
339 bool isSingle = false;
340 for (const auto &item : info->item_list) {
342 continue;
343 if (next || isSingle) // Two visible things
344 return nullptr;
345 if (item.subinfo)
346 next = item.subinfo;
347 else if (item.widgetItem)
348 isSingle = true;
349 }
350 if (isSingle)
351 return info;
352 info = next;
353 }
354 return info;
355}
356
360QDockWidget *QDockWidgetGroupWindow::activeTabbedDockWidget() const
361{
362 QDockWidget *dw = nullptr;
363 const QDockAreaLayoutInfo *info = tabLayoutInfo();
364 if (!info)
365 return nullptr;
366 if (info->tabBar && info->tabBar->currentIndex() >= 0) {
367 int i = info->tabIndexToListIndex(info->tabBar->currentIndex());
368 if (i >= 0) {
369 const QDockAreaLayoutItem &item = info->item_list.at(i);
370 if (item.widgetItem)
371 dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
372 }
373 }
374 if (!dw) {
375 for (int i = 0; !dw && i < info->item_list.size(); ++i) {
376 const QDockAreaLayoutItem &item = info->item_list.at(i);
377 if (item.skip())
378 continue;
379 if (!item.widgetItem)
380 continue;
381 dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
382 }
383 }
384 return dw;
385}
386#endif // QT_CONFIG(tabbar)
387
392void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
393{
394 const QDockAreaLayoutInfo *info = layoutInfo();
395 if (!info->isEmpty()) {
396 show(); // It might have been hidden,
397 return;
398 }
399 // There might still be placeholders
400 if (!info->item_list.isEmpty()) {
401 hide();
402 return;
403 }
404
405 // Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
406 const auto dockWidgets = findChildren<QDockWidget *>(Qt::FindDirectChildrenOnly);
407 for (QDockWidget *dw : dockWidgets) {
408 const bool wasFloating = dw->isFloating();
409 const bool wasHidden = dw->isHidden();
410 dw->setParent(parentWidget());
411 qCDebug(lcQpaDockWidgets) << "Reparented:" << dw << "to" << parentWidget() << "by" << this;
412 if (wasFloating) {
413 dw->setFloating(true);
414 } else {
415 // maybe it was hidden, we still have to put it back in the main layout.
417 qt_mainwindow_layout(static_cast<QMainWindow *>(parentWidget()));
418 Qt::DockWidgetArea area = ml->dockWidgetArea(this);
420 area = Qt::LeftDockWidgetArea; // FIXME: DockWidget doesn't save original docking area
421 static_cast<QMainWindow *>(parentWidget())->addDockWidget(area, dw);
422 qCDebug(lcQpaDockWidgets) << "Redocked to Mainwindow:" << area << dw << "by" << this;
423 }
424 if (!wasHidden)
425 dw->show();
426 }
427#if QT_CONFIG(tabbar)
428 const auto tabBars = findChildren<QTabBar *>(Qt::FindDirectChildrenOnly);
429 for (QTabBar *tb : tabBars)
430 tb->setParent(parentWidget());
431#endif
432 deleteLater();
433}
434
438void QDockWidgetGroupWindow::adjustFlags()
439{
440 Qt::WindowFlags oldFlags = windowFlags();
441 Qt::WindowFlags flags = oldFlags;
442
443#if QT_CONFIG(tabbar)
444 QDockWidget *top = activeTabbedDockWidget();
445#else
446 QDockWidget *top = nullptr;
447#endif
448 if (!top) { // nested tabs, show window decoration
449 flags =
450 ((oldFlags & ~Qt::FramelessWindowHint) | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
451 } else if (static_cast<QDockWidgetGroupLayout *>(layout())->nativeWindowDeco()) {
454 flags &= ~Qt::FramelessWindowHint;
455 } else {
458 }
459
460 if (oldFlags != flags) {
461 if (!windowHandle())
462 create(); // The desired geometry is forgotten if we call setWindowFlags before having a window
463 setWindowFlags(flags);
464 const bool gainedNativeDecos = (oldFlags & Qt::FramelessWindowHint) && !(flags & Qt::FramelessWindowHint);
465 const bool lostNativeDecos = !(oldFlags & Qt::FramelessWindowHint) && (flags & Qt::FramelessWindowHint);
466
467 // Adjust the geometry after gaining/losing decos, so that the client area appears always
468 // at the same place when tabbing
469 if (lostNativeDecos) {
470 QRect newGeometry = geometry();
471 newGeometry.setTop(frameGeometry().top());
472 const int bottomFrame = geometry().top() - frameGeometry().top();
473 m_removedFrameSize = QSize((frameSize() - size()).width(), bottomFrame);
474 setGeometry(newGeometry);
475 } else if (gainedNativeDecos && m_removedFrameSize.isValid()) {
476 QRect r = geometry();
477 r.adjust(-m_removedFrameSize.width() / 2, 0,
478 -m_removedFrameSize.width() / 2, -m_removedFrameSize.height());
479 setGeometry(r);
480 m_removedFrameSize = QSize();
481 }
482
483 show(); // setWindowFlags hides the window
484 }
485
486 QWidget *titleBarOf = top ? top : parentWidget();
487 setWindowTitle(titleBarOf->windowTitle());
488 setWindowIcon(titleBarOf->windowIcon());
489}
490
491bool QDockWidgetGroupWindow::hasNativeDecos() const
492{
493#if QT_CONFIG(tabbar)
494 QDockWidget *dw = activeTabbedDockWidget();
495 if (!dw) // We have a group of nested QDockWidgets (not just floating tabs)
496 return true;
497
499 return false;
500
501 return dw->titleBarWidget() == nullptr;
502#else
503 return true;
504#endif
505}
506
507/*
508 The given widget is hovered over this floating group.
509 This function will save the state and create a gap in the actual state.
510 currentGapRect and currentGapPos will be set.
511 One must call restore() or apply() after this function.
512 Returns true if there was any change in the currentGapPos
513 */
514bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
515{
516 QDockAreaLayoutInfo &savedState = static_cast<QDockWidgetGroupLayout *>(layout())->savedState;
517 if (savedState.isEmpty())
518 savedState = *layoutInfo();
519
520 QMainWindow::DockOptions opts = static_cast<QMainWindow *>(parentWidget())->dockOptions();
521 QDockAreaLayoutInfo newState = savedState;
522 bool nestingEnabled =
525#if !QT_CONFIG(tabbar)
527#else
529 if (auto group = qobject_cast<QDockWidgetGroupWindow *>(widgetItem->widget())) {
530 if (!group->tabLayoutInfo())
532 }
533 if (newState.tabbed) {
534 // insertion into a top-level tab
536 newState.item_list.first().size = pick(savedState.o, savedState.rect.size());
537 newState.tabbed = false;
538 newState.tabBar = nullptr;
539 }
540#endif
541
542 auto newGapPos = newState.gapIndex(mousePos, nestingEnabled, tabMode);
543 Q_ASSERT(!newGapPos.isEmpty());
544
545 // Do not insert a new gap item, if the current position already is a gap,
546 // or if the group window contains one
547 if (newGapPos == currentGapPos || newState.hasGapItem(newGapPos))
548 return false;
549
550 currentGapPos = newGapPos;
551 newState.insertGap(currentGapPos, widgetItem);
552 newState.fitItems();
553 *layoutInfo() = std::move(newState);
554 updateCurrentGapRect();
555 layoutInfo()->apply(opts & QMainWindow::AnimatedDocks);
556 return true;
557}
558
559void QDockWidgetGroupWindow::updateCurrentGapRect()
560{
561 if (!currentGapPos.isEmpty())
562 currentGapRect = layoutInfo()->info(currentGapPos)->itemRect(currentGapPos.last(), true);
563}
564
565/*
566 Remove the gap that was created by hover()
567 */
568void QDockWidgetGroupWindow::restore()
569{
570 QDockAreaLayoutInfo &savedState = static_cast<QDockWidgetGroupLayout *>(layout())->savedState;
571 if (!savedState.isEmpty()) {
572 *layoutInfo() = savedState;
573 savedState = QDockAreaLayoutInfo();
574 }
575 currentGapRect = QRect();
576 currentGapPos.clear();
577 adjustFlags();
578 layoutInfo()->fitItems();
579 layoutInfo()->apply(static_cast<QMainWindow *>(parentWidget())->dockOptions()
581}
582
583/*
584 Apply the state that was created by hover
585 */
586void QDockWidgetGroupWindow::apply()
587{
588 static_cast<QDockWidgetGroupLayout *>(layout())->savedState.clear();
589 currentGapRect = QRect();
590 layoutInfo()->plug(currentGapPos);
591 currentGapPos.clear();
592 adjustFlags();
593 layoutInfo()->apply(false);
594}
595
596#endif
597
598/******************************************************************************
599** QMainWindowLayoutState
600*/
601
602// we deal with all the #ifndefferry here so QMainWindowLayout code is clean
603
605 :
606#if QT_CONFIG(toolbar)
607 toolBarAreaLayout(win),
608#endif
609#if QT_CONFIG(dockwidget)
610 dockAreaLayout(win)
611#else
612 centralWidgetItem(0)
613#endif
614
615{
616 mainWindow = win;
617}
618
620{
621
622 QSize result(0, 0);
623
624#if QT_CONFIG(dockwidget)
625 result = dockAreaLayout.sizeHint();
626#else
629#endif
630
631#if QT_CONFIG(toolbar)
632 result = toolBarAreaLayout.sizeHint(result);
633#endif // QT_CONFIG(toolbar)
634
635 return result;
636}
637
639{
640 QSize result(0, 0);
641
642#if QT_CONFIG(dockwidget)
643 result = dockAreaLayout.minimumSize();
644#else
647#endif
648
649#if QT_CONFIG(toolbar)
650 result = toolBarAreaLayout.minimumSize(result);
651#endif // QT_CONFIG(toolbar)
652
653 return result;
654}
655
662{
664
665 QSize size;
666
667#if QT_CONFIG(dockwidget)
668 size = dockAreaLayout.minimumStableSize();
669#endif
670
671#if QT_CONFIG(toolbar)
672 size.rwidth() += toolBarAreaLayout.docks[QInternal::LeftDock].rect.width();
673 size.rwidth() += toolBarAreaLayout.docks[QInternal::RightDock].rect.width();
674 size.rheight() += toolBarAreaLayout.docks[QInternal::TopDock].rect.height();
675 size.rheight() += toolBarAreaLayout.docks[QInternal::BottomDock].rect.height();
676#endif
677
678 return size.width() <= mainWindow->width() && size.height() <= mainWindow->height();
679}
680
682{
683#if QT_CONFIG(toolbar)
684 toolBarAreaLayout.apply(animated);
685#endif
686
687#if QT_CONFIG(dockwidget)
688// dumpLayout(dockAreaLayout, QString());
689 dockAreaLayout.apply(animated);
690#else
691 if (centralWidgetItem) {
694 layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
695 }
696#endif
697}
698
700{
701 QRect r;
702#if !QT_CONFIG(toolbar)
703 r = rect;
704#else
705 toolBarAreaLayout.rect = rect;
706 r = toolBarAreaLayout.fitLayout();
707#endif // QT_CONFIG(toolbar)
708
709#if QT_CONFIG(dockwidget)
710 dockAreaLayout.rect = r;
711 dockAreaLayout.fitLayout();
712#else
714#endif
715}
716
718{
719#if QT_CONFIG(toolbar)
720 toolBarAreaLayout.deleteAllLayoutItems();
721#endif
722
723#if QT_CONFIG(dockwidget)
724 dockAreaLayout.deleteAllLayoutItems();
725#endif
726}
727
729{
730#if QT_CONFIG(dockwidget)
731 delete dockAreaLayout.centralWidgetItem;
732 dockAreaLayout.centralWidgetItem = nullptr;
733#else
734 delete centralWidgetItem;
736#endif
737}
738
740{
741#if QT_CONFIG(toolbar)
742 if (QLayoutItem *ret = toolBarAreaLayout.itemAt(x, index))
743 return ret;
744#endif
745
746#if QT_CONFIG(dockwidget)
747 if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index))
748 return ret;
749#else
750 if (centralWidgetItem && (*x)++ == index)
751 return centralWidgetItem;
752#endif
753
754 return nullptr;
755}
756
758{
759#if QT_CONFIG(toolbar)
760 if (QLayoutItem *ret = toolBarAreaLayout.takeAt(x, index))
761 return ret;
762#endif
763
764#if QT_CONFIG(dockwidget)
765 if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index))
766 return ret;
767#else
768 if (centralWidgetItem && (*x)++ == index) {
770 centralWidgetItem = nullptr;
771 return ret;
772 }
773#endif
774
775 return nullptr;
776}
777
779{
781
782#if QT_CONFIG(toolbar)
783 // is it a toolbar?
784 if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
785 result = toolBarAreaLayout.indexOf(toolBar);
786 if (!result.isEmpty())
787 result.prepend(0);
788 return result;
789 }
790#endif
791
792#if QT_CONFIG(dockwidget)
793 // is it a dock widget?
794 if (qobject_cast<QDockWidget *>(widget) || qobject_cast<QDockWidgetGroupWindow *>(widget)) {
795 result = dockAreaLayout.indexOf(widget);
796 if (!result.isEmpty())
797 result.prepend(1);
798 return result;
799 }
800#endif // QT_CONFIG(dockwidget)
801
802 return result;
803}
804
806{
807#if QT_CONFIG(dockwidget)
808 if (dockAreaLayout.centralWidgetItem != nullptr && dockAreaLayout.centralWidgetItem->widget() == widget)
809 return true;
810 if (!dockAreaLayout.indexOf(widget).isEmpty())
811 return true;
812#else
814 return true;
815#endif
816
817#if QT_CONFIG(toolbar)
818 if (!toolBarAreaLayout.indexOf(widget).isEmpty())
819 return true;
820#endif
821 return false;
822}
823
825{
826 QLayoutItem *item = nullptr;
827 //make sure we remove the widget
829
830 if (widget != nullptr)
832
833#if QT_CONFIG(dockwidget)
834 dockAreaLayout.centralWidgetItem = item;
835#else
837#endif
838}
839
841{
842 QLayoutItem *item = nullptr;
843
844#if QT_CONFIG(dockwidget)
845 item = dockAreaLayout.centralWidgetItem;
846#else
848#endif
849
850 if (item != nullptr)
851 return item->widget();
852 return nullptr;
853}
854
856 const QPoint &pos) const
857{
859
860#if QT_CONFIG(toolbar)
861 // is it a toolbar?
862 if (qobject_cast<QToolBar*>(widget) != nullptr) {
863 result = toolBarAreaLayout.gapIndex(pos);
864 if (!result.isEmpty())
865 result.prepend(0);
866 return result;
867 }
868#endif
869
870#if QT_CONFIG(dockwidget)
871 // is it a dock widget?
872 if (qobject_cast<QDockWidget *>(widget) != nullptr
873 || qobject_cast<QDockWidgetGroupWindow *>(widget)) {
874 bool disallowTabs = false;
875#if QT_CONFIG(tabbar)
876 if (auto *group = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
877 if (!group->tabLayoutInfo()) // Disallow to drop nested docks as a tab
878 disallowTabs = true;
879 }
880#endif
881 result = dockAreaLayout.gapIndex(pos, disallowTabs);
882 if (!result.isEmpty())
883 result.prepend(1);
884 return result;
885 }
886#endif // QT_CONFIG(dockwidget)
887
888 return result;
889}
890
892{
893 if (path.isEmpty())
894 return false;
895
896 int i = path.first();
897
898#if QT_CONFIG(toolbar)
899 if (i == 0) {
900 Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != nullptr);
901 return toolBarAreaLayout.insertGap(path.mid(1), item);
902 }
903#endif
904
905#if QT_CONFIG(dockwidget)
906 if (i == 1) {
907 Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) || qobject_cast<QDockWidgetGroupWindow*>(item->widget()));
908 return dockAreaLayout.insertGap(path.mid(1), item);
909 }
910#endif // QT_CONFIG(dockwidget)
911
912 return false;
913}
914
916{
917 int i = path.first();
918
919#if QT_CONFIG(toolbar)
920 if (i == 0)
921 toolBarAreaLayout.remove(path.mid(1));
922#endif
923
924#if QT_CONFIG(dockwidget)
925 if (i == 1)
926 dockAreaLayout.remove(path.mid(1));
927#endif // QT_CONFIG(dockwidget)
928}
929
931{
932#if QT_CONFIG(toolbar)
933 toolBarAreaLayout.remove(item);
934#endif
935
936#if QT_CONFIG(dockwidget)
937 // is it a dock widget?
938 if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(item->widget())) {
939 QList<int> path = dockAreaLayout.indexOf(dockWidget);
940 if (!path.isEmpty())
941 dockAreaLayout.remove(path);
942 }
943#endif // QT_CONFIG(dockwidget)
944}
945
947{
948#if QT_CONFIG(toolbar)
949 toolBarAreaLayout.clear();
950#endif
951
952#if QT_CONFIG(dockwidget)
953 dockAreaLayout.clear();
954#else
956#endif
957
958 rect = QRect();
959}
960
962{
963 return rect.isValid();
964}
965
967{
968 int i = path.first();
969
970#if QT_CONFIG(toolbar)
971 if (i == 0) {
972 const QToolBarAreaLayoutItem *tbItem = toolBarAreaLayout.item(path.mid(1));
973 Q_ASSERT(tbItem);
974 return tbItem->widgetItem;
975 }
976#endif
977
978#if QT_CONFIG(dockwidget)
979 if (i == 1)
980 return dockAreaLayout.item(path.mid(1)).widgetItem;
981#endif // QT_CONFIG(dockwidget)
982
983 return nullptr;
984}
985
987{
988 int i = path.first();
989
990#if QT_CONFIG(toolbar)
991 if (i == 0)
992 return toolBarAreaLayout.itemRect(path.mid(1));
993#endif
994
995#if QT_CONFIG(dockwidget)
996 if (i == 1)
997 return dockAreaLayout.itemRect(path.mid(1));
998#endif // QT_CONFIG(dockwidget)
999
1000 return QRect();
1001}
1002
1004{
1005 int i = path.first();
1006
1007#if QT_CONFIG(toolbar)
1008 if (i == 0)
1009 return toolBarAreaLayout.itemRect(path.mid(1));
1010#endif
1011
1012#if QT_CONFIG(dockwidget)
1013 if (i == 1)
1014 return dockAreaLayout.gapRect(path.mid(1));
1015#endif // QT_CONFIG(dockwidget)
1016
1017 return QRect();
1018}
1019
1021{
1022 int i = path.first();
1023
1024#if QT_CONFIG(toolbar)
1025 if (i == 0)
1026 return toolBarAreaLayout.plug(path.mid(1));
1027#endif
1028
1029#if QT_CONFIG(dockwidget)
1030 if (i == 1)
1031 return dockAreaLayout.plug(path.mid(1));
1032#endif // QT_CONFIG(dockwidget)
1033
1034 return nullptr;
1035}
1036
1038{
1039 int i = path.first();
1040
1041#if !QT_CONFIG(toolbar)
1042 Q_UNUSED(other);
1043#else
1044 if (i == 0)
1045 return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : nullptr);
1046#endif
1047
1048#if QT_CONFIG(dockwidget)
1049 if (i == 1)
1050 return dockAreaLayout.unplug(path.mid(1));
1051#endif // QT_CONFIG(dockwidget)
1052
1053 return nullptr;
1054}
1055
1057{
1058#if QT_CONFIG(dockwidget)
1059 dockAreaLayout.saveState(stream);
1060#if QT_CONFIG(tabbar)
1061 const QList<QDockWidgetGroupWindow *> floatingTabs =
1062 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
1063
1064 for (QDockWidgetGroupWindow *floating : floatingTabs) {
1065 if (floating->layoutInfo()->isEmpty())
1066 continue;
1067 stream << uchar(QDockAreaLayout::FloatingDockWidgetTabMarker) << floating->geometry();
1068 floating->layoutInfo()->saveState(stream);
1069 }
1070#endif
1071#endif
1072#if QT_CONFIG(toolbar)
1073 toolBarAreaLayout.saveState(stream);
1074#endif
1075}
1076
1077template <typename T>
1079{
1080 const QObjectList &list = o->children();
1082
1083 for (int i=0; i < list.size(); ++i) {
1084 if (T t = qobject_cast<T>(list[i])) {
1085 result.append(t);
1086 }
1087 }
1088
1089 return result;
1090}
1091
1092#if QT_CONFIG(dockwidget)
1093static QList<QDockWidget*> allMyDockWidgets(const QWidget *mainWindow)
1094{
1096 for (QObject *c : mainWindow->children()) {
1097 if (auto *dw = qobject_cast<QDockWidget*>(c)) {
1098 result.append(dw);
1099 } else if (auto *gw = qobject_cast<QDockWidgetGroupWindow*>(c)) {
1100 for (QObject *c : gw->children()) {
1101 if (auto *dw = qobject_cast<QDockWidget*>(c))
1102 result.append(dw);
1103 }
1104 }
1105 }
1106
1107 return result;
1108}
1109#endif // QT_CONFIG(dockwidget)
1110
1111//pre4.3 tests the format that was used before 4.3
1113{
1114 while (!stream.atEnd()) {
1115 uchar marker;
1116 stream >> marker;
1117 switch(marker)
1118 {
1119#if QT_CONFIG(toolbar)
1122 {
1123 QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
1124 if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, true /*testing*/)) {
1125 return false;
1126 }
1127 }
1128 break;
1129#endif // QT_CONFIG(toolbar)
1130
1131#if QT_CONFIG(dockwidget)
1133 {
1134 const auto dockWidgets = allMyDockWidgets(mainWindow);
1135 if (!dockAreaLayout.restoreState(stream, dockWidgets, true /*testing*/)) {
1136 return false;
1137 }
1138 }
1139 break;
1140#if QT_CONFIG(tabbar)
1142 {
1143 QRect geom;
1144 stream >> geom;
1146 auto dockWidgets = allMyDockWidgets(mainWindow);
1147 if (!info.restoreState(stream, dockWidgets, true /* testing*/))
1148 return false;
1149 }
1150 break;
1151#endif // QT_CONFIG(tabbar)
1152#endif // QT_CONFIG(dockwidget)
1153 default:
1154 //there was an error during the parsing
1155 return false;
1156 }// switch
1157 } //while
1158
1159 //everything went fine: it must be a pre-4.3 saved state
1160 return true;
1161}
1162
1164 const QMainWindowLayoutState &oldState)
1165{
1166 //make a copy of the data so that we can read it more than once
1168 while(!_stream.atEnd()) {
1169 int length = 1024;
1170 QByteArray ba(length, '\0');
1171 length = _stream.readRawData(ba.data(), ba.size());
1172 ba.resize(length);
1173 copy += ba;
1174 }
1175
1176 QDataStream ds(copy);
1177 ds.setVersion(_stream.version());
1178 if (!checkFormat(ds))
1179 return false;
1180
1182 stream.setVersion(_stream.version());
1183
1184 while (!stream.atEnd()) {
1185 uchar marker;
1186 stream >> marker;
1187 switch(marker)
1188 {
1189#if QT_CONFIG(dockwidget)
1191 {
1192 const auto dockWidgets = allMyDockWidgets(mainWindow);
1193 if (!dockAreaLayout.restoreState(stream, dockWidgets))
1194 return false;
1195
1196 for (int i = 0; i < dockWidgets.size(); ++i) {
1197 QDockWidget *w = dockWidgets.at(i);
1198 QList<int> path = dockAreaLayout.indexOf(w);
1199 if (path.isEmpty()) {
1200 QList<int> oldPath = oldState.dockAreaLayout.indexOf(w);
1201 if (oldPath.isEmpty()) {
1202 continue;
1203 }
1204 QDockAreaLayoutInfo *info = dockAreaLayout.info(oldPath);
1205 if (info == nullptr) {
1206 continue;
1207 }
1208 info->item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(w)));
1209 }
1210 }
1211 }
1212 break;
1213#if QT_CONFIG(tabwidget)
1215 {
1216 auto dockWidgets = allMyDockWidgets(mainWindow);
1217 QDockWidgetGroupWindow* floatingTab = qt_mainwindow_layout(mainWindow)->createTabbedDockWindow();
1218 *floatingTab->layoutInfo() = QDockAreaLayoutInfo(
1219 &dockAreaLayout.sep, QInternal::LeftDock, // FIXME: DockWidget doesn't save original docking area
1221 QRect geometry;
1222 stream >> geometry;
1223 QDockAreaLayoutInfo *info = floatingTab->layoutInfo();
1224 if (!info->restoreState(stream, dockWidgets, false))
1225 return false;
1226 geometry = QDockAreaLayout::constrainedRect(geometry, floatingTab);
1227 floatingTab->move(geometry.topLeft());
1228 floatingTab->resize(geometry.size());
1229
1230 // Don't show an empty QDockWidgetGroupWindow if no dock widget is available yet.
1231 // reparentWidgets() would be triggered by show(), so do it explicitly here.
1232 if (info->onlyHasPlaceholders())
1233 info->reparentWidgets(floatingTab);
1234 else
1235 floatingTab->show();
1236 }
1237 break;
1238#endif // QT_CONFIG(tabwidget)
1239#endif // QT_CONFIG(dockwidget)
1240
1241#if QT_CONFIG(toolbar)
1244 {
1245 QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
1246 if (!toolBarAreaLayout.restoreState(stream, toolBars, marker))
1247 return false;
1248
1249 for (int i = 0; i < toolBars.size(); ++i) {
1250 QToolBar *w = toolBars.at(i);
1251 QList<int> path = toolBarAreaLayout.indexOf(w);
1252 if (path.isEmpty()) {
1253 QList<int> oldPath = oldState.toolBarAreaLayout.indexOf(w);
1254 if (oldPath.isEmpty()) {
1255 continue;
1256 }
1257 toolBarAreaLayout.docks[oldPath.at(0)].insertToolBar(nullptr, w);
1258 }
1259 }
1260 }
1261 break;
1262#endif // QT_CONFIG(toolbar)
1263 default:
1264 return false;
1265 }// switch
1266 } //while
1267
1268
1269 return true;
1270}
1271
1272/******************************************************************************
1273** QMainWindowLayoutState - toolbars
1274*/
1275
1276#if QT_CONFIG(toolbar)
1277
1278static inline void validateToolBarArea(Qt::ToolBarArea &area)
1279{
1280 switch (area) {
1283 case Qt::TopToolBarArea:
1285 break;
1286 default:
1288 }
1289}
1290
1292{
1293 switch (area) {
1298 default:
1299 break;
1300 }
1301
1302 return QInternal::DockCount;
1303}
1304
1305static Qt::ToolBarArea toToolBarArea(QInternal::DockPosition pos)
1306{
1307 switch (pos) {
1312 default: break;
1313 }
1314 return Qt::NoToolBarArea;
1315}
1316
1317static inline Qt::ToolBarArea toToolBarArea(int pos)
1318{
1319 return toToolBarArea(static_cast<QInternal::DockPosition>(pos));
1320}
1321
1322void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area)
1323{
1324 validateToolBarArea(area);
1325
1326 layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
1327 if (savedState.isValid())
1328 savedState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
1329
1330 invalidate();
1331}
1332
1333void QMainWindowLayout::insertToolBarBreak(QToolBar *before)
1334{
1335 layoutState.toolBarAreaLayout.insertToolBarBreak(before);
1336 if (savedState.isValid())
1337 savedState.toolBarAreaLayout.insertToolBarBreak(before);
1338 invalidate();
1339}
1340
1341void QMainWindowLayout::removeToolBarBreak(QToolBar *before)
1342{
1343 layoutState.toolBarAreaLayout.removeToolBarBreak(before);
1344 if (savedState.isValid())
1345 savedState.toolBarAreaLayout.removeToolBarBreak(before);
1346 invalidate();
1347}
1348
1349void QMainWindowLayout::moveToolBar(QToolBar *toolbar, int pos)
1350{
1351 layoutState.toolBarAreaLayout.moveToolBar(toolbar, pos);
1352 if (savedState.isValid())
1353 savedState.toolBarAreaLayout.moveToolBar(toolbar, pos);
1354 invalidate();
1355}
1356
1357/* Removes the toolbar from the mainwindow so that it can be added again. Does not
1358 explicitly hide the toolbar. */
1359void QMainWindowLayout::removeToolBar(QToolBar *toolbar)
1360{
1361 if (toolbar) {
1362 QObject::disconnect(parentWidget(), SIGNAL(iconSizeChanged(QSize)),
1363 toolbar, SLOT(_q_updateIconSize(QSize)));
1364 QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
1365 toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
1366
1367 removeWidget(toolbar);
1368 }
1369}
1370
1374void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
1375 QToolBar *toolbar,
1376 bool)
1377{
1378 validateToolBarArea(area);
1379 // let's add the toolbar to the layout
1380 addChildWidget(toolbar);
1381 QLayoutItem *item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
1382 if (savedState.isValid() && item) {
1383 // copy the toolbar also in the saved state
1384 savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
1385 }
1386 invalidate();
1387
1388 // this ensures that the toolbar has the right window flags (not floating any more)
1389 toolbar->d_func()->updateWindowFlags(false /*floating*/);
1390}
1391
1395void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
1396{
1397 addChildWidget(toolbar);
1398 QLayoutItem *item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
1399 if (savedState.isValid() && item) {
1400 // copy the toolbar also in the saved state
1401 savedState.toolBarAreaLayout.insertItem(before, item);
1402 }
1403 if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) {
1404 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
1405 if (!currentGapPos.isEmpty()) {
1408 }
1409 }
1410 invalidate();
1411}
1412
1413Qt::ToolBarArea QMainWindowLayout::toolBarArea(const QToolBar *toolbar) const
1414{
1415 QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar);
1416 switch (pos) {
1421 default: break;
1422 }
1423 return Qt::NoToolBarArea;
1424}
1425
1426bool QMainWindowLayout::toolBarBreak(QToolBar *toolBar) const
1427{
1428 return layoutState.toolBarAreaLayout.toolBarBreak(toolBar);
1429}
1430
1431void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const
1432{
1433 option->toolBarArea = toolBarArea(toolBar);
1434 layoutState.toolBarAreaLayout.getStyleOptionInfo(option, toolBar);
1435}
1436
1437void QMainWindowLayout::toggleToolBarsVisible()
1438{
1439 layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
1441 QPoint topLeft = parentWidget()->geometry().topLeft();
1443 r = layoutState.toolBarAreaLayout.rectHint(r);
1444 r.moveTo(topLeft);
1446 } else {
1447 update();
1448 }
1449}
1450
1451#endif // QT_CONFIG(toolbar)
1452
1453/******************************************************************************
1454** QMainWindowLayoutState - dock areas
1455*/
1456
1457#if QT_CONFIG(dockwidget)
1458
1460{
1461 switch (area) {
1466 default:
1467 break;
1468 }
1469
1470 return QInternal::DockCount;
1471}
1472
1473inline static Qt::DockWidgetArea toDockWidgetArea(int pos)
1474{
1476}
1477
1478// Checks if QDockWidgetGroupWindow or QDockWidget can be plugged the area indicated by path.
1479// Returns false if called with invalid widget type or if compiled without dockwidget support.
1480#if QT_CONFIG(dockwidget)
1481static bool isAreaAllowed(QWidget *widget, const QList<int> &path)
1482{
1483 Q_ASSERT_X((path.size() > 1), "isAreaAllowed", "invalid path size");
1485
1486 // Read permissions directly from a single dock widget
1487 if (QDockWidget *dw = qobject_cast<QDockWidget *>(widget)) {
1488 const bool allowed = dw->isAreaAllowed(area);
1489 if (!allowed)
1490 qCDebug(lcQpaDockWidgets) << "No permission for single DockWidget" << widget << "to dock on" << area;
1491 return allowed;
1492 }
1493
1494 // Read permissions from a DockWidgetGroupWindow depending on its DockWidget children
1495 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
1496 const QList<QDockWidget *> children = dwgw->findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly);
1497
1498 if (children.size() == 1) {
1499 // Group window has a single child => read its permissions
1500 const bool allowed = children.at(0)->isAreaAllowed(area);
1501 if (!allowed)
1502 qCDebug(lcQpaDockWidgets) << "No permission for DockWidgetGroupWindow" << widget << "to dock on" << area;
1503 return allowed;
1504 } else {
1505 // Group window has more than one or no children => dock it anywhere
1506 qCDebug(lcQpaDockWidgets) << "DockWidgetGroupWindow" << widget << "has" << children.size() << "children:";
1507 qCDebug(lcQpaDockWidgets) << children;
1508 qCDebug(lcQpaDockWidgets) << "DockWidgetGroupWindow" << widget << "can dock at" << area << "and anywhere else.";
1509 return true;
1510 }
1511 }
1512 qCDebug(lcQpaDockWidgets) << "Docking requested for invalid widget type (coding error)." << widget << area;
1513 return false;
1514}
1515#endif
1516
1517void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
1518{
1519 if (layoutState.dockAreaLayout.corners[corner] == area)
1520 return;
1521 layoutState.dockAreaLayout.corners[corner] = area;
1522 if (savedState.isValid())
1523 savedState.dockAreaLayout.corners[corner] = area;
1524 invalidate();
1525}
1526
1527Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner) const
1528{
1529 return layoutState.dockAreaLayout.corners[corner];
1530}
1531
1532// Returns the rectangle of a dockWidgetArea
1533// if max is true, the maximum possible rectangle for dropping is returned
1534// the current visible rectangle otherwise
1535#if QT_CONFIG(dockwidget)
1536QRect QMainWindowLayout::dockWidgetAreaRect(const Qt::DockWidgetArea area, DockWidgetAreaSize size) const
1537{
1538 const QInternal::DockPosition dockPosition = toDockPos(area);
1539
1540 // Called with invalid dock widget area
1541 if (dockPosition == QInternal::DockCount) {
1542 qCDebug(lcQpaDockWidgets) << "QMainWindowLayout::dockWidgetAreaRect called with" << area;
1543 return QRect();
1544 }
1545
1546 const QDockAreaLayout dl = layoutState.dockAreaLayout;
1547
1548 // Return maximum or visible rectangle
1549 return (size == Maximum) ? dl.gapRect(dockPosition) : dl.docks[dockPosition].rect;
1550}
1551#endif
1552
1553void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area,
1554 QDockWidget *dockwidget,
1555 Qt::Orientation orientation)
1556{
1557 addChildWidget(dockwidget);
1558
1559 // If we are currently moving a separator, then we need to abort the move, since each
1560 // time we move the mouse layoutState is replaced by savedState modified by the move.
1561 if (!movingSeparator.isEmpty())
1562 endSeparatorMove(movingSeparatorPos);
1563
1564 layoutState.dockAreaLayout.addDockWidget(toDockPos(area), dockwidget, orientation);
1565 emit dockwidget->dockLocationChanged(area);
1566 invalidate();
1567}
1568
1569bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget)
1570{
1571 addChildWidget(dockwidget);
1572 if (!layoutState.dockAreaLayout.restoreDockWidget(dockwidget))
1573 return false;
1574 emit dockwidget->dockLocationChanged(dockWidgetArea(dockwidget));
1575 invalidate();
1576 return true;
1577}
1578
1579#if QT_CONFIG(tabbar)
1580void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
1581{
1582 addChildWidget(second);
1583 layoutState.dockAreaLayout.tabifyDockWidget(first, second);
1585 invalidate();
1586}
1587
1588bool QMainWindowLayout::documentMode() const
1589{
1590 return _documentMode;
1591}
1592
1593void QMainWindowLayout::setDocumentMode(bool enabled)
1594{
1595 if (_documentMode == enabled)
1596 return;
1597
1598 _documentMode = enabled;
1599
1600 // Update the document mode for all tab bars
1601 for (QTabBar *bar : std::as_const(usedTabBars))
1602 bar->setDocumentMode(_documentMode);
1603 for (QTabBar *bar : std::as_const(unusedTabBars))
1604 bar->setDocumentMode(_documentMode);
1605}
1606
1607void QMainWindowLayout::setVerticalTabsEnabled(bool enabled)
1608{
1609 if (verticalTabsEnabled == enabled)
1610 return;
1611
1612 verticalTabsEnabled = enabled;
1613
1614 updateTabBarShapes();
1615}
1616
1617#if QT_CONFIG(tabwidget)
1618QTabWidget::TabShape QMainWindowLayout::tabShape() const
1619{
1620 return _tabShape;
1621}
1622
1623void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape)
1624{
1625 if (_tabShape == tabShape)
1626 return;
1627
1628 _tabShape = tabShape;
1629
1630 updateTabBarShapes();
1631}
1632
1633QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const
1634{
1635 const QInternal::DockPosition dockPos = toDockPos(area);
1636 if (dockPos < QInternal::DockCount)
1637 return tabPositions[dockPos];
1638 qWarning("QMainWindowLayout::tabPosition called with out-of-bounds value '%d'", int(area));
1639 return QTabWidget::North;
1640}
1641
1642void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
1643{
1644 const Qt::DockWidgetArea dockWidgetAreas[] = {
1649 };
1650 const QInternal::DockPosition dockPositions[] = {
1655 };
1656
1657 for (int i = 0; i < QInternal::DockCount; ++i)
1658 if (areas & dockWidgetAreas[i])
1659 tabPositions[dockPositions[i]] = tabPosition;
1660
1661 updateTabBarShapes();
1662}
1663
1665#endif // QT_CONFIG(tabwidget)
1666
1667void QMainWindowLayout::updateTabBarShapes()
1668{
1669#if QT_CONFIG(tabwidget)
1670 const QTabWidget::TabPosition vertical[] = {
1675 };
1676#else
1677 const QTabBar::Shape vertical[] = {
1682 };
1683#endif
1684
1685 QDockAreaLayout &layout = layoutState.dockAreaLayout;
1686
1687 for (int i = 0; i < QInternal::DockCount; ++i) {
1688#if QT_CONFIG(tabwidget)
1689 QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i];
1690 QTabBar::Shape shape = _q_tb_tabBarShapeFrom(_tabShape, pos);
1691#else
1692 QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth;
1693#endif
1694 layout.docks[i].setTabBarShape(shape);
1695 }
1696}
1697#endif // QT_CONFIG(tabbar)
1698
1699void QMainWindowLayout::splitDockWidget(QDockWidget *after,
1700 QDockWidget *dockwidget,
1701 Qt::Orientation orientation)
1702{
1703 addChildWidget(dockwidget);
1704 layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation);
1705 emit dockwidget->dockLocationChanged(dockWidgetArea(after));
1706 invalidate();
1707}
1708
1709Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QWidget *widget) const
1710{
1711 const QList<int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget);
1712 if (pathToWidget.isEmpty())
1713 return Qt::NoDockWidgetArea;
1714 return toDockWidgetArea(pathToWidget.first());
1715}
1716
1717void QMainWindowLayout::keepSize(QDockWidget *w)
1718{
1719 layoutState.dockAreaLayout.keepSize(w);
1720}
1721
1722#if QT_CONFIG(tabbar)
1723
1724// Handle custom tooltip, and allow to drag tabs away.
1725class QMainWindowTabBar : public QTabBar
1726{
1728 QPointer<QDockWidget> draggingDock; // Currently dragging (detached) dock widget
1729public:
1730 QMainWindowTabBar(QMainWindow *parent);
1731protected:
1732 bool event(QEvent *e) override;
1733 void mouseReleaseEvent(QMouseEvent*) override;
1734 void mouseMoveEvent(QMouseEvent*) override;
1735
1736};
1737
1738QMainWindowTabBar::QMainWindowTabBar(QMainWindow *parent)
1740{
1741 setExpanding(false);
1742}
1743
1744void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
1745{
1746 // The QTabBar handles the moving (reordering) of tabs.
1747 // When QTabBarPrivate::dragInProgress is true, and that the mouse is outside of a region
1748 // around the QTabBar, we will consider the user wants to drag that QDockWidget away from this
1749 // tab area.
1750
1751 QTabBarPrivate *d = static_cast<QTabBarPrivate*>(d_ptr.data());
1752 if (!draggingDock && (mainWindow->dockOptions() & QMainWindow::GroupedDragging)) {
1754 offset *= 3;
1755 QRect r = rect().adjusted(-offset, -offset, offset, offset);
1756 if (d->dragInProgress && !r.contains(e->position().toPoint()) && d->validIndex(d->pressedIndex)) {
1757 QMainWindowLayout* mlayout = qt_mainwindow_layout(mainWindow);
1758 QDockAreaLayoutInfo *info = mlayout->dockInfo(this);
1759 Q_ASSERT(info);
1760 int idx = info->tabIndexToListIndex(d->pressedIndex);
1761 const QDockAreaLayoutItem &item = info->item_list.at(idx);
1762 if (item.widgetItem
1763 && (draggingDock = qobject_cast<QDockWidget *>(item.widgetItem->widget()))) {
1764 // We should drag this QDockWidget away by unpluging it.
1765 // First cancel the QTabBar's internal move
1766 d->moveTabFinished(d->pressedIndex);
1767 d->pressedIndex = -1;
1768 if (d->movingTab)
1769 d->movingTab->setVisible(false);
1770 d->dragStartPosition = QPoint();
1771
1772 // Then starts the drag using QDockWidgetPrivate's API
1773 QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
1774 QDockWidgetLayout *dwlayout = static_cast<QDockWidgetLayout *>(draggingDock->layout());
1775 dockPriv->initDrag(dwlayout->titleArea().center(), true);
1776 dockPriv->startDrag(false);
1777 if (dockPriv->state)
1778 dockPriv->state->ctrlDrag = e->modifiers() & Qt::ControlModifier;
1779 }
1780 }
1781 }
1782
1783 if (draggingDock) {
1784 QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
1785 if (dockPriv->state && dockPriv->state->dragging) {
1786 QPoint pos = e->globalPosition().toPoint() - dockPriv->state->pressPos;
1787 draggingDock->move(pos);
1788 // move will call QMainWindowLayout::hover
1789 }
1790 }
1792}
1793
1794void QMainWindowTabBar::mouseReleaseEvent(QMouseEvent *e)
1795{
1796 if (draggingDock && e->button() == Qt::LeftButton) {
1797 QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
1798 if (dockPriv->state && dockPriv->state->dragging) {
1799 dockPriv->endDrag();
1800 }
1801 draggingDock = nullptr;
1802 }
1804}
1805
1806bool QMainWindowTabBar::event(QEvent *e)
1807{
1808 // show the tooltip if tab is too small to fit label
1809
1810 if (e->type() != QEvent::ToolTip)
1811 return QTabBar::event(e);
1812 QSize size = this->size();
1813 QSize hint = sizeHint();
1814 if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
1815 size = size.transposed();
1816 hint = hint.transposed();
1817 }
1818 if (size.width() < hint.width())
1819 return QTabBar::event(e);
1820 e->accept();
1821 return true;
1822}
1823
1824QTabBar *QMainWindowLayout::getTabBar()
1825{
1826 if (!usedTabBars.isEmpty() && !isInRestoreState) {
1827 /*
1828 If dock widgets have been removed and added while the main window was
1829 hidden, then the layout hasn't been activated yet, and tab bars from empty
1830 docking areas haven't been put in the cache yet.
1831 */
1832 activate();
1833 }
1834
1835 QTabBar *result = nullptr;
1836 if (!unusedTabBars.isEmpty()) {
1837 result = unusedTabBars.takeLast();
1838 } else {
1839 result = new QMainWindowTabBar(static_cast<QMainWindow *>(parentWidget()));
1840 result->setDrawBase(true);
1841 result->setElideMode(Qt::ElideRight);
1842 result->setDocumentMode(_documentMode);
1843 result->setMovable(true);
1844 connect(result, SIGNAL(currentChanged(int)), this, SLOT(tabChanged()));
1845 connect(result, &QTabBar::tabMoved, this, &QMainWindowLayout::tabMoved);
1846 }
1847
1848 usedTabBars.insert(result);
1849 return result;
1850}
1851
1852// Allocates a new separator widget if needed
1853QWidget *QMainWindowLayout::getSeparatorWidget()
1854{
1855 QWidget *result = nullptr;
1856 if (!unusedSeparatorWidgets.isEmpty()) {
1857 result = unusedSeparatorWidgets.takeLast();
1858 } else {
1859 result = new QWidget(parentWidget());
1860 result->setAttribute(Qt::WA_MouseNoMask, true);
1861 result->setAutoFillBackground(false);
1862 result->setObjectName("qt_qmainwindow_extended_splitter"_L1);
1863 }
1864 usedSeparatorWidgets.insert(result);
1865 return result;
1866}
1867
1872QDockAreaLayoutInfo *QMainWindowLayout::dockInfo(QWidget *widget)
1873{
1874 QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
1875 if (info)
1876 return info;
1877 const auto groups =
1878 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
1879 for (QDockWidgetGroupWindow *dwgw : groups) {
1880 info = dwgw->layoutInfo()->info(widget);
1881 if (info)
1882 return info;
1883 }
1884 return nullptr;
1885}
1886
1887void QMainWindowLayout::tabChanged()
1888{
1889 QTabBar *tb = qobject_cast<QTabBar*>(sender());
1890 if (tb == nullptr)
1891 return;
1892 QDockAreaLayoutInfo *info = dockInfo(tb);
1893 if (info == nullptr)
1894 return;
1895
1896 QDockWidget *activated = info->apply(false);
1897
1898 if (activated)
1899 emit static_cast<QMainWindow *>(parentWidget())->tabifiedDockWidgetActivated(activated);
1900
1901 if (auto dwgw = qobject_cast<QDockWidgetGroupWindow*>(tb->parentWidget()))
1902 dwgw->adjustFlags();
1903
1904 if (QWidget *w = centralWidget())
1905 w->raise();
1906}
1907
1908void QMainWindowLayout::tabMoved(int from, int to)
1909{
1910 QTabBar *tb = qobject_cast<QTabBar*>(sender());
1911 Q_ASSERT(tb);
1912 QDockAreaLayoutInfo *info = dockInfo(tb);
1913 Q_ASSERT(info);
1914
1915 info->moveTab(from, to);
1916}
1917
1918void QMainWindowLayout::raise(QDockWidget *widget)
1919{
1920 QDockAreaLayoutInfo *info = dockInfo(widget);
1921 if (info == nullptr)
1922 return;
1923 if (!info->tabbed)
1924 return;
1925 info->setCurrentTab(widget);
1926}
1927#endif // QT_CONFIG(tabbar)
1928
1929#endif // QT_CONFIG(dockwidget)
1930
1931
1932/******************************************************************************
1933** QMainWindowLayoutState - layout interface
1934*/
1935
1937{
1938 int result = 0;
1939 while (itemAt(result))
1940 ++result;
1941 return result;
1942}
1943
1945{
1946 int x = 0;
1947
1949 return ret;
1950
1951 if (statusbar && x++ == index)
1952 return statusbar;
1953
1954 return nullptr;
1955}
1956
1958{
1959 int x = 0;
1960
1962 // the widget might in fact have been destroyed by now
1963 if (QWidget *w = ret->widget()) {
1965 if (w == pluggingWidget)
1966 pluggingWidget = nullptr;
1967 }
1968
1969 if (savedState.isValid() ) {
1970 //we need to remove the item also from the saved state to prevent crash
1972 //Also, the item may be contained several times as a gap item.
1974 }
1975
1976#if QT_CONFIG(toolbar)
1977 if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) {
1978 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
1979 if (!currentGapPos.isEmpty()) {
1982 }
1983 }
1984#endif
1985
1986 return ret;
1987 }
1988
1989 if (statusbar && x++ == index) {
1991 statusbar = nullptr;
1992 return ret;
1993 }
1994
1995 return nullptr;
1996}
1997
1999{
2000 if (savedState.isValid())
2001 return;
2002
2003 QRect r = _r;
2004
2006
2007 if (statusbar) {
2008 QRect sbr(QPoint(r.left(), 0),
2009 QSize(r.width(), statusbar->heightForWidth(r.width()))
2011 sbr.moveBottom(r.bottom());
2012 QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr);
2014 r.setBottom(sbr.top() - 1);
2015 }
2016
2017 if (restoredState) {
2018 /*
2019 The main window was hidden and was going to be maximized or full-screened when
2020 the state was restored. The state might have been for a larger window size than
2021 the current size (in _r), and the window might still be in the process of being
2022 shown and transitioning to the final size (there's no reliable way of knowing
2023 this across different platforms). Try again with the restored state.
2024 */
2026 if (restoredState->fits()) {
2027 restoredState.reset();
2029 } else {
2030 /*
2031 Try again in the next setGeometry call, but discard the restored state
2032 after 150ms without any further tries. That's a reasonably short amount of
2033 time during which we can expect the windowing system to either have completed
2034 showing the window, or resized the window once more (which then restarts the
2035 timer in timerEvent).
2036 If the windowing system is done, then the user won't have had a chance to
2037 change the layout interactively AND trigger another resize.
2038 */
2040 }
2041 }
2042
2043 layoutState.rect = r;
2044
2046 applyState(layoutState, false);
2047}
2048
2050{
2051 if (e->timerId() == discardRestoredStateTimer.timerId()) {
2053 restoredState.reset();
2054 }
2056}
2057
2059{ qWarning("QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); }
2060
2062{
2063 if (!szHint.isValid()) {
2065 const QSize sbHint = statusbar ? statusbar->sizeHint() : QSize(0, 0);
2066 szHint = QSize(qMax(sbHint.width(), szHint.width()),
2067 sbHint.height() + szHint.height());
2068 }
2069 return szHint;
2070}
2071
2073{
2074 if (!minSize.isValid()) {
2076 const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0);
2077 minSize = QSize(qMax(sbMin.width(), minSize.width()),
2078 sbMin.height() + minSize.height());
2079 }
2080 return minSize;
2081}
2082
2084{
2086 minSize = szHint = QSize();
2087}
2088
2089#if QT_CONFIG(dockwidget)
2090void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w)
2091{
2092 if (currentHoveredFloat != w) {
2093 if (currentHoveredFloat) {
2094 disconnect(currentHoveredFloat.data(), &QObject::destroyed,
2095 this, &QMainWindowLayout::updateGapIndicator);
2096 disconnect(currentHoveredFloat.data(), &QDockWidgetGroupWindow::resized,
2097 this, &QMainWindowLayout::updateGapIndicator);
2098 if (currentHoveredFloat)
2099 currentHoveredFloat->restore();
2100 } else if (w) {
2101 restore(true);
2102 }
2103
2104 currentHoveredFloat = w;
2105
2106 if (w) {
2108 this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection);
2109 connect(w, &QDockWidgetGroupWindow::resized,
2110 this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection);
2111 }
2112
2113 updateGapIndicator();
2114 }
2115}
2116#endif // QT_CONFIG(dockwidget)
2117
2118/******************************************************************************
2119** QMainWindowLayout - remaining stuff
2120*/
2121
2122static void fixToolBarOrientation(QLayoutItem *item, int dockPos)
2123{
2124#if QT_CONFIG(toolbar)
2125 QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget());
2126 if (toolBar == nullptr)
2127 return;
2128
2129 QRect oldGeo = toolBar->geometry();
2130
2132 = static_cast<QInternal::DockPosition>(dockPos);
2135 if (o != toolBar->orientation())
2136 toolBar->setOrientation(o);
2137
2138 QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize())
2139 .expandedTo(toolBar->minimumSize());
2140
2141 if (toolBar->size() != hint) {
2142 QRect newGeo(oldGeo.topLeft(), hint);
2143 if (toolBar->layoutDirection() == Qt::RightToLeft)
2144 newGeo.moveRight(oldGeo.right());
2145 toolBar->setGeometry(newGeo);
2146 }
2147
2148#else
2149 Q_UNUSED(item);
2150 Q_UNUSED(dockPos);
2151#endif
2152}
2153
2155{
2156 if (!savedState.isValid())
2157 return;
2158
2159 QWidget *widget = widgetItem->widget();
2162 if (currentGapPos.isEmpty())
2163 return;
2164 fixToolBarOrientation(widgetItem, currentGapPos.at(1));
2168
2169 plug(widgetItem);
2170}
2171
2173{
2174#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget) && QT_CONFIG(tabbar)
2175 if (currentHoveredFloat) {
2176 QWidget *widget = widgetItem->widget();
2177 QList<int> previousPath = layoutState.indexOf(widget);
2178 if (!previousPath.isEmpty())
2179 layoutState.remove(previousPath);
2180 previousPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
2181 // Let's remove the widget from any possible group window
2182 const auto groups =
2183 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
2184 for (QDockWidgetGroupWindow *dwgw : groups) {
2185 if (dwgw == currentHoveredFloat)
2186 continue;
2187 QList<int> path = dwgw->layoutInfo()->indexOf(widget);
2188 if (!path.isEmpty())
2189 dwgw->layoutInfo()->remove(path);
2190 }
2192 currentHoveredFloat->apply();
2193 if (!previousPath.isEmpty())
2194 currentHoveredFloat->layoutInfo()->remove(previousPath);
2195 QRect globalRect = currentHoveredFloat->currentGapRect;
2196 globalRect.moveTopLeft(currentHoveredFloat->mapToGlobal(globalRect.topLeft()));
2199 return true;
2200 }
2201#endif
2202
2203 if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty())
2204 return false;
2205
2206 fixToolBarOrientation(widgetItem, currentGapPos.at(1));
2207
2208 QWidget *widget = widgetItem->widget();
2209
2210#if QT_CONFIG(dockwidget)
2211 // Let's remove the widget from any possible group window
2212 const auto groups =
2213 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
2214 for (QDockWidgetGroupWindow *dwgw : groups) {
2215 QList<int> path = dwgw->layoutInfo()->indexOf(widget);
2216 if (!path.isEmpty())
2217 dwgw->layoutInfo()->remove(path);
2218 }
2219#endif
2220
2221 QList<int> previousPath = layoutState.indexOf(widget);
2222
2224 if (!it)
2225 return false;
2226 Q_ASSERT(it == widgetItem);
2227 if (!previousPath.isEmpty())
2228 layoutState.remove(previousPath);
2229
2231 QRect globalRect = currentGapRect;
2232 globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
2233#if QT_CONFIG(dockwidget)
2234 if (qobject_cast<QDockWidget*>(widget) != nullptr) {
2235 QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
2236 if (layout->nativeWindowDeco()) {
2237 globalRect.adjust(0, layout->titleHeight(), 0, 0);
2238 } else {
2240 globalRect.adjust(-fw, -fw, fw, fw);
2241 }
2242 }
2243#endif
2245
2246 return true;
2247}
2248
2250{
2251 //this function is called from within the Widget Animator whenever an animation is finished
2252 //on a certain widget
2253#if QT_CONFIG(toolbar)
2254 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
2255 QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
2256 if (tbl->animating) {
2257 tbl->animating = false;
2258 if (tbl->expanded)
2259 tbl->layoutActions(tb->size());
2260 tb->update();
2261 }
2262 }
2263#endif
2264
2265 if (widget == pluggingWidget) {
2266
2267#if QT_CONFIG(dockwidget)
2268#if QT_CONFIG(tabbar)
2269 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
2270 // When the animated widget was a QDockWidgetGroupWindow, it means each of the
2271 // embedded QDockWidget needs to be plugged back into the QMainWindow layout.
2272 savedState.clear();
2273 QDockAreaLayoutInfo *srcInfo = dwgw->layoutInfo();
2274 const QDockAreaLayoutInfo *srcTabInfo = dwgw->tabLayoutInfo();
2275 QDockAreaLayoutInfo *dstParentInfo;
2276 QList<int> dstPath;
2277
2278 if (currentHoveredFloat) {
2279 dstPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
2280 Q_ASSERT(dstPath.size() >= 1);
2281 dstParentInfo = currentHoveredFloat->layoutInfo()->info(dstPath);
2282 } else {
2283 dstPath = layoutState.dockAreaLayout.indexOf(widget);
2284 Q_ASSERT(dstPath.size() >= 2);
2285 dstParentInfo = layoutState.dockAreaLayout.info(dstPath);
2286 }
2287 Q_ASSERT(dstParentInfo);
2288 int idx = dstPath.constLast();
2289 Q_ASSERT(dstParentInfo->item_list[idx].widgetItem->widget() == dwgw);
2290 if (dstParentInfo->tabbed && srcTabInfo) {
2291 // merge the two tab widgets
2292 delete dstParentInfo->item_list[idx].widgetItem;
2293 dstParentInfo->item_list.removeAt(idx);
2294 std::copy(srcTabInfo->item_list.cbegin(), srcTabInfo->item_list.cend(),
2295 std::inserter(dstParentInfo->item_list,
2296 dstParentInfo->item_list.begin() + idx));
2297 quintptr currentId = srcTabInfo->currentTabId();
2298 *srcInfo = QDockAreaLayoutInfo();
2299 dstParentInfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data()
2300 : parentWidget());
2301 dstParentInfo->updateTabBar();
2302 dstParentInfo->setCurrentTabId(currentId);
2303 } else {
2304 QDockAreaLayoutItem &item = dstParentInfo->item_list[idx];
2305 Q_ASSERT(item.widgetItem->widget() == dwgw);
2306 delete item.widgetItem;
2307 item.widgetItem = nullptr;
2308 item.subinfo = new QDockAreaLayoutInfo(std::move(*srcInfo));
2309 *srcInfo = QDockAreaLayoutInfo();
2310 item.subinfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data()
2311 : parentWidget());
2312 item.subinfo->setTabBarShape(dstParentInfo->tabBarShape);
2313 }
2314 dwgw->destroyOrHideIfEmpty();
2315 }
2316#endif
2317
2318 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
2319 dw->setParent(currentHoveredFloat ? currentHoveredFloat.data() : parentWidget());
2320 dw->show();
2321 dw->d_func()->plug(currentGapRect);
2322 }
2323#endif
2324#if QT_CONFIG(toolbar)
2325 if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
2326 tb->d_func()->plug(currentGapRect);
2327#endif
2328
2329 savedState.clear();
2331 pluggingWidget = nullptr;
2332#if QT_CONFIG(dockwidget)
2333 setCurrentHoveredFloat(nullptr);
2334#endif
2335 //applying the state will make sure that the currentGap is updated correctly
2336 //and all the geometries (especially the one from the central widget) is correct
2337 layoutState.apply(false);
2338
2339#if QT_CONFIG(dockwidget)
2340#if QT_CONFIG(tabbar)
2341 if (qobject_cast<QDockWidget*>(widget) != nullptr) {
2342 // info() might return null if the widget is destroyed while
2343 // animating but before the animationFinished signal is received.
2344 if (QDockAreaLayoutInfo *info = dockInfo(widget))
2345 info->setCurrentTab(widget);
2346 }
2347#endif
2348#endif
2349 }
2350
2351 if (!widgetAnimator.animating()) {
2352 //all animations are finished
2353#if QT_CONFIG(dockwidget)
2354 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
2355#if QT_CONFIG(tabbar)
2356 const auto usedTabBarsCopy = usedTabBars; // list potentially modified by animations
2357 for (QTabBar *tab_bar : usedTabBarsCopy)
2358 tab_bar->show();
2359#endif // QT_CONFIG(tabbar)
2360#endif // QT_CONFIG(dockwidget)
2361 }
2362
2363 updateGapIndicator();
2364}
2365
2366void QMainWindowLayout::restore(bool keepSavedState)
2367{
2368 if (!savedState.isValid())
2369 return;
2370
2373 if (!keepSavedState)
2374 savedState.clear();
2376 pluggingWidget = nullptr;
2377 updateGapIndicator();
2378}
2379
2381 : QLayout(parentLayout ? static_cast<QWidget *>(nullptr) : mainwindow)
2382 , layoutState(mainwindow)
2383 , savedState(mainwindow)
2384 , dockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
2385 , statusbar(nullptr)
2386#if QT_CONFIG(dockwidget)
2387#if QT_CONFIG(tabbar)
2388 , _documentMode(false)
2389 , verticalTabsEnabled(false)
2390#if QT_CONFIG(tabwidget)
2391 , _tabShape(QTabWidget::Rounded)
2392#endif
2393#endif
2394#endif // QT_CONFIG(dockwidget)
2395 , widgetAnimator(this)
2396 , pluggingWidget(nullptr)
2397{
2398 if (parentLayout)
2399 setParent(parentLayout);
2400
2401#if QT_CONFIG(dockwidget)
2402#if QT_CONFIG(tabbar)
2403 sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, nullptr, mainwindow);
2404#endif
2405
2406#if QT_CONFIG(tabwidget)
2407 for (int i = 0; i < QInternal::DockCount; ++i)
2408 tabPositions[i] = QTabWidget::South;
2409#endif
2410#endif // QT_CONFIG(dockwidget)
2411 pluggingWidget = nullptr;
2412
2413 setObjectName(mainwindow->objectName() + "_layout"_L1);
2414}
2415
2417{
2420
2421 delete statusbar;
2422}
2423
2424void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts)
2425{
2426 if (opts == dockOptions)
2427 return;
2428
2429 dockOptions = opts;
2430
2431#if QT_CONFIG(dockwidget) && QT_CONFIG(tabbar)
2432 setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs);
2433#endif
2434
2435 invalidate();
2436}
2437
2438#if QT_CONFIG(statusbar)
2439QStatusBar *QMainWindowLayout::statusBar() const
2440{ return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; }
2441
2442void QMainWindowLayout::setStatusBar(QStatusBar *sb)
2443{
2444 if (sb)
2445 addChildWidget(sb);
2446 delete statusbar;
2447 statusbar = sb ? new QWidgetItemV2(sb) : nullptr;
2448 invalidate();
2449}
2450#endif // QT_CONFIG(statusbar)
2451
2453{
2454 return layoutState.centralWidget();
2455}
2456
2458{
2459 if (widget != nullptr)
2462 if (savedState.isValid()) {
2463#if QT_CONFIG(dockwidget)
2464 savedState.dockAreaLayout.centralWidgetItem = layoutState.dockAreaLayout.centralWidgetItem;
2465 savedState.dockAreaLayout.fallbackToSizeHints = true;
2466#else
2468#endif
2469 }
2470 invalidate();
2471}
2472
2473#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2481static bool unplugGroup(QMainWindowLayout *layout, QLayoutItem **item,
2482 QDockAreaLayoutItem &parentItem)
2483{
2484 if (!parentItem.subinfo || !parentItem.subinfo->tabbed)
2485 return false;
2486
2487 // The QDockWidget is part of a group of tab and we need to unplug them all.
2488 QDockWidgetGroupWindow *floatingTabs = layout->createTabbedDockWindow();
2489 QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
2490 *info = std::move(*parentItem.subinfo);
2491 delete parentItem.subinfo;
2492 parentItem.subinfo = nullptr;
2493 floatingTabs->setGeometry(info->rect.translated(layout->parentWidget()->pos()));
2494 floatingTabs->show();
2495 floatingTabs->raise();
2496 *item = new QDockWidgetGroupWindowItem(floatingTabs);
2497 parentItem.widgetItem = *item;
2498 return true;
2499}
2500#endif
2501
2502#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2503static QTabBar::Shape tabwidgetPositionToTabBarShape(QWidget *w)
2504{
2506 if (qobject_cast<QDockWidget *>(w)) {
2507 switch (static_cast<QDockWidgetPrivate *>(qt_widget_private(w))->tabPosition) {
2508 case QTabWidget::North:
2510 break;
2511 case QTabWidget::South:
2513 break;
2514 case QTabWidget::West:
2516 break;
2517 case QTabWidget::East:
2519 break;
2520 }
2521 }
2522 return result;
2523}
2524#endif // QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2525
2537{
2538#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2539 auto *groupWindow = qobject_cast<const QDockWidgetGroupWindow *>(widget->parentWidget());
2540 if (!widget->isWindow() && groupWindow) {
2541 if (group && groupWindow->tabLayoutInfo()) {
2542 // We are just dragging a floating window as it, not need to do anything, we just have to
2543 // look up the corresponding QWidgetItem* if it exists
2544 if (QDockAreaLayoutInfo *info = dockInfo(widget->parentWidget())) {
2545 QList<int> groupWindowPath = info->indexOf(widget->parentWidget());
2546 return groupWindowPath.isEmpty() ? nullptr : info->item(groupWindowPath).widgetItem;
2547 }
2548 qCDebug(lcQpaDockWidgets) << "Drag only:" << widget << "Group:" << group;
2549 return nullptr;
2550 }
2551 QList<int> path = groupWindow->layoutInfo()->indexOf(widget);
2552 QDockAreaLayoutItem parentItem = groupWindow->layoutInfo()->item(path);
2553 QLayoutItem *item = parentItem.widgetItem;
2554 if (group && path.size() > 1
2555 && unplugGroup(this, &item, parentItem)) {
2556 qCDebug(lcQpaDockWidgets) << "Unplugging:" << widget << "from" << item;
2557 return item;
2558 } else {
2559 // We are unplugging a single dock widget from a floating window.
2560 QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget);
2561 Q_ASSERT(dockWidget); // cannot be a QDockWidgetGroupWindow because it's not floating.
2562
2563 // unplug the widget first
2564 dockWidget->d_func()->unplug(widget->geometry());
2565
2566 // Create a floating tab, copy properties and generate layout info
2567 QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
2568 const QInternal::DockPosition dockPos = groupWindow->layoutInfo()->dockPos;
2569 QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
2570
2571 const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dockWidget);
2572
2573 // Populate newly created DockAreaLayoutInfo of floating tabs
2574 *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, dockPos,
2575 Qt::Horizontal, shape,
2577
2578 // Create tab and hide it as group window contains only one widget
2579 info->tabbed = true;
2580 info->tabBar = getTabBar();
2581 info->tabBar->hide();
2582 updateGapIndicator();
2583
2584 // Reparent it to a QDockWidgetGroupLayout
2585 floatingTabs->setGeometry(dockWidget->geometry());
2586
2587 // Append reference to floatingTabs to the dock's item_list
2588 parentItem.widgetItem = new QDockWidgetGroupWindowItem(floatingTabs);
2589 layoutState.dockAreaLayout.docks[dockPos].item_list.append(parentItem);
2590
2591 // use populated parentItem to set reference to dockWidget as the first item in own list
2592 parentItem.widgetItem = new QDockWidgetItem(dockWidget);
2593 info->item_list = {parentItem};
2594
2595 // Add non-gap items of the dock to the tab bar
2596 for (const auto &listItem : layoutState.dockAreaLayout.docks[dockPos].item_list) {
2597 if (listItem.GapItem || !listItem.widgetItem)
2598 continue;
2599 info->tabBar->addTab(listItem.widgetItem->widget()->objectName());
2600 }
2601
2602 // Re-parent and fit
2603 floatingTabs->setParent(layoutState.mainWindow);
2604 floatingTabs->layoutInfo()->fitItems();
2605 floatingTabs->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
2606 groupWindow->layoutInfo()->fitItems();
2607 groupWindow->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
2608 dockWidget->d_func()->tabPosition = layoutState.mainWindow->tabPosition(toDockWidgetArea(dockPos));
2609 info->reparentWidgets(floatingTabs);
2610 dockWidget->setParent(floatingTabs);
2611 info->updateTabBar();
2612
2613 // Show the new item
2614 const QList<int> path = layoutState.indexOf(floatingTabs);
2618
2619 // Update gap, fix orientation, raise and show
2621 currentGapRect = r;
2622 updateGapIndicator();
2624 floatingTabs->show();
2625 floatingTabs->raise();
2626
2627 qCDebug(lcQpaDockWidgets) << "Unplugged from floating dock:" << widget << "from" << parentItem.widgetItem;
2628 return parentItem.widgetItem;
2629 }
2630 }
2631#endif
2633 if (path.isEmpty())
2634 return nullptr;
2635
2637 if (widget->isWindow())
2638 return item;
2639
2642
2643#if QT_CONFIG(dockwidget)
2644 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
2645 Q_ASSERT(path.constFirst() == 1);
2646#if QT_CONFIG(tabwidget)
2647 if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3
2648 && unplugGroup(this, &item,
2649 layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2)))) {
2650 path.removeLast();
2652 } else
2653#endif // QT_CONFIG(tabwidget)
2654 {
2655 // Dock widget is unplugged from a main window dock
2656 // => height or width need to be decreased by separator size
2657 switch (dockWidgetArea(dw)) {
2660 r.setHeight(r.height() - sep);
2661 break;
2664 r.setWidth(r.width() - sep);
2665 break;
2668 break;
2669 }
2670
2671 // Depending on the title bar layout (vertical / horizontal),
2672 // width and height have to provide minimum space for window handles
2673 // and mouse dragging.
2674 // Assuming horizontal title bar, if the dock widget does not have a layout.
2675 const auto *layout = qobject_cast<QDockWidgetLayout *>(dw->layout());
2676 const bool verticalTitleBar = layout ? layout->verticalTitleBar : false;
2677 const int tbHeight = QApplication::style()
2679 : 20;
2680 const int minHeight = verticalTitleBar ? 2 * tbHeight : tbHeight;
2681 const int minWidth = verticalTitleBar ? tbHeight : 2 * tbHeight;
2682 r.setSize(r.size().expandedTo(QSize(minWidth, minHeight)));
2683 qCDebug(lcQpaDockWidgets) << dw << "will be unplugged with size" << r.size();
2684
2685 dw->d_func()->unplug(r);
2686 }
2687 }
2688#endif // QT_CONFIG(dockwidget)
2689#if QT_CONFIG(toolbar)
2690 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
2691 tb->d_func()->unplug(r);
2692 }
2693#endif
2694
2695#if !QT_CONFIG(dockwidget) || !QT_CONFIG(tabbar)
2696 Q_UNUSED(group);
2697#endif
2698
2702 currentGapRect = r;
2703 updateGapIndicator();
2704
2706
2707 return item;
2708}
2709
2710void QMainWindowLayout::updateGapIndicator()
2711{
2712#if QT_CONFIG(rubberband)
2714#if QT_CONFIG(dockwidget)
2715 || currentHoveredFloat
2716#endif
2717 )) {
2718 QWidget *expectedParent =
2719#if QT_CONFIG(dockwidget)
2720 currentHoveredFloat ? currentHoveredFloat.data() :
2721#endif
2722 parentWidget();
2723 if (!gapIndicator) {
2724 gapIndicator = new QRubberBand(QRubberBand::Rectangle, expectedParent);
2725 // For accessibility to identify this special widget.
2726 gapIndicator->setObjectName("qt_rubberband"_L1);
2727 } else if (gapIndicator->parent() != expectedParent) {
2728 gapIndicator->setParent(expectedParent);
2729 }
2730
2731 // Prevent re-entry in case of size change
2732 const bool sigBlockState = gapIndicator->signalsBlocked();
2733 auto resetSignals = qScopeGuard([this, sigBlockState](){ gapIndicator->blockSignals(sigBlockState); });
2734 gapIndicator->blockSignals(true);
2735
2736#if QT_CONFIG(dockwidget)
2737 if (currentHoveredFloat)
2738 gapIndicator->setGeometry(currentHoveredFloat->currentGapRect);
2739 else
2740#endif
2741 gapIndicator->setGeometry(currentGapRect);
2742
2743 gapIndicator->show();
2744 gapIndicator->raise();
2745
2746 // Reset signal state
2747
2748 } else if (gapIndicator) {
2749 gapIndicator->hide();
2750 }
2751
2752#endif // QT_CONFIG(rubberband)
2753}
2754
2756 const QPoint &mousePos) {
2757 if (!parentWidget()->isVisible() || parentWidget()->isMinimized() ||
2758 pluggingWidget != nullptr || hoverTarget == nullptr)
2759 return;
2760
2761 QWidget *widget = hoverTarget->widget();
2762
2763#if QT_CONFIG(dockwidget)
2764 if ((dockOptions & QMainWindow::GroupedDragging) && (qobject_cast<QDockWidget*>(widget)
2765 || qobject_cast<QDockWidgetGroupWindow *>(widget))) {
2766
2767 // Check if we are over another floating dock widget
2769 const auto siblings = parentWidget()->children();
2770 for (QObject *c : siblings) {
2772 if (!w)
2773 continue;
2774
2775 // Handle only dock widgets and group windows
2776 if (!qobject_cast<QDockWidget*>(w) && !qobject_cast<QDockWidgetGroupWindow *>(w))
2777 continue;
2778
2779 // Check permission to dock on another dock widget or floating dock
2780 // FIXME in 6.4
2781
2782 if (w != widget && w->isWindow() && w->isVisible() && !w->isMinimized())
2783 candidates << w;
2784
2785 if (QDockWidgetGroupWindow *group = qobject_cast<QDockWidgetGroupWindow *>(w)) {
2786 // floating QDockWidgets have a QDockWidgetGroupWindow as a parent,
2787 // if they have been hovered over
2788 const auto groupChildren = group->children();
2789 for (QObject *c : groupChildren) {
2790 if (QDockWidget *dw = qobject_cast<QDockWidget*>(c)) {
2791 if (dw != widget && dw->isFloating() && dw->isVisible() && !dw->isMinimized())
2792 candidates << dw;
2793 }
2794 }
2795 }
2796 }
2797
2798 for (QWidget *w : candidates) {
2799 const QScreen *screen1 = qt_widget_private(widget)->associatedScreen();
2800 const QScreen *screen2 = qt_widget_private(w)->associatedScreen();
2801 if (screen1 && screen2 && screen1 != screen2)
2802 continue;
2803 if (!w->geometry().contains(mousePos))
2804 continue;
2805
2806#if QT_CONFIG(tabwidget)
2807 if (auto dropTo = qobject_cast<QDockWidget *>(w)) {
2808
2809 // w is the drop target's widget
2810 w = dropTo->widget();
2811
2812 // Create a floating tab, unless already existing
2813 if (!qobject_cast<QDockWidgetGroupWindow *>(w)) {
2814 QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
2815 floatingTabs->setGeometry(dropTo->geometry());
2816 QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
2817 const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dropTo);
2818 const QInternal::DockPosition dockPosition = toDockPos(dockWidgetArea(dropTo));
2819 *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, dockPosition,
2820 Qt::Horizontal, shape,
2821 static_cast<QMainWindow *>(parentWidget()));
2822 info->tabBar = getTabBar();
2823 info->tabbed = true;
2824 QLayout *parentLayout = dropTo->parentWidget()->layout();
2825 info->item_list.append(
2826 QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo))));
2827
2828 dropTo->setParent(floatingTabs);
2829 qCDebug(lcQpaDockWidgets) << "Wrapping" << widget << "into floating tabs" << floatingTabs;
2830 w = floatingTabs;
2831 }
2832
2833 // Show the drop target and raise widget to foreground
2834 dropTo->show();
2835 qCDebug(lcQpaDockWidgets) << "Showing" << dropTo;
2836 widget->raise();
2837 qCDebug(lcQpaDockWidgets) << "Raising" << widget;
2838 }
2839#endif
2840 auto group = qobject_cast<QDockWidgetGroupWindow *>(w);
2841 Q_ASSERT(group);
2842 if (group->hover(hoverTarget, group->mapFromGlobal(mousePos))) {
2843 setCurrentHoveredFloat(group);
2844 applyState(layoutState); // update the tabbars
2845 }
2846 return;
2847 }
2848 }
2849 setCurrentHoveredFloat(nullptr);
2850 layoutState.dockAreaLayout.fallbackToSizeHints = false;
2851#endif // QT_CONFIG(dockwidget)
2852
2853 QPoint pos = parentWidget()->mapFromGlobal(mousePos);
2854
2855 if (!savedState.isValid())
2857
2859
2860 if (!path.isEmpty()) {
2861 bool allowed = false;
2862
2863#if QT_CONFIG(dockwidget)
2864 allowed = isAreaAllowed(widget, path);
2865#endif
2866#if QT_CONFIG(toolbar)
2867 if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
2868 allowed = tb->isAreaAllowed(toToolBarArea(path.at(1)));
2869#endif
2870
2871 if (!allowed)
2872 path.clear();
2873 }
2874
2875 if (path == currentGapPos)
2876 return; // the gap is already there
2877
2879 if (path.isEmpty()) {
2880 fixToolBarOrientation(hoverTarget, 2); // 2 = top dock, ie. horizontal
2881 restore(true);
2882 return;
2883 }
2884
2885 fixToolBarOrientation(hoverTarget, currentGapPos.at(1));
2886
2888
2889 if (!newState.insertGap(path, hoverTarget)) {
2890 restore(true); // not enough space
2891 return;
2892 }
2893
2894 QSize min = newState.minimumSize();
2895 QSize size = newState.rect.size();
2896
2897 if (min.width() > size.width() || min.height() > size.height()) {
2898 restore(true);
2899 return;
2900 }
2901
2902 newState.fitLayout();
2903
2905
2906#if QT_CONFIG(dockwidget)
2907 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
2908#endif
2909 layoutState = std::move(newState);
2911
2912 updateGapIndicator();
2913}
2914
2915#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2916QDockWidgetGroupWindow *QMainWindowLayout::createTabbedDockWindow()
2917{
2918 QDockWidgetGroupWindow* f = new QDockWidgetGroupWindow(parentWidget(), Qt::Tool);
2919 new QDockWidgetGroupLayout(f);
2920 return f;
2921}
2922#endif
2923
2925{
2926 // applying the state can lead to showing separator widgets, which would lead to a re-layout
2927 // (even though the separator widgets are not really part of the layout)
2928 // break the loop
2929 if (isInApplyState)
2930 return;
2931 isInApplyState = true;
2932#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2933 QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
2934 const auto groups =
2935 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
2936 for (QDockWidgetGroupWindow *dwgw : groups)
2937 used += dwgw->layoutInfo()->usedTabBars();
2938
2939 const QSet<QTabBar*> retired = usedTabBars - used;
2940 usedTabBars = used;
2941 for (QTabBar *tab_bar : retired) {
2942 tab_bar->hide();
2943 while (tab_bar->count() > 0)
2944 tab_bar->removeTab(0);
2945 unusedTabBars.append(tab_bar);
2946 }
2947
2948 if (sep == 1) {
2949 const QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
2950 const QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
2951 usedSeparatorWidgets = usedSeps;
2952 for (QWidget *sepWidget : retiredSeps) {
2953 unusedSeparatorWidgets.append(sepWidget);
2954 sepWidget->hide();
2955 }
2956 }
2957
2958 for (int i = 0; i < QInternal::DockCount; ++i)
2959 newState.dockAreaLayout.docks[i].reparentWidgets(parentWidget());
2960
2961#endif // QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2963 isInApplyState = false;
2964}
2965
2967{
2969}
2970
2972{
2973 QScopedValueRollback<bool> guard(isInRestoreState, true);
2977
2981 if (parentWidget()->isVisible())
2982 applyState(layoutState, false); // hides tabBars allocated by newState
2983 return false;
2984 }
2985
2986 if (parentWidget()->isVisible()) {
2988 applyState(layoutState, false);
2989 } else {
2990 /*
2991 The state might not fit into the size of the widget as it gets shown, but
2992 if the window is expected to be maximized or full screened, then we might
2993 get several resizes as part of that transition, at the end of which the
2994 state might fit. So keep the restored state around for now and try again
2995 later in setGeometry.
2996 */
2997 if ((parentWidget()->windowState() & (Qt::WindowFullScreen | Qt::WindowMaximized))
2998 && !layoutState.fits()) {
3000 }
3001 }
3002
3004 savedState.clear();
3005
3006#if QT_CONFIG(dockwidget)
3007 if (parentWidget()->isVisible()) {
3008#if QT_CONFIG(tabbar)
3009 for (QTabBar *tab_bar : std::as_const(usedTabBars))
3010 tab_bar->show();
3011
3012#endif
3013 }
3014#endif // QT_CONFIG(dockwidget)
3015
3016 return true;
3017}
3018
3019#if QT_CONFIG(draganddrop)
3020bool QMainWindowLayout::needsPlatformDrag()
3021{
3022 static const bool wayland =
3024 return wayland;
3025}
3026
3027Qt::DropAction QMainWindowLayout::performPlatformWidgetDrag(QLayoutItem *widgetItem,
3028 const QPoint &pressPosition)
3029{
3030 draggingWidget = widgetItem;
3031 QWidget *widget = widgetItem->widget();
3032 auto drag = QDrag(widget);
3033 auto mimeData = new QMimeData();
3034 auto window = widgetItem->widget()->windowHandle();
3035
3036 auto serialize = [](const auto &object) {
3039 dataStream << object;
3040 return data;
3041 };
3042 mimeData->setData("application/x-qt-mainwindowdrag-window"_L1,
3043 serialize(reinterpret_cast<qintptr>(window)));
3044 mimeData->setData("application/x-qt-mainwindowdrag-position"_L1, serialize(pressPosition));
3045 drag.setMimeData(mimeData);
3046
3047 auto result = drag.exec();
3048
3049 draggingWidget = nullptr;
3050 return result;
3051}
3052#endif
3053
3055
3056#include "moc_qmainwindowlayout_p.cpp"
static QStyle * style()
Returns the application's style object.
int startDragDistance
the minimum distance required for a drag and drop operation to start.
void start(int msec, QObject *obj)
\obsolete Use chrono overload instead.
int timerId() const noexcept
Returns the timer's ID.
Definition qbasictimer.h:35
void stop()
Stops the timer.
QSize minimumSize() const override
\reimp
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
\inmodule QtCore
Definition qcoreevent.h:372
\inmodule QtCore\reentrant
Definition qdatastream.h:30
int readRawData(char *, int len)
Reads at most len bytes from the stream into s and returns the number of bytes read.
bool atEnd() const
Returns true if the I/O device has reached the end position (end of the stream or file) or if there i...
int version() const
Returns the version number of the data serialization format.
void setVersion(int)
Sets the version number of the data serialization format to v, a value of the \l Version enum.
\inmodule QtCore
QDockWidget * apply(bool animate)
QList< QDockAreaLayoutItem > item_list
QDockAreaLayoutInfo * info(const QList< int > &path)
QRect gapRect(const QList< int > &path) const
static QRect constrainedRect(QRect rect, QWidget *widget)
QDockAreaLayoutInfo docks[4]
static bool wmSupportsNativeWindowDeco()
QRect titleArea() const
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
void startDrag(bool group=true)
void initDrag(const QPoint &pos, bool nca)
void endDrag(bool abort=false)
The QDockWidget class provides a widget that can be docked inside a QMainWindow or floated as a top-l...
Definition qdockwidget.h:20
bool isAreaAllowed(Qt::DockWidgetArea area) const
Returns true if this dock widget can be placed in the given area; otherwise returns false.
Definition qdockwidget.h:64
QWidget * titleBarWidget() const
bool isFloating() const
Definition qdockwidget.h:56
void dockLocationChanged(Qt::DockWidgetArea area)
void setFloating(bool floating)
\inmodule QtGui
Definition qdrag.h:22
\inmodule QtCore
Definition qcoreevent.h:45
@ NonClientAreaMouseButtonDblClick
Definition qcoreevent.h:215
@ LayoutRequest
Definition qcoreevent.h:112
@ NonClientAreaMouseMove
Definition qcoreevent.h:212
@ NonClientAreaMouseButtonRelease
Definition qcoreevent.h:214
@ NonClientAreaMouseButtonPress
Definition qcoreevent.h:213
@ ChildAdded
Definition qcoreevent.h:106
qint64 size() const
Returns the file size in bytes.
QPointF pos() const
Returns the position of the item in parent coordinates.
QGraphicsWidget * window() const
GraphicsItemFlags flags() const
Returns this item's flags.
qreal x
the x position of the item
QString platformName
The name of the underlying platform plugin.
The QLayoutItem class provides an abstract item that a QLayout manipulates.
Definition qlayoutitem.h:25
virtual QSize minimumSize() const =0
Implemented in subclasses to return the minimum size of this item.
virtual int heightForWidth(int) const
Returns the preferred height for this layout item, given the width, which is not used in this default...
virtual void setGeometry(const QRect &)=0
Implemented in subclasses to set this item's geometry to r.
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.
The QLayout class is the base class of geometry managers.
Definition qlayout.h:26
void removeWidget(QWidget *w)
Removes the widget widget from the layout.
Definition qlayout.cpp:1322
void addChildWidget(QWidget *w)
This function is called from addWidget() functions in subclasses to add w as a managed widget of a la...
Definition qlayout.cpp:836
void update()
Updates the layout for parentWidget().
Definition qlayout.cpp:970
QSize maximumSize() const override
Returns the maximum size of this layout.
Definition qlayout.cpp:926
void setSizeConstraint(SizeConstraint)
Definition qlayout.cpp:1240
bool activate()
Redoes the layout for parentWidget() if necessary.
Definition qlayout.cpp:994
virtual void addItem(QLayoutItem *)=0
Implemented in subclasses to add an item.
@ SetMinAndMaxSize
Definition qlayout.h:41
virtual QLayoutItem * itemAt(int index) const =0
Must be implemented in subclasses to return the layout item at index.
friend class QWidget
Definition qlayout.h:125
virtual QLayoutItem * takeAt(int index)=0
Must be implemented in subclasses to remove the layout item at index from the layout,...
QSize minimumSize() const override
Returns the minimum size of this layout.
Definition qlayout.cpp:911
void invalidate() override
\reimp
Definition qlayout.cpp:469
QWidget * parentWidget() const
Returns the parent widget of this layout, or \nullptr if this layout is not installed on any widget.
Definition qlayout.cpp:399
virtual int count() const =0
Must be implemented in subclasses to return the number of items in the layout.
virtual void setGeometry(const QRect &) override
\reimp
Definition qlayout.cpp:451
QLayout * layout() override
\reimp
virtual int indexOf(const QWidget *) const
Searches for widget widget in this layout (not including child layouts).
Definition qlayout.cpp:1176
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
T & first()
Definition qlist.h:628
void removeAt(qsizetype i)
Definition qlist.h:573
const T & constLast() const noexcept
Definition qlist.h:633
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void prepend(rvalue_ref t)
Definition qlist.h:456
iterator begin()
Definition qlist.h:608
const T & constFirst() const noexcept
Definition qlist.h:630
const_iterator cend() const noexcept
Definition qlist.h:614
const_iterator cbegin() const noexcept
Definition qlist.h:613
void clear()
Definition qlist.h:417
QLayoutItem * takeAt(int index, int *x)
void setCentralWidget(QWidget *widget)
bool insertGap(const QList< int > &path, QLayoutItem *item)
QList< int > indexOf(QWidget *widget) const
QRect gapRect(const QList< int > &path) const
QLayoutItem * item(const QList< int > &path)
QRect itemRect(const QList< int > &path) const
bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState)
void saveState(QDataStream &stream) const
void remove(const QList< int > &path)
QLayoutItem * itemAt(int index, int *x) const
QWidget * centralWidget() const
void apply(bool animated)
bool checkFormat(QDataStream &stream)
QMainWindowLayoutState(QMainWindow *win)
QLayoutItem * unplug(const QList< int > &path, QMainWindowLayoutState *savedState=nullptr)
QList< int > gapIndex(QWidget *widget, const QPoint &pos) const
QLayoutItem * plug(const QList< int > &path)
bool contains(QWidget *widget) const
void setCentralWidget(QWidget *cw)
void timerEvent(QTimerEvent *e) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
void hover(QLayoutItem *hoverTarget, const QPoint &mousePos)
void revert(QLayoutItem *widgetItem)
QSize sizeHint() const override
Implemented in subclasses to return the preferred size of this item.
QMainWindowLayoutState savedState
QBasicTimer discardRestoredStateTimer
QLayoutItem * unplug(QWidget *widget, bool group=false)
QLayoutItem * itemAt(int index) const override
Must be implemented in subclasses to return the layout item at index.
void setDockOptions(QMainWindow::DockOptions opts)
void invalidate() override
\reimp
void restore(bool keepSavedState=false)
void addItem(QLayoutItem *item) override
Implemented in subclasses to add an item.
QSize minimumSize() const override
Returns the minimum size of this layout.
QWidget * centralWidget() const
QWidgetAnimator widgetAnimator
bool plug(QLayoutItem *widgetItem)
QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout)
int count() const override
Must be implemented in subclasses to return the number of items in the layout.
std::unique_ptr< QMainWindowLayoutState > restoredState
void saveState(QDataStream &stream) const
QMainWindow::DockOptions dockOptions
void setGeometry(const QRect &r) override
\reimp
QLayoutItem * takeAt(int index) override
Must be implemented in subclasses to remove the layout item at index from the layout,...
void applyState(QMainWindowLayoutState &newState, bool animate=true)
bool restoreState(QDataStream &stream)
QMainWindowLayoutState layoutState
void animationFinished(QWidget *widget)
The QMainWindow class provides a main application window.
Definition qmainwindow.h:25
\inmodule QtCore
Definition qmimedata.h:16
void setData(const QString &mimetype, const QByteArray &data)
Sets the data associated with the MIME type given by mimeType to the specified data.
\inmodule QtGui
Definition qevent.h:195
The QMoveEvent class contains event parameters for move events.
Definition qevent.h:501
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:153
\inmodule QtCore
Definition qobject.h:90
const QObjectList & children() const
Returns a list of child objects.
Definition qobject.h:171
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2521
QString objectName
the name of this object
Definition qobject.h:94
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
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
virtual void timerEvent(QTimerEvent *event)
This event handler can be reimplemented in a subclass to receive timer events for the object.
Definition qobject.cpp:1433
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:114
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore
Definition qpointer.h:18
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void moveTopLeft(const QPoint &p) noexcept
Moves the rectangle, leaving the top-left corner at the given position.
Definition qrect.h:303
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 bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:169
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 QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:241
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:232
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 QRubberBand class provides a rectangle or line that can indicate a selection or a boundary.
Definition qrubberband.h:18
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
Definition qset.h:18
\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 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 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
The QStatusBar class provides a horizontal bar suitable for presenting status information.
Definition qstatusbar.h:17
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
\variable QStyleOptionFocusRect::backgroundColor
void initFrom(const QWidget *w)
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
static QRect visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect)
Returns the given logicalRectangle converted to screen coordinates based on the specified direction.
Definition qstyle.cpp:2144
@ PM_DockWidgetFrameWidth
Definition qstyle.h:437
@ PM_TitleBarHeight
Definition qstyle.h:448
@ PM_DockWidgetSeparatorExtent
Definition qstyle.h:435
@ PE_FrameDockWidget
Definition qstyle.h:105
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
bool event(QEvent *) override
\reimp
Definition qtabbar.cpp:1666
void mouseReleaseEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2306
void mouseMoveEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2154
void tabMoved(int from, int to)
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
@ RoundedWest
Definition qtabbar.h:42
@ RoundedEast
Definition qtabbar.h:42
The QTabWidget class provides a stack of tabbed widgets.
Definition qtabwidget.h:20
TabPosition
This enum type defines where QTabWidget draws the tab row:
Definition qtabwidget.h:74
TabShape
This enum type defines the shape of the tabs: \value Rounded The tabs are drawn with a rounded look.
Definition qtabwidget.h:85
\inmodule QtCore
\inmodule QtCore
Definition qcoreevent.h:359
bool layoutActions(const QSize &size)
The QToolBar class provides a movable panel that contains a set of controls.
Definition qtoolbar.h:23
Qt::Orientation orientation
orientation of the toolbar
Definition qtoolbar.h:30
void setOrientation(Qt::Orientation orientation)
Definition qtoolbar.cpp:633
void animate(QWidget *widget, const QRect &final_geometry, bool animate)
void abort(QWidget *widget)
bool animating() const
QScreen * associatedScreen() const
Definition qwidget.cpp:1063
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.
Qt::LayoutDirection layoutDirection
the layout direction for this widget.
Definition qwidget.h:170
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
bool isMinimized() const
Definition qwidget.cpp:2843
bool isHidden() const
Returns true if the widget is hidden, otherwise returns false.
Definition qwidget.h:877
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
QSize minimumSize
the widget's minimum size
Definition qwidget.h:120
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
QSize maximumSize
the widget's maximum size in pixels
Definition qwidget.h:121
QPoint pos
the position of the widget within its parent widget
Definition qwidget.h:111
bool isMaximized() const
Definition qwidget.cpp:2883
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7956
QIcon windowIcon
the widget's icon
Definition qwidget.h:152
void update()
Updates the widget unless updates are disabled or the widget is hidden.
QWindow * windowHandle() const
If this is a native widget, return the associated QWindow.
Definition qwidget.cpp:2490
QSize sizeHint
the recommended size for the widget
Definition qwidget.h:148
bool event(QEvent *event) override
This is the main event handler; it handles event event.
Definition qwidget.cpp:8912
QStyle * style() const
Definition qwidget.cpp:2607
QString windowTitle
the window title (caption)
Definition qwidget.h:151
QWidget * parentWidget() const
Returns the parent of this widget, or \nullptr if it does not have any parent widget.
Definition qwidget.h:904
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition qwidget.h:811
bool isVisible() const
Definition qwidget.h:874
QPointF mapFromGlobal(const QPointF &) const
Translates the global screen coordinate pos to widget coordinates.
#define this
Definition dialogs.cpp:9
QOpenGLWidget * widget
[1]
QString str
[2]
double e
QSet< QString >::iterator it
rect
[4]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
short next
Definition keywords.cpp:445
QTextStream & qout()
Definition lalr.cpp:26
Combined button and popup list for selecting options.
@ WindowFullScreen
Definition qnamespace.h:254
@ WindowMaximized
Definition qnamespace.h:253
DockWidgetArea
@ BottomDockWidgetArea
@ DockWidgetArea_Mask
@ NoDockWidgetArea
@ RightDockWidgetArea
@ LeftDockWidgetArea
@ TopDockWidgetArea
@ LeftButton
Definition qnamespace.h:57
@ WA_MouseNoMask
Definition qnamespace.h:337
ToolBarArea
@ LeftToolBarArea
@ BottomToolBarArea
@ TopToolBarArea
@ NoToolBarArea
@ RightToolBarArea
@ RightToLeft
Orientation
Definition qnamespace.h:97
@ Horizontal
Definition qnamespace.h:98
@ Vertical
Definition qnamespace.h:99
@ FindDirectChildrenOnly
@ ControlModifier
@ CaseInsensitive
DropAction
@ UniqueConnection
@ CustomizeWindowHint
Definition qnamespace.h:238
@ FramelessWindowHint
Definition qnamespace.h:224
@ Tool
Definition qnamespace.h:211
@ WindowTitleHint
Definition qnamespace.h:225
@ WindowCloseButtonHint
Definition qnamespace.h:240
@ ElideRight
Definition qnamespace.h:189
ToolButtonStyle
const char * dockWidgetArea(int v)
Definition language.cpp:138
static jboolean copy(JNIEnv *, jobject)
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
QMainWindowLayout * qt_mainwindow_layout(const QMainWindow *window)
static int pick(bool vertical, const QSize &size)
EGLStreamKHR stream
static int area(const QSize &s)
Definition qicon.cpp:152
#define qWarning
Definition qlogging.h:162
#define qCDebug(category,...)
return ret
static void fixToolBarOrientation(QLayoutItem *item, int dockPos)
QMainWindowLayout * qt_mainwindow_layout(const QMainWindow *window)
static QList< T > findChildrenHelper(const QObject *o)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLint GLint GLint GLint GLint x
[0]
GLsizei GLuint * groups
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLuint object
[3]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLint GLsizei width
GLboolean GLuint group
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
const GLchar * marker
GLint first
struct _cl_event * event
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLuint GLenum option
static constexpr QSize frameSize(const T &frame)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
static constexpr QChar sep
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
QTabBar::Shape _q_tb_tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
#define QT_CONFIG(feature)
#define emit
#define Q_UNUSED(x)
unsigned char uchar
Definition qtypes.h:27
size_t quintptr
Definition qtypes.h:72
ptrdiff_t qintptr
Definition qtypes.h:71
Q_WIDGETS_EXPORT QWidgetPrivate * qt_widget_private(QWidget *widget)
QWidget * qobject_cast< QWidget * >(QObject *o)
Definition qwidget.h:786
#define enabled
static QRect frameGeometry(HWND hwnd, bool topLevel)
QWidget * win
Definition settings.cpp:6
view show()
[18] //! [19]
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QByteArray ba
[0]
QFileInfo info(fileName)
[8]
QDataStream & operator<<(QDataStream &out, const MyClass &myObj)
[4]
QMimeData * mimeData
QObject::connect nullptr
QVBoxLayout * layout
myObject disconnect()
[26]
QSharedPointer< T > other(t)
[5]
QGraphicsItem * item
edit hide()
edit isVisible()
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QDockWidget * dockWidget
[0]
file setParent(multiPart)
view create()
QDockAreaLayoutInfo * subinfo
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:955
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent