Skip to content

Commit

Permalink
Merge pull request qt#91 from autodesk-forks/kandass1/MAYA-131102/res…
Browse files Browse the repository at this point in the history
…olve_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.
  • Loading branch information
Senthil Kannan Kandaswamy authored and GitHub Enterprise committed Nov 6, 2023
2 parents ea84a19 + 9f02de8 commit 9d9e7c0
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 67 deletions.
99 changes: 32 additions & 67 deletions src/widgets/widgets/qmainwindowlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#include <qmap.h>
#include <qtimer.h>
#include <qpointer.h>
#include <qobject.h>
#include <qaction.h>

#ifndef QT_NO_DEBUG_STREAM
# include <qdebug.h>
Expand Down Expand Up @@ -264,6 +266,20 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
if (QDockWidget *dw = activeTabbedDockWidget()) {
dw->close();
adjustFlags();
// when all child QDockWidgets' are closed, this QDockWidgetGroupWindow will be hidden
// after receiving the `LayoutRequest` event. This causes subsequent call to show
// on the current QDockWidget to fail. Hence, adding a connection to the
// QDockWidget's toggle action to re-show this QDockWidgetGroupWindow along with the
// current QDockWidget.
m_widgetConnections[dw] = connect(dw->toggleViewAction(), &QAction::toggled, [this, dw]() {
// show this QDockWidgetGroupWindow before showing the child QDockWidget.
show();
dw->show();
// once at least one child becomes visible, clear all listeners since we no longer need them..
for (const auto& pair : m_widgetConnections)
disconnect(pair.second);
m_widgetConnections.clear();
});
}
#endif
return true;
Expand All @@ -288,6 +304,10 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
if (qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
adjustFlags();
break;
case QEvent::ChildRemoved:
if (auto widget = qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
m_widgetConnections.erase(widget);
break;
case QEvent::LayoutRequest:
// We might need to show the widget again
destroyOrHideIfEmpty();
Expand Down Expand Up @@ -2577,70 +2597,7 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)

// unplug the widget first
dockWidget->d_func()->unplug(widget->geometry());

// Create a floating tab, copy properties and generate layout info
QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
const QInternal::DockPosition dockPos = groupWindow->layoutInfo()->dockPos;
QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();

const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dockWidget);

// Populate newly created DockAreaLayoutInfo of floating tabs
*info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, dockPos,
Qt::Horizontal, shape,
layoutState.mainWindow);

// Create tab and hide it as group window contains only one widget
info->tabbed = true;
info->tabBar = getTabBar();
info->tabBar->hide();
updateGapIndicator();

// Reparent it to a QDockWidgetGroupLayout
floatingTabs->setGeometry(dockWidget->geometry());

// Append reference to floatingTabs to the dock's item_list
parentItem.widgetItem = new QDockWidgetGroupWindowItem(floatingTabs);
layoutState.dockAreaLayout.docks[dockPos].item_list.append(parentItem);

// use populated parentItem to set reference to dockWidget as the first item in own list
parentItem.widgetItem = new QDockWidgetItem(dockWidget);
info->item_list = {parentItem};

// Add non-gap items of the dock to the tab bar
for (const auto &listItem : layoutState.dockAreaLayout.docks[dockPos].item_list) {
if (listItem.GapItem || !listItem.widgetItem)
continue;
info->tabBar->addTab(listItem.widgetItem->widget()->objectName());
}

// Re-parent and fit
floatingTabs->setParent(layoutState.mainWindow);
floatingTabs->layoutInfo()->fitItems();
floatingTabs->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
groupWindow->layoutInfo()->fitItems();
groupWindow->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
dockWidget->d_func()->tabPosition = layoutState.mainWindow->tabPosition(toDockWidgetArea(dockPos));
info->reparentWidgets(floatingTabs);
dockWidget->setParent(floatingTabs);
info->updateTabBar();

// Show the new item
const QList<int> path = layoutState.indexOf(floatingTabs);
QRect r = layoutState.itemRect(path);
savedState = layoutState;
savedState.fitLayout();

// Update gap, fix orientation, raise and show
currentGapPos = path;
currentGapRect = r;
updateGapIndicator();
fixToolBarOrientation(parentItem.widgetItem, currentGapPos.at(1));
floatingTabs->show();
floatingTabs->raise();

qCDebug(lcQpaDockWidgets) << "Unplugged from floating dock:" << widget << "from" << parentItem.widgetItem;
return parentItem.widgetItem;
return item;
}
}
#endif
Expand Down Expand Up @@ -2837,10 +2794,18 @@ void QMainWindowLayout::hover(QLayoutItem *hoverTarget,
info->tabBar = getTabBar();
info->tabbed = true;
QLayout *parentLayout = dropTo->parentWidget()->layout();
info->item_list.append(
QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo))));

auto parentItem = QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo)));
if (!parentItem.widgetItem)
parentItem.widgetItem = new QDockWidgetItem(dropTo);
info->item_list.append(parentItem);

auto oldGroupWindow = qobject_cast<QDockWidgetGroupWindow *>(dropTo->parent());
dropTo->setParent(floatingTabs);
// just an early cleanup to if there are no other children.
if (oldGroupWindow) {
oldGroupWindow->destroyOrHideIfEmpty();
}

qCDebug(lcQpaDockWidgets) << "Wrapping" << widget << "into floating tabs" << floatingTabs;
w = floatingTabs;
}
Expand Down
2 changes: 2 additions & 0 deletions src/widgets/widgets/qmainwindowlayout_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "qtoolbararealayout_p.h"
#endif
#include <QtCore/qloggingcategory.h>
#include <unordered_map>

QT_REQUIRE_CONFIG(mainwindow);

Expand Down Expand Up @@ -335,6 +336,7 @@ class Q_AUTOTEST_EXPORT QDockWidgetGroupWindow : public QWidget

private:
QSize m_removedFrameSize;
std::unordered_map<QDockWidget*, QMetaObject::Connection> m_widgetConnections;
};

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

0 comments on commit 9d9e7c0

Please sign in to comment.