5#ifndef QMAINWINDOWLAYOUT_P_H
6#define QMAINWINDOWLAYOUT_P_H
19#include <QtWidgets/private/qtwidgetsglobal_p.h>
20#include "QtWidgets/private/qwidgetanimator_p.h"
23#include "QtWidgets/qlayout.h"
25#include "QtWidgets/qtabbar.h"
26#include "QtGui/qpainter.h"
27#include "QtGui/qevent.h"
29#include "QtCore/qbasictimer.h"
30#include "QtCore/qlist.h"
31#include "QtCore/qset.h"
32#include "private/qlayoutengine_p.h"
33#include "private/qwidgetanimator_p.h"
34#if QT_CONFIG(dockwidget)
35#include "private/qdockwidget_p.h"
37#include "qdockarealayout_p.h"
38#include "qdockwidget.h"
40struct QDockWidgetPrivate {
41 enum class DragScope {
47#include "qtoolbararealayout_p.h"
51#include <QtCore/qloggingcategory.h>
52#include <QtCore/qpointer.h>
63template <
typename Layout>
66 Layout *layout() {
return static_cast<Layout *>(
this); }
67 const Layout *layout()
const {
return static_cast<
const Layout *>(
this); }
68 QWidget *window() {
return layout()->parentWidget(); }
78#if QT_CONFIG(dockwidget)
105#if QT_CONFIG(dockwidget)
108template <
typename Layout>
109QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(
const QList<
int> &path)
111 const QDockAreaLayoutInfo *info = layout()->dockAreaLayoutInfo()->info(path);
112 Q_ASSERT(info !=
nullptr);
113 if (path.size() == 1) {
115 switch (path.first()) {
116 case QInternal::LeftDock:
117 case QInternal::RightDock:
118 return Qt::SplitHCursor;
119 case QInternal::TopDock:
120 case QInternal::BottomDock:
121 return Qt::SplitVCursor;
129 return info->o == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor;
132template <
typename Layout>
133void QMainWindowLayoutSeparatorHelper<Layout>::adjustCursor(
const QPoint &pos)
135 QWidget *w = layout()->window();
138 if (pos == QPoint(0, 0)) {
139 if (!hoverSeparator.isEmpty())
140 w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
141 hoverSeparator.clear();
143 if (cursorAdjusted) {
144 cursorAdjusted =
false;
146 w->setCursor(oldCursor);
150 }
else if (movingSeparator.isEmpty()) {
151 QList<
int> pathToSeparator = findSeparator(pos);
153 if (pathToSeparator != hoverSeparator) {
154 if (!hoverSeparator.isEmpty())
155 w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
157 hoverSeparator = pathToSeparator;
159 if (hoverSeparator.isEmpty()) {
160 if (cursorAdjusted) {
161 cursorAdjusted =
false;
163 w->setCursor(oldCursor);
168 w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
169 if (!cursorAdjusted) {
170 oldCursor = w->cursor();
171 hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
173 adjustedCursor = separatorCursor(hoverSeparator);
174 w->setCursor(adjustedCursor);
175 cursorAdjusted =
true;
182template <
typename Layout>
183bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
185 QWidget *w = window();
186 switch (event->type()) {
187 case QEvent::Paint: {
189 QRegion r =
static_cast<QPaintEvent *>(event)->region();
190 layout()->dockAreaLayoutInfo()->paintSeparators(&p, w, r, hoverPos);
195 case QEvent::HoverMove: {
196 adjustCursor(
static_cast<QHoverEvent *>(event)->position().toPoint());
202 case QEvent::HoverEnter:
204 case QEvent::HoverLeave:
205 adjustCursor(QPoint(0, 0));
207 case QEvent::ShortcutOverride:
208 adjustCursor(QPoint(0, 0));
212 case QEvent::MouseButtonPress: {
213 QMouseEvent *e =
static_cast<QMouseEvent *>(event);
214 if (e->button() == Qt::LeftButton && startSeparatorMove(e->position().toPoint())) {
222 case QEvent::MouseMove: {
223 QMouseEvent *e =
static_cast<QMouseEvent *>(event);
226 adjustCursor(e->position().toPoint());
228 if (e->buttons() & Qt::LeftButton) {
229 if (separatorMove(e->position().toPoint())) {
239 case QEvent::MouseButtonRelease: {
240 QMouseEvent *e =
static_cast<QMouseEvent *>(event);
241 if (endSeparatorMove(e->position().toPoint())) {
250 case QEvent::CursorChange:
254 if (cursorAdjusted && adjustedCursor.shape() != w->cursor().shape()) {
255 oldCursor = w->cursor();
256 hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
259 w->setCursor(adjustedCursor);
264 if (
static_cast<QTimerEvent *>(event)->timerId() == separatorMoveTimer.timerId()) {
266 separatorMoveTimer.stop();
267 if (movingSeparator.isEmpty())
269 if (movingSeparatorOrigin == movingSeparatorPos)
273 window()->update(layout()->dockAreaLayoutInfo()->separatorRegion());
275 layout()->layoutState = layout()->savedState;
276 layout()->dockAreaLayoutInfo()->separatorMove(movingSeparator, movingSeparatorOrigin,
278 movingSeparatorPos = movingSeparatorOrigin;
288template <
typename Layout>
289QList<
int> QMainWindowLayoutSeparatorHelper<Layout>::findSeparator(
const QPoint &pos)
const
291 Layout *layout =
const_cast<Layout*>(
this->layout());
292#if QT_CONFIG(toolbar)
293 QToolBarAreaLayout *toolBarAreaLayout = layout->toolBarAreaLayout();
294 if (toolBarAreaLayout && !toolBarAreaLayout->isEmpty()) {
299 const QWidget *widget = layout->window();
300 QWidget *childWidget = widget->childAt(pos);
301 while (childWidget && childWidget != widget) {
302 if (
auto *toolBar = qobject_cast<QToolBar*>(childWidget)) {
303 if (!toolBarAreaLayout->indexOf(toolBar).isEmpty())
306 childWidget = childWidget->parentWidget();
310 return layout->dockAreaLayoutInfo()->findSeparator(pos);
313template <
typename Layout>
314bool QMainWindowLayoutSeparatorHelper<Layout>::startSeparatorMove(
const QPoint &pos)
316 movingSeparator = findSeparator(pos);
318 if (movingSeparator.isEmpty())
321 layout()->savedState = layout()->layoutState;
322 movingSeparatorPos = movingSeparatorOrigin = pos;
326template <
typename Layout>
327bool QMainWindowLayoutSeparatorHelper<Layout>::separatorMove(
const QPoint &pos)
329 if (movingSeparator.isEmpty())
331 movingSeparatorPos = pos;
332 separatorMoveTimer.start(0, window());
335template <
typename Layout>
336bool QMainWindowLayoutSeparatorHelper<Layout>::endSeparatorMove(
const QPoint &)
338 if (movingSeparator.isEmpty())
340 movingSeparator.clear();
341 layout()->savedState.clear();
345class Q_AUTOTEST_EXPORT QDockWidgetGroupWindow :
public QWidget
349 explicit QDockWidgetGroupWindow(QWidget *parent =
nullptr, Qt::WindowFlags f = {})
353 QDockAreaLayoutInfo *layoutInfo()
const;
355 const QDockAreaLayoutInfo *tabLayoutInfo()
const;
356 QDockWidget *activeTabbedDockWidget()
const;
358 void destroyOrHideIfEmpty();
359 bool hasVisibleDockWidgets()
const;
361 bool hasNativeDecos()
const;
363 bool hover(QLayoutItem *widgetItem,
const QPoint &mousePos);
364 void updateCurrentGapRect();
367 void childEvent(QChildEvent *event) override;
368 void reparentToMainWindow(QDockWidget *dockWidget);
369 void destroyIfSingleItemLeft();
370 QList<QDockWidget *> dockWidgets()
const {
return findChildren<QDockWidget *>(); }
372 QRect currentGapRect;
373 QList<
int> currentGapPos;
379 bool event(QEvent *) override;
380 bool eventFilter(QObject *obj, QEvent *event) override;
381 void paintEvent(QPaintEvent*) override;
384 QSize m_removedFrameSize;
389class QDockWidgetGroupWindowItem :
public QWidgetItem
392 explicit QDockWidgetGroupWindowItem(QDockWidgetGroupWindow *parent) : QWidgetItem(parent) {}
396 QSize minimumSize()
const override
398 if (
auto dw = widget()->findChild<QDockWidget *>())
399 return dw->minimumSize();
400 return lay()->minimumSize();
402 QSize maximumSize()
const override
404 auto dw = widget()->findChild<QDockWidget *>();
406 return dw->maximumSize();
407 return lay()->maximumSize();
409 QSize sizeHint()
const override
411 auto dw = widget()->findChild<QDockWidget *>();
413 return dw->sizeHint();
414 return lay()->sizeHint();
416 QWidget* widget()
const override {
return wid; }
419 QLayout *lay()
const {
return const_cast<QDockWidgetGroupWindowItem *>(
this)->widget()->layout(); }
424
425
426
427
432 enum class StateMarkers {
433 FloatingDockWidgetTab = 0xf9,
437 ToolBarEx = Sequence,
443 QMainWindow *mainWindow;
445 QMainWindowLayoutState(QMainWindow *win);
447#if QT_CONFIG(toolbar)
448 QToolBarAreaLayout toolBarAreaLayout;
451#if QT_CONFIG(dockwidget)
452 QDockAreaLayout dockAreaLayout;
454 QLayoutItem *centralWidgetItem;
455 QRect centralWidgetRect;
458 void apply(QWidgetAnimator::AnimationRule rule);
459 void deleteAllLayoutItems();
460 void deleteCentralWidgetItem();
462 QSize sizeHint()
const;
463 QSize minimumSize()
const;
467 QLayoutItem *itemAt(
int index,
int *x)
const;
468 QLayoutItem *takeAt(
int index,
int *x);
469 QList<
int> indexOf(QWidget *widget)
const;
470 QLayoutItem *item(
const QList<
int> &path);
471 QRect itemRect(
const QList<
int> &path)
const;
472 QRect gapRect(
const QList<
int> &path)
const;
474 bool contains(QWidget *widget)
const;
476 void setCentralWidget(QWidget *widget);
477 QWidget *centralWidget()
const;
479 QList<
int> gapIndex(QWidget *widget,
const QPoint &pos)
const;
480 bool insertGap(
const QList<
int> &path, QLayoutItem *item);
481 void remove(
const QList<
int> &path);
482 void remove(QLayoutItem *item);
484 bool isValid()
const;
486 QLayoutItem *plug(
const QList<
int> &path);
487 QLayoutItem *unplug(
const QList<
int> &path, QMainWindowLayoutState *savedState =
nullptr);
489 void saveState(QDataStream &stream)
const;
490 bool checkFormat(QDataStream &stream);
491 bool restoreState(QDataStream &stream,
const QMainWindowLayoutState &oldState);
492 friend QDebug operator<<(QDebug debug, StateMarkers marker);
493 friend QDataStream &operator<<(QDataStream &stream, StateMarkers marker);
494 friend QDataStream &operator>>(QDataStream &stream, StateMarkers &marker);
497class QMainWindowTabBar;
500 public QMainWindowLayoutSeparatorHelper<QMainWindowLayout>
505 QMainWindowLayoutState layoutState, savedState;
506 std::unique_ptr<QMainWindowLayoutState> restoredState;
508 QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout);
509 ~QMainWindowLayout();
511 QMainWindow::DockOptions dockOptions;
512 void setDockOptions(QMainWindow::DockOptions opts);
514 QLayoutItem *statusbar;
517#if QT_CONFIG(statusbar)
518 QStatusBar *statusBar()
const;
519 void setStatusBar(QStatusBar *sb);
523 QWidget *centralWidget()
const;
524 void setCentralWidget(QWidget *cw);
527#if QT_CONFIG(toolbar)
528 void addToolBarBreak(Qt::ToolBarArea area);
529 void insertToolBarBreak(QToolBar *before);
530 void removeToolBarBreak(QToolBar *before);
532 void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar,
bool needAddChildWidget =
true);
533 void insertToolBar(QToolBar *before, QToolBar *toolbar);
534 Qt::ToolBarArea toolBarArea(
const QToolBar *toolbar)
const;
535 bool toolBarBreak(QToolBar *toolBar)
const;
536 void getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar)
const;
537 void removeToolBar(QToolBar *toolbar);
538 void toggleToolBarsVisible();
539 void moveToolBar(QToolBar *toolbar,
int pos);
540 QToolBarAreaLayout *toolBarAreaLayout() {
return &layoutState.toolBarAreaLayout; }
544#if QT_CONFIG(dockwidget)
545 void setCorner(Qt::Corner corner, Qt::DockWidgetArea area);
546 Qt::DockWidgetArea corner(Qt::Corner corner)
const;
547 enum DockWidgetAreaSize {Visible, Maximum};
548 QRect dockWidgetAreaRect(Qt::DockWidgetArea area, DockWidgetAreaSize size = Maximum)
const;
549 void addDockWidget(Qt::DockWidgetArea area,
550 QDockWidget *dockwidget,
551 Qt::Orientation orientation);
552 void splitDockWidget(QDockWidget *after,
553 QDockWidget *dockwidget,
554 Qt::Orientation orientation);
555 Qt::DockWidgetArea dockWidgetArea(
const QWidget* widget)
const;
556 bool restoreDockWidget(QDockWidget *dockwidget);
558 void tabifyDockWidget(QDockWidget *first, QDockWidget *second);
559 void raise(QDockWidget *widget);
560 void setVerticalTabsEnabled(
bool enabled);
562 QDockAreaLayoutInfo *dockInfo(QWidget *w);
564 bool documentMode()
const;
565 void setDocumentMode(
bool enabled);
567 QTabBar *getTabBar();
568 void unuseTabBar(QTabBar *bar);
569 QSet<QTabBar*> usedTabBars;
570 bool verticalTabsEnabled;
572 QWidget *getSeparatorWidget();
573 QSet<QWidget*> usedSeparatorWidgets;
576#if QT_CONFIG(tabwidget)
577 QTabWidget::TabPosition tabPositions[QInternal::DockCount];
578 QTabWidget::TabShape _tabShape;
580 QTabWidget::TabShape tabShape()
const;
581 void setTabShape(QTabWidget::TabShape tabShape);
582 QTabWidget::TabPosition tabPosition(Qt::DockWidgetArea area)
const;
583 void setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition);
585 QDockWidgetGroupWindow *createTabbedDockWindow();
589 QDockAreaLayout *dockAreaLayoutInfo() {
return &layoutState.dockAreaLayout; }
590 void keepSize(QDockWidget *w);
594 enum VersionMarkers {
597 void saveState(QDataStream &stream)
const;
598 bool restoreState(QDataStream &stream);
599 QBasicTimer discardRestoredStateTimer;
602 void addItem(QLayoutItem *item) override;
603 void setGeometry(
const QRect &r) override;
604 QLayoutItem *itemAt(
int index)
const override;
605 QLayoutItem *takeAt(
int index) override;
606 int count()
const override;
608 QSize sizeHint()
const override;
609 QSize minimumSize()
const override;
610 mutable QSize szHint;
611 mutable QSize minSize;
612 void invalidate() override;
615 QWidgetAnimator widgetAnimator;
616 QList<
int> currentGapPos;
617 QRect currentGapRect;
618 QWidget *pluggingWidget;
619#if QT_CONFIG(rubberband)
620 QPointer<QRubberBand> gapIndicator;
622#if QT_CONFIG(dockwidget)
623 QPointer<QDockWidgetGroupWindow> currentHoveredFloat;
624 void setCurrentHoveredFloat(QDockWidgetGroupWindow *w);
626 bool isDockWidgetTabbed(
const QDockWidget *dockWidget)
const;
627 QList<QDockWidget *> tabifiedDockWidgets(
const QDockWidget *dockWidget)
const;
628 QMainWindowTabBar *findTabBar(
const QDockWidget *dockWidget)
const;
631 bool isInApplyState =
false;
633 void hover(QLayoutItem *hoverTarget,
const QPoint &mousePos);
634 bool plug(QLayoutItem *widgetItem);
635 QLayoutItem *unplug(QWidget *widget, QDockWidgetPrivate::DragScope scope);
636 void revert(QLayoutItem *widgetItem);
637 void applyState(QMainWindowLayoutState &newState,
bool animate =
true);
638 void applyRestoredState();
639 void restore(QInternal::SaveStateRule rule);
640 void animationFinished(QWidget *widget);
642#if QT_CONFIG(draganddrop)
643 static bool needsPlatformDrag();
644 Qt::DropAction performPlatformWidgetDrag(QLayoutItem *widgetItem,
const QPoint &pressPosition);
645 QLayoutItem *draggingWidget =
nullptr;
649 void timerEvent(QTimerEvent *e) override;
652 void updateGapIndicator();
653#if QT_CONFIG(dockwidget)
656 void tabMoved(
int from,
int to);
657 void tabifyWhileFloating(QDockWidget *first, QDockWidget *second);
663 void updateTabBarShapes();
665 bool isInRestoreState =
false;
668#if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM)
670QDebug operator<<(QDebug debug,
const QDockAreaLayout &layout);
671QDebug operator<<(QDebug debug,
const QMainWindowLayout *layout);
QList< int > hoverSeparator
The QMainWindow class provides a main application window.
Combined button and popup list for selecting options.
QT_REQUIRE_CONFIG(animation)
static int grow(QLayoutStruct &ls, int delta)
static QRect dockedGeometry(QWidget *widget)
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
static int realMinSize(const QDockAreaLayoutInfo &info)
static int qMax(int i1, int i2, int i3)
static int shrink(QLayoutStruct &ls, int delta)
Q_DECLARE_FLAGS(StateFlags, StateFlag)
static int separatorMoveHelper(QList< QLayoutStruct > &list, int index, int delta, int sep)
static QInternal::DockPosition dockPosHelper(const QRect &rect, const QPoint &_pos, Qt::Orientation o, bool nestingEnabled, QDockAreaLayoutInfo::TabMode tabMode)
static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
static int realMaxSize(const QDockAreaLayoutInfo &info)
QMainWindowLayout * qt_mainwindow_layout(const QMainWindow *window)
QT_REQUIRE_CONFIG(dockwidget)
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQIORing)
QT_REQUIRE_CONFIG(mainwindow)