1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QDYNAMICMAINWINDOWLAYOUT_P_H |
5 | #define QDYNAMICMAINWINDOWLAYOUT_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtWidgets/private/qtwidgetsglobal_p.h> |
19 | #include "qmainwindow.h" |
20 | |
21 | #include "QtWidgets/qlayout.h" |
22 | #if QT_CONFIG(tabbar) |
23 | #include "QtWidgets/qtabbar.h" |
24 | #include "QtGui/qpainter.h" |
25 | #include "QtGui/qevent.h" |
26 | #endif |
27 | #include "QtCore/qbasictimer.h" |
28 | #include "QtCore/qlist.h" |
29 | #include "QtCore/qset.h" |
30 | #include "private/qlayoutengine_p.h" |
31 | #include "private/qwidgetanimator_p.h" |
32 | |
33 | #if QT_CONFIG(dockwidget) |
34 | #include "qdockarealayout_p.h" |
35 | #include "qdockwidget.h" |
36 | #endif |
37 | #if QT_CONFIG(toolbar) |
38 | #include "qtoolbararealayout_p.h" |
39 | #endif |
40 | #include <QtCore/qloggingcategory.h> |
41 | |
42 | QT_REQUIRE_CONFIG(mainwindow); |
43 | |
44 | QT_BEGIN_NAMESPACE |
45 | |
46 | Q_DECLARE_LOGGING_CATEGORY(lcQpaDockWidgets); |
47 | |
48 | class QToolBar; |
49 | class QRubberBand; |
50 | |
51 | template <typename Layout> // Make use of the "Curiously recurring template pattern" |
52 | class QMainWindowLayoutSeparatorHelper |
53 | { |
54 | Layout *layout() { return static_cast<Layout *>(this); } |
55 | const Layout *layout() const { return static_cast<const Layout *>(this); } |
56 | QWidget *window() { return layout()->parentWidget(); } |
57 | |
58 | public: |
59 | Q_DISABLE_COPY_MOVE(QMainWindowLayoutSeparatorHelper) |
60 | |
61 | QMainWindowLayoutSeparatorHelper() = default; |
62 | |
63 | QList<int> hoverSeparator; |
64 | QPoint hoverPos; |
65 | |
66 | #if QT_CONFIG(dockwidget) |
67 | |
68 | #if QT_CONFIG(cursor) |
69 | QCursor separatorCursor(const QList<int> &path); |
70 | void adjustCursor(const QPoint &pos); |
71 | QCursor oldCursor; |
72 | QCursor adjustedCursor; |
73 | bool hasOldCursor = false; |
74 | bool cursorAdjusted = false; |
75 | #endif // QT_CONFIG(cursor) |
76 | |
77 | QList<int> movingSeparator; |
78 | QPoint movingSeparatorOrigin, movingSeparatorPos; |
79 | QBasicTimer separatorMoveTimer; |
80 | |
81 | bool startSeparatorMove(const QPoint &pos); |
82 | bool separatorMove(const QPoint &pos); |
83 | bool endSeparatorMove(const QPoint &pos); |
84 | bool windowEvent(QEvent *e); |
85 | |
86 | #endif // QT_CONFIG(dockwidget) |
87 | |
88 | }; |
89 | |
90 | #if QT_CONFIG(dockwidget) |
91 | |
92 | #if QT_CONFIG(cursor) |
93 | template <typename Layout> |
94 | QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(const QList<int> &path) |
95 | { |
96 | const QDockAreaLayoutInfo *info = layout()->dockAreaLayoutInfo()->info(path); |
97 | Q_ASSERT(info != nullptr); |
98 | if (path.size() == 1) { // is this the "top-level" separator which separates a dock area |
99 | // from the central widget? |
100 | switch (path.first()) { |
101 | case QInternal::LeftDock: |
102 | case QInternal::RightDock: |
103 | return Qt::SplitHCursor; |
104 | case QInternal::TopDock: |
105 | case QInternal::BottomDock: |
106 | return Qt::SplitVCursor; |
107 | default: |
108 | break; |
109 | } |
110 | } |
111 | |
112 | // no, it's a splitter inside a dock area, separating two dock widgets |
113 | |
114 | return info->o == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor; |
115 | } |
116 | |
117 | template <typename Layout> |
118 | void QMainWindowLayoutSeparatorHelper<Layout>::adjustCursor(const QPoint &pos) |
119 | { |
120 | QWidget *w = layout()->window(); |
121 | hoverPos = pos; |
122 | |
123 | if (pos == QPoint(0, 0)) { |
124 | if (!hoverSeparator.isEmpty()) |
125 | w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator)); |
126 | hoverSeparator.clear(); |
127 | |
128 | if (cursorAdjusted) { |
129 | cursorAdjusted = false; |
130 | if (hasOldCursor) |
131 | w->setCursor(oldCursor); |
132 | else |
133 | w->unsetCursor(); |
134 | } |
135 | } else if (movingSeparator.isEmpty()) { // Don't change cursor when moving separator |
136 | QList<int> pathToSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos); |
137 | |
138 | if (pathToSeparator != hoverSeparator) { |
139 | if (!hoverSeparator.isEmpty()) |
140 | w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator)); |
141 | |
142 | hoverSeparator = pathToSeparator; |
143 | |
144 | if (hoverSeparator.isEmpty()) { |
145 | if (cursorAdjusted) { |
146 | cursorAdjusted = false; |
147 | if (hasOldCursor) |
148 | w->setCursor(oldCursor); |
149 | else |
150 | w->unsetCursor(); |
151 | } |
152 | } else { |
153 | w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator)); |
154 | if (!cursorAdjusted) { |
155 | oldCursor = w->cursor(); |
156 | hasOldCursor = w->testAttribute(attribute: Qt::WA_SetCursor); |
157 | } |
158 | adjustedCursor = separatorCursor(path: hoverSeparator); |
159 | w->setCursor(adjustedCursor); |
160 | cursorAdjusted = true; |
161 | } |
162 | } |
163 | } |
164 | } |
165 | #endif // QT_CONFIG(cursor) |
166 | |
167 | template <typename Layout> |
168 | bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event) |
169 | { |
170 | QWidget *w = window(); |
171 | switch (event->type()) { |
172 | case QEvent::Paint: { |
173 | QPainter p(w); |
174 | QRegion r = static_cast<QPaintEvent *>(event)->region(); |
175 | layout()->dockAreaLayoutInfo()->paintSeparators(&p, w, r, hoverPos); |
176 | break; |
177 | } |
178 | |
179 | #if QT_CONFIG(cursor) |
180 | case QEvent::HoverMove: { |
181 | adjustCursor(pos: static_cast<QHoverEvent *>(event)->position().toPoint()); |
182 | break; |
183 | } |
184 | |
185 | // We don't want QWidget to call update() on the entire QMainWindow |
186 | // on HoverEnter and HoverLeave, hence accept the event (return true). |
187 | case QEvent::HoverEnter: |
188 | return true; |
189 | case QEvent::HoverLeave: |
190 | adjustCursor(pos: QPoint(0, 0)); |
191 | return true; |
192 | case QEvent::ShortcutOverride: // when a menu pops up |
193 | adjustCursor(pos: QPoint(0, 0)); |
194 | break; |
195 | #endif // QT_CONFIG(cursor) |
196 | |
197 | case QEvent::MouseButtonPress: { |
198 | QMouseEvent *e = static_cast<QMouseEvent *>(event); |
199 | if (e->button() == Qt::LeftButton && startSeparatorMove(pos: e->position().toPoint())) { |
200 | // The click was on a separator, eat this event |
201 | e->accept(); |
202 | return true; |
203 | } |
204 | break; |
205 | } |
206 | |
207 | case QEvent::MouseMove: { |
208 | QMouseEvent *e = static_cast<QMouseEvent *>(event); |
209 | |
210 | #if QT_CONFIG(cursor) |
211 | adjustCursor(pos: e->position().toPoint()); |
212 | #endif |
213 | if (e->buttons() & Qt::LeftButton) { |
214 | if (separatorMove(pos: e->position().toPoint())) { |
215 | // We're moving a separator, eat this event |
216 | e->accept(); |
217 | return true; |
218 | } |
219 | } |
220 | |
221 | break; |
222 | } |
223 | |
224 | case QEvent::MouseButtonRelease: { |
225 | QMouseEvent *e = static_cast<QMouseEvent *>(event); |
226 | if (endSeparatorMove(pos: e->position().toPoint())) { |
227 | // We've released a separator, eat this event |
228 | e->accept(); |
229 | return true; |
230 | } |
231 | break; |
232 | } |
233 | |
234 | #if QT_CONFIG(cursor) |
235 | case QEvent::CursorChange: |
236 | // CursorChange events are triggered as mouse moves to new widgets even |
237 | // if the cursor doesn't actually change, so do not change oldCursor if |
238 | // the "changed" cursor has same shape as adjusted cursor. |
239 | if (cursorAdjusted && adjustedCursor.shape() != w->cursor().shape()) { |
240 | oldCursor = w->cursor(); |
241 | hasOldCursor = w->testAttribute(attribute: Qt::WA_SetCursor); |
242 | |
243 | // Ensure our adjusted cursor stays visible |
244 | w->setCursor(adjustedCursor); |
245 | } |
246 | break; |
247 | #endif // QT_CONFIG(cursor) |
248 | case QEvent::Timer: |
249 | if (static_cast<QTimerEvent *>(event)->timerId() == separatorMoveTimer.timerId()) { |
250 | // let's move the separators |
251 | separatorMoveTimer.stop(); |
252 | if (movingSeparator.isEmpty()) |
253 | return true; |
254 | if (movingSeparatorOrigin == movingSeparatorPos) |
255 | return true; |
256 | |
257 | // when moving the separator, we need to update the previous position |
258 | window()->update(layout()->dockAreaLayoutInfo()->separatorRegion()); |
259 | |
260 | layout()->layoutState = layout()->savedState; |
261 | layout()->dockAreaLayoutInfo()->separatorMove(movingSeparator, movingSeparatorOrigin, |
262 | movingSeparatorPos); |
263 | movingSeparatorPos = movingSeparatorOrigin; |
264 | return true; |
265 | } |
266 | break; |
267 | default: |
268 | break; |
269 | } |
270 | return false; |
271 | } |
272 | |
273 | template <typename Layout> |
274 | bool QMainWindowLayoutSeparatorHelper<Layout>::startSeparatorMove(const QPoint &pos) |
275 | { |
276 | movingSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos); |
277 | |
278 | if (movingSeparator.isEmpty()) |
279 | return false; |
280 | |
281 | layout()->savedState = layout()->layoutState; |
282 | movingSeparatorPos = movingSeparatorOrigin = pos; |
283 | |
284 | return true; |
285 | } |
286 | template <typename Layout> |
287 | bool QMainWindowLayoutSeparatorHelper<Layout>::separatorMove(const QPoint &pos) |
288 | { |
289 | if (movingSeparator.isEmpty()) |
290 | return false; |
291 | movingSeparatorPos = pos; |
292 | separatorMoveTimer.start(0, window()); |
293 | return true; |
294 | } |
295 | template <typename Layout> |
296 | bool QMainWindowLayoutSeparatorHelper<Layout>::endSeparatorMove(const QPoint &) |
297 | { |
298 | if (movingSeparator.isEmpty()) |
299 | return false; |
300 | movingSeparator.clear(); |
301 | layout()->savedState.clear(); |
302 | return true; |
303 | } |
304 | |
305 | class Q_AUTOTEST_EXPORT QDockWidgetGroupWindow : public QWidget |
306 | { |
307 | Q_OBJECT |
308 | public: |
309 | explicit QDockWidgetGroupWindow(QWidget *parent = nullptr, Qt::WindowFlags f = {}) |
310 | : QWidget(parent, f) |
311 | { |
312 | } |
313 | QDockAreaLayoutInfo *layoutInfo() const; |
314 | #if QT_CONFIG(tabbar) |
315 | const QDockAreaLayoutInfo *tabLayoutInfo() const; |
316 | QDockWidget *activeTabbedDockWidget() const; |
317 | #endif |
318 | void destroyOrHideIfEmpty(); |
319 | bool hasVisibleDockWidgets() const; |
320 | void adjustFlags(); |
321 | bool hasNativeDecos() const; |
322 | |
323 | bool hover(QLayoutItem *widgetItem, const QPoint &mousePos); |
324 | void updateCurrentGapRect(); |
325 | void restore(); |
326 | void apply(); |
327 | |
328 | QRect currentGapRect; |
329 | QList<int> currentGapPos; |
330 | |
331 | signals: |
332 | void resized(); |
333 | |
334 | protected: |
335 | bool event(QEvent *) override; |
336 | void paintEvent(QPaintEvent*) override; |
337 | |
338 | private: |
339 | QSize m_removedFrameSize; |
340 | }; |
341 | |
342 | // This item will be used in the layout for the gap item. We cannot use QWidgetItem directly |
343 | // because QWidgetItem functions return an empty size for widgets that are floating. |
344 | class QDockWidgetGroupWindowItem : public QWidgetItem |
345 | { |
346 | public: |
347 | explicit QDockWidgetGroupWindowItem(QDockWidgetGroupWindow *parent) : QWidgetItem(parent) {} |
348 | |
349 | // when the item contains a dock widget, obtain its size (to prevent infinite loop) |
350 | // ask the layout otherwise |
351 | QSize minimumSize() const override |
352 | { |
353 | if (auto dw = widget()->findChild<QDockWidget *>()) |
354 | return dw->minimumSize(); |
355 | return lay()->minimumSize(); |
356 | } |
357 | QSize maximumSize() const override |
358 | { |
359 | auto dw = widget()->findChild<QDockWidget *>(); |
360 | if (dw) |
361 | return dw->maximumSize(); |
362 | return lay()->maximumSize(); |
363 | } |
364 | QSize sizeHint() const override |
365 | { |
366 | auto dw = widget()->findChild<QDockWidget *>(); |
367 | if (dw) |
368 | return dw->sizeHint(); |
369 | return lay()->sizeHint(); |
370 | } |
371 | QWidget* widget() const override { return wid; } |
372 | |
373 | private: |
374 | QLayout *lay() const { return const_cast<QDockWidgetGroupWindowItem *>(this)->widget()->layout(); } |
375 | }; |
376 | #endif // QT_CONFIG(dockwidget) |
377 | |
378 | /* This data structure represents the state of all the tool-bars and dock-widgets. It's value based |
379 | so it can be easily copied into a temporary variable. All operations are performed without moving |
380 | any widgets. Only when we are sure we have the desired state, we call apply(), which moves the |
381 | widgets. |
382 | */ |
383 | |
384 | class Q_AUTOTEST_EXPORT QMainWindowLayoutState |
385 | { |
386 | public: |
387 | QRect rect; |
388 | QMainWindow *mainWindow; |
389 | |
390 | QMainWindowLayoutState(QMainWindow *win); |
391 | |
392 | #if QT_CONFIG(toolbar) |
393 | QToolBarAreaLayout toolBarAreaLayout; |
394 | #endif |
395 | |
396 | #if QT_CONFIG(dockwidget) |
397 | QDockAreaLayout dockAreaLayout; |
398 | #else |
399 | QLayoutItem *centralWidgetItem; |
400 | QRect centralWidgetRect; |
401 | #endif |
402 | |
403 | void apply(bool animated); |
404 | void deleteAllLayoutItems(); |
405 | void deleteCentralWidgetItem(); |
406 | |
407 | QSize sizeHint() const; |
408 | QSize minimumSize() const; |
409 | bool fits() const; |
410 | void fitLayout(); |
411 | |
412 | QLayoutItem *itemAt(int index, int *x) const; |
413 | QLayoutItem *takeAt(int index, int *x); |
414 | QList<int> indexOf(QWidget *widget) const; |
415 | QLayoutItem *item(const QList<int> &path); |
416 | QRect itemRect(const QList<int> &path) const; |
417 | QRect gapRect(const QList<int> &path) const; // ### get rid of this, use itemRect() instead |
418 | |
419 | bool contains(QWidget *widget) const; |
420 | |
421 | void setCentralWidget(QWidget *widget); |
422 | QWidget *centralWidget() const; |
423 | |
424 | QList<int> gapIndex(QWidget *widget, const QPoint &pos) const; |
425 | bool insertGap(const QList<int> &path, QLayoutItem *item); |
426 | void remove(const QList<int> &path); |
427 | void remove(QLayoutItem *item); |
428 | void clear(); |
429 | bool isValid() const; |
430 | |
431 | QLayoutItem *plug(const QList<int> &path); |
432 | QLayoutItem *unplug(const QList<int> &path, QMainWindowLayoutState *savedState = nullptr); |
433 | |
434 | void saveState(QDataStream &stream) const; |
435 | bool checkFormat(QDataStream &stream); |
436 | bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState); |
437 | }; |
438 | |
439 | class Q_AUTOTEST_EXPORT QMainWindowLayout |
440 | : public QLayout, |
441 | public QMainWindowLayoutSeparatorHelper<QMainWindowLayout> |
442 | { |
443 | Q_OBJECT |
444 | |
445 | public: |
446 | QMainWindowLayoutState layoutState, savedState; |
447 | std::unique_ptr<QMainWindowLayoutState> restoredState; |
448 | |
449 | QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout); |
450 | ~QMainWindowLayout(); |
451 | |
452 | QMainWindow::DockOptions dockOptions; |
453 | void setDockOptions(QMainWindow::DockOptions opts); |
454 | |
455 | QLayoutItem *statusbar; |
456 | |
457 | // status bar |
458 | #if QT_CONFIG(statusbar) |
459 | QStatusBar *statusBar() const; |
460 | void setStatusBar(QStatusBar *sb); |
461 | #endif |
462 | |
463 | // central widget |
464 | QWidget *centralWidget() const; |
465 | void setCentralWidget(QWidget *cw); |
466 | |
467 | // toolbars |
468 | #if QT_CONFIG(toolbar) |
469 | void addToolBarBreak(Qt::ToolBarArea area); |
470 | void insertToolBarBreak(QToolBar *before); |
471 | void removeToolBarBreak(QToolBar *before); |
472 | |
473 | void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar, bool needAddChildWidget = true); |
474 | void insertToolBar(QToolBar *before, QToolBar *toolbar); |
475 | Qt::ToolBarArea toolBarArea(const QToolBar *toolbar) const; |
476 | bool toolBarBreak(QToolBar *toolBar) const; |
477 | void getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const; |
478 | void removeToolBar(QToolBar *toolbar); |
479 | void toggleToolBarsVisible(); |
480 | void moveToolBar(QToolBar *toolbar, int pos); |
481 | #endif |
482 | |
483 | // dock widgets |
484 | #if QT_CONFIG(dockwidget) |
485 | void setCorner(Qt::Corner corner, Qt::DockWidgetArea area); |
486 | Qt::DockWidgetArea corner(Qt::Corner corner) const; |
487 | enum DockWidgetAreaSize {Visible, Maximum}; |
488 | QRect dockWidgetAreaRect(Qt::DockWidgetArea area, DockWidgetAreaSize size = Maximum) const; |
489 | void addDockWidget(Qt::DockWidgetArea area, |
490 | QDockWidget *dockwidget, |
491 | Qt::Orientation orientation); |
492 | void splitDockWidget(QDockWidget *after, |
493 | QDockWidget *dockwidget, |
494 | Qt::Orientation orientation); |
495 | Qt::DockWidgetArea dockWidgetArea(QWidget* widget) const; |
496 | bool restoreDockWidget(QDockWidget *dockwidget); |
497 | #if QT_CONFIG(tabbar) |
498 | void tabifyDockWidget(QDockWidget *first, QDockWidget *second); |
499 | void raise(QDockWidget *widget); |
500 | void setVerticalTabsEnabled(bool enabled); |
501 | |
502 | QDockAreaLayoutInfo *dockInfo(QWidget *w); |
503 | bool _documentMode; |
504 | bool documentMode() const; |
505 | void setDocumentMode(bool enabled); |
506 | |
507 | QTabBar *getTabBar(); |
508 | QSet<QTabBar*> usedTabBars; |
509 | QList<QTabBar*> unusedTabBars; |
510 | bool verticalTabsEnabled; |
511 | |
512 | QWidget *getSeparatorWidget(); |
513 | QSet<QWidget*> usedSeparatorWidgets; |
514 | QList<QWidget*> unusedSeparatorWidgets; |
515 | int sep; // separator extent |
516 | |
517 | #if QT_CONFIG(tabwidget) |
518 | QTabWidget::TabPosition tabPositions[QInternal::DockCount]; |
519 | QTabWidget::TabShape _tabShape; |
520 | |
521 | QTabWidget::TabShape tabShape() const; |
522 | void setTabShape(QTabWidget::TabShape tabShape); |
523 | QTabWidget::TabPosition tabPosition(Qt::DockWidgetArea area) const; |
524 | void setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition); |
525 | |
526 | QDockWidgetGroupWindow *createTabbedDockWindow(); |
527 | #endif // QT_CONFIG(tabwidget) |
528 | #endif // QT_CONFIG(tabbar) |
529 | |
530 | QDockAreaLayout *dockAreaLayoutInfo() { return &layoutState.dockAreaLayout; } |
531 | void keepSize(QDockWidget *w); |
532 | #endif // QT_CONFIG(dockwidget) |
533 | |
534 | // save/restore |
535 | enum VersionMarkers { // sentinel values used to validate state data |
536 | VersionMarker = 0xff |
537 | }; |
538 | void saveState(QDataStream &stream) const; |
539 | bool restoreState(QDataStream &stream); |
540 | QBasicTimer discardRestoredStateTimer; |
541 | |
542 | // QLayout interface |
543 | void addItem(QLayoutItem *item) override; |
544 | void setGeometry(const QRect &r) override; |
545 | QLayoutItem *itemAt(int index) const override; |
546 | QLayoutItem *takeAt(int index) override; |
547 | int count() const override; |
548 | |
549 | QSize sizeHint() const override; |
550 | QSize minimumSize() const override; |
551 | mutable QSize szHint; |
552 | mutable QSize minSize; |
553 | void invalidate() override; |
554 | |
555 | // animations |
556 | QWidgetAnimator widgetAnimator; |
557 | QList<int> currentGapPos; |
558 | QRect currentGapRect; |
559 | QWidget *pluggingWidget; |
560 | #if QT_CONFIG(rubberband) |
561 | QPointer<QRubberBand> gapIndicator; |
562 | #endif |
563 | #if QT_CONFIG(dockwidget) |
564 | QPointer<QDockWidgetGroupWindow> currentHoveredFloat; // set when dragging over a floating dock widget |
565 | void setCurrentHoveredFloat(QDockWidgetGroupWindow *w); |
566 | #endif |
567 | bool isInApplyState = false; |
568 | |
569 | void hover(QLayoutItem *hoverTarget, const QPoint &mousePos); |
570 | bool plug(QLayoutItem *widgetItem); |
571 | QLayoutItem *unplug(QWidget *widget, bool group = false); |
572 | void revert(QLayoutItem *widgetItem); |
573 | void applyState(QMainWindowLayoutState &newState, bool animate = true); |
574 | void restore(bool keepSavedState = false); |
575 | void animationFinished(QWidget *widget); |
576 | |
577 | #if QT_CONFIG(draganddrop) |
578 | static bool needsPlatformDrag(); |
579 | Qt::DropAction performPlatformWidgetDrag(QLayoutItem *widgetItem, const QPoint &pressPosition); |
580 | QLayoutItem *draggingWidget = nullptr; |
581 | #endif |
582 | |
583 | protected: |
584 | void timerEvent(QTimerEvent *e) override; |
585 | |
586 | private Q_SLOTS: |
587 | void updateGapIndicator(); |
588 | #if QT_CONFIG(dockwidget) |
589 | #if QT_CONFIG(tabbar) |
590 | void tabChanged(); |
591 | void tabMoved(int from, int to); |
592 | #endif |
593 | #endif |
594 | private: |
595 | #if QT_CONFIG(tabbar) |
596 | void updateTabBarShapes(); |
597 | #endif |
598 | bool isInRestoreState = false; |
599 | }; |
600 | |
601 | #if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM) |
602 | class QDebug; |
603 | QDebug operator<<(QDebug debug, const QDockAreaLayout &layout); |
604 | QDebug operator<<(QDebug debug, const QMainWindowLayout *layout); |
605 | #endif |
606 | |
607 | QT_END_NAMESPACE |
608 | |
609 | #endif // QDYNAMICMAINWINDOWLAYOUT_P_H |
610 | |