Skip to content

Commit 9d9e7c0

Browse files
senthilauto2023GitHub Enterprise
authored and
GitHub Enterprise
committed
Merge pull request qt#91 from autodesk-forks/kandass1/MAYA-131102/resolve_docking_issues_post_qt6_new
- Dragging an individual DockWidget (Tab) doesn't require a QDockWidgetGroupWindow immediately, Hence, returning the unplugged DockWidget directly. - Hovering a DockWidget on top of another DockWidget, creates a QDockWidgetGroupWindow if one doesn't already exist. However, dropTarget's widgetItem might not be already available in the parent layout which causes a crash. Hence, setting a DockWidgetItem. - Closing all the child DockWidgets would eventually cause the QDockWidgetGroupWindow to be hidden. However, when we re-toggle DockWidget visibility from the menu items, the DockWidget won't become visible since its parent QDockWidgetGroupWindow is hidden. Hence adding a listener for the DockWidget's toggle action ensures the parent is shown before the widget.
2 parents ea84a19 + 9f02de8 commit 9d9e7c0

File tree

2 files changed

+34
-67
lines changed

2 files changed

+34
-67
lines changed

src/widgets/widgets/qmainwindowlayout.cpp

+32-67
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include <qmap.h>
3636
#include <qtimer.h>
3737
#include <qpointer.h>
38+
#include <qobject.h>
39+
#include <qaction.h>
3840

3941
#ifndef QT_NO_DEBUG_STREAM
4042
# include <qdebug.h>
@@ -264,6 +266,20 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
264266
if (QDockWidget *dw = activeTabbedDockWidget()) {
265267
dw->close();
266268
adjustFlags();
269+
// when all child QDockWidgets' are closed, this QDockWidgetGroupWindow will be hidden
270+
// after receiving the `LayoutRequest` event. This causes subsequent call to show
271+
// on the current QDockWidget to fail. Hence, adding a connection to the
272+
// QDockWidget's toggle action to re-show this QDockWidgetGroupWindow along with the
273+
// current QDockWidget.
274+
m_widgetConnections[dw] = connect(dw->toggleViewAction(), &QAction::toggled, [this, dw]() {
275+
// show this QDockWidgetGroupWindow before showing the child QDockWidget.
276+
show();
277+
dw->show();
278+
// once at least one child becomes visible, clear all listeners since we no longer need them..
279+
for (const auto& pair : m_widgetConnections)
280+
disconnect(pair.second);
281+
m_widgetConnections.clear();
282+
});
267283
}
268284
#endif
269285
return true;
@@ -288,6 +304,10 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
288304
if (qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
289305
adjustFlags();
290306
break;
307+
case QEvent::ChildRemoved:
308+
if (auto widget = qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
309+
m_widgetConnections.erase(widget);
310+
break;
291311
case QEvent::LayoutRequest:
292312
// We might need to show the widget again
293313
destroyOrHideIfEmpty();
@@ -2577,70 +2597,7 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
25772597

25782598
// unplug the widget first
25792599
dockWidget->d_func()->unplug(widget->geometry());
2580-
2581-
// Create a floating tab, copy properties and generate layout info
2582-
QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
2583-
const QInternal::DockPosition dockPos = groupWindow->layoutInfo()->dockPos;
2584-
QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
2585-
2586-
const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dockWidget);
2587-
2588-
// Populate newly created DockAreaLayoutInfo of floating tabs
2589-
*info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, dockPos,
2590-
Qt::Horizontal, shape,
2591-
layoutState.mainWindow);
2592-
2593-
// Create tab and hide it as group window contains only one widget
2594-
info->tabbed = true;
2595-
info->tabBar = getTabBar();
2596-
info->tabBar->hide();
2597-
updateGapIndicator();
2598-
2599-
// Reparent it to a QDockWidgetGroupLayout
2600-
floatingTabs->setGeometry(dockWidget->geometry());
2601-
2602-
// Append reference to floatingTabs to the dock's item_list
2603-
parentItem.widgetItem = new QDockWidgetGroupWindowItem(floatingTabs);
2604-
layoutState.dockAreaLayout.docks[dockPos].item_list.append(parentItem);
2605-
2606-
// use populated parentItem to set reference to dockWidget as the first item in own list
2607-
parentItem.widgetItem = new QDockWidgetItem(dockWidget);
2608-
info->item_list = {parentItem};
2609-
2610-
// Add non-gap items of the dock to the tab bar
2611-
for (const auto &listItem : layoutState.dockAreaLayout.docks[dockPos].item_list) {
2612-
if (listItem.GapItem || !listItem.widgetItem)
2613-
continue;
2614-
info->tabBar->addTab(listItem.widgetItem->widget()->objectName());
2615-
}
2616-
2617-
// Re-parent and fit
2618-
floatingTabs->setParent(layoutState.mainWindow);
2619-
floatingTabs->layoutInfo()->fitItems();
2620-
floatingTabs->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
2621-
groupWindow->layoutInfo()->fitItems();
2622-
groupWindow->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
2623-
dockWidget->d_func()->tabPosition = layoutState.mainWindow->tabPosition(toDockWidgetArea(dockPos));
2624-
info->reparentWidgets(floatingTabs);
2625-
dockWidget->setParent(floatingTabs);
2626-
info->updateTabBar();
2627-
2628-
// Show the new item
2629-
const QList<int> path = layoutState.indexOf(floatingTabs);
2630-
QRect r = layoutState.itemRect(path);
2631-
savedState = layoutState;
2632-
savedState.fitLayout();
2633-
2634-
// Update gap, fix orientation, raise and show
2635-
currentGapPos = path;
2636-
currentGapRect = r;
2637-
updateGapIndicator();
2638-
fixToolBarOrientation(parentItem.widgetItem, currentGapPos.at(1));
2639-
floatingTabs->show();
2640-
floatingTabs->raise();
2641-
2642-
qCDebug(lcQpaDockWidgets) << "Unplugged from floating dock:" << widget << "from" << parentItem.widgetItem;
2643-
return parentItem.widgetItem;
2600+
return item;
26442601
}
26452602
}
26462603
#endif
@@ -2837,10 +2794,18 @@ void QMainWindowLayout::hover(QLayoutItem *hoverTarget,
28372794
info->tabBar = getTabBar();
28382795
info->tabbed = true;
28392796
QLayout *parentLayout = dropTo->parentWidget()->layout();
2840-
info->item_list.append(
2841-
QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo))));
2842-
2797+
auto parentItem = QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo)));
2798+
if (!parentItem.widgetItem)
2799+
parentItem.widgetItem = new QDockWidgetItem(dropTo);
2800+
info->item_list.append(parentItem);
2801+
2802+
auto oldGroupWindow = qobject_cast<QDockWidgetGroupWindow *>(dropTo->parent());
28432803
dropTo->setParent(floatingTabs);
2804+
// just an early cleanup to if there are no other children.
2805+
if (oldGroupWindow) {
2806+
oldGroupWindow->destroyOrHideIfEmpty();
2807+
}
2808+
28442809
qCDebug(lcQpaDockWidgets) << "Wrapping" << widget << "into floating tabs" << floatingTabs;
28452810
w = floatingTabs;
28462811
}

src/widgets/widgets/qmainwindowlayout_p.h

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "qtoolbararealayout_p.h"
3939
#endif
4040
#include <QtCore/qloggingcategory.h>
41+
#include <unordered_map>
4142

4243
QT_REQUIRE_CONFIG(mainwindow);
4344

@@ -335,6 +336,7 @@ class Q_AUTOTEST_EXPORT QDockWidgetGroupWindow : public QWidget
335336

336337
private:
337338
QSize m_removedFrameSize;
339+
std::unordered_map<QDockWidget*, QMetaObject::Connection> m_widgetConnections;
338340
};
339341

340342
// This item will be used in the layout for the gap item. We cannot use QWidgetItem directly

0 commit comments

Comments
 (0)