Fix QMainWindow::restoreDockWidget() with GroupedDragging

We need to account for the fact that the placeholder might be in a
floating tab.

Task-number: QTBUG-50491
Change-Id: I03d8e49cc40f58691154f5c3984f3b0670a974d5
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Sérgio Martins <sergio.martins@kdab.com>
bb10
Olivier Goffart 2016-06-24 10:57:10 +02:00 committed by Olivier Goffart (Woboq GmbH)
parent 55ab276700
commit 17e5d9d7ca
4 changed files with 80 additions and 46 deletions

View File

@ -2604,6 +2604,21 @@ void QDockAreaLayout::remove(const QList<int> &path)
docks[index].remove(path.mid(1));
}
void QDockAreaLayout::removePlaceHolder(const QString &name)
{
QList<int> index = indexOfPlaceHolder(name);
if (!index.isEmpty())
remove(index);
foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>(
QString(), Qt::FindDirectChildrenOnly)) {
index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
if (!index.isEmpty()) {
dwgw->layoutInfo()->remove(index);
dwgw->destroyOrHideIfEmpty();
}
}
}
static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
@ -3030,15 +3045,27 @@ QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
{
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (index.isEmpty())
return false;
QDockAreaLayoutItem *item = 0;
foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>(
QString(), Qt::FindDirectChildrenOnly)) {
QList<int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty()) {
dockWidget->setParent(dwgw);
item = const_cast<QDockAreaLayoutItem *>(&dwgw->layoutInfo()->item(index));
break;
}
}
if (!item) {
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (index.isEmpty())
return false;
item = const_cast<QDockAreaLayoutItem *>(&this->item(index));
}
QDockAreaLayoutItem &item = this->item(index);
QPlaceHolderItem *placeHolder = item.placeHolderItem;
QPlaceHolderItem *placeHolder = item->placeHolderItem;
Q_ASSERT(placeHolder != 0);
item.widgetItem = new QDockWidgetItem(dockWidget);
item->widgetItem = new QDockWidgetItem(dockWidget);
if (placeHolder->window) {
const QRect r = constrainedRect(placeHolder->topLevelRect, dockWidget);
@ -3050,7 +3077,7 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
dockWidget->d_func()->setWindowState(true);
#endif
item.placeHolderItem = 0;
item->placeHolderItem = 0;
delete placeHolder;
return true;
@ -3086,9 +3113,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do
info = new_info;
}
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty())
remove(index);
removePlaceHolder(dockWidget->objectName());
}
void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
@ -3101,9 +3126,7 @@ void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
Q_ASSERT(info != 0);
info->tab(path.last(), new QDockWidgetItem(second));
QList<int> index = indexOfPlaceHolder(second->objectName());
if (!index.isEmpty())
remove(index);
removePlaceHolder(second->objectName());
}
void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks,
@ -3165,9 +3188,7 @@ void QDockAreaLayout::splitDockWidget(QDockWidget *after,
Q_ASSERT(info != 0);
info->split(path.last(), orientation, new QDockWidgetItem(dockWidget));
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty())
remove(index);
removePlaceHolder(dockWidget->objectName());
}
void QDockAreaLayout::apply(bool animate)

View File

@ -255,6 +255,7 @@ public:
QLayoutItem *plug(const QList<int> &path);
QLayoutItem *unplug(const QList<int> &path);
void remove(const QList<int> &path);
void removePlaceHolder(const QString &name);
void fitLayout();

View File

@ -215,11 +215,10 @@ public:
}
void setGeometry(const QRect&r) Q_DECL_OVERRIDE
{
static_cast<QDockWidgetGroupWindow *>(parent())->destroyOrHideIfEmpty();
QDockAreaLayoutInfo *li = layoutInfo();
if (li->isEmpty()) {
static_cast<QDockWidgetGroupWindow *>(parent())->destroyIfEmpty();
if (li->isEmpty())
return;
}
int fw = frameWidth();
li->reparentWidgets(parentWidget());
li->rect = r.adjusted(fw, fw, -fw, -fw);
@ -272,6 +271,10 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
if (qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
adjustFlags();
break;
case QEvent::LayoutRequest:
// We might need to show the widget again
destroyOrHideIfEmpty();
break;
default:
break;
}
@ -325,34 +328,43 @@ QDockWidget *QDockWidgetGroupWindow::topDockWidget() const
}
/*! \internal
Destroy this window if there is no more QDockWidget in it.
Destroy or hide this window if there is no more QDockWidget in it.
Otherwise make sure it is shown.
*/
void QDockWidgetGroupWindow::destroyIfEmpty()
void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
{
if (layoutInfo()->isEmpty()) {
// Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
foreach (QDockWidget *dw,
findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly)) {
bool wasFloating = dw->isFloating();
bool wasHidden = dw->isHidden();
dw->setParent(parentWidget());
if (wasFloating) {
dw->setFloating(true);
} else {
// maybe it was hidden, we still have to put it back in the main layout.
QMainWindowLayout *ml = qt_mainwindow_layout(static_cast<QMainWindow*>(parentWidget()));
Qt::DockWidgetArea area = ml->dockWidgetArea(this);
if (area == Qt::NoDockWidgetArea)
area = Qt::LeftDockWidgetArea;
static_cast<QMainWindow*>(parentWidget())->addDockWidget(area, dw);
}
if (!wasHidden)
dw->show();
}
foreach (QTabBar *tb, findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly))
tb->setParent(parentWidget());
deleteLater();
if (!layoutInfo()->isEmpty()) {
show(); // It might have been hidden,
return;
}
// There might still be placeholders
if (!layoutInfo()->item_list.isEmpty()) {
hide();
return;
}
// Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
foreach (QDockWidget *dw, findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly)) {
bool wasFloating = dw->isFloating();
bool wasHidden = dw->isHidden();
dw->setParent(parentWidget());
if (wasFloating) {
dw->setFloating(true);
} else {
// maybe it was hidden, we still have to put it back in the main layout.
QMainWindowLayout *ml =
qt_mainwindow_layout(static_cast<QMainWindow *>(parentWidget()));
Qt::DockWidgetArea area = ml->dockWidgetArea(this);
if (area == Qt::NoDockWidgetArea)
area = Qt::LeftDockWidgetArea;
static_cast<QMainWindow *>(parentWidget())->addDockWidget(area, dw);
}
if (!wasHidden)
dw->show();
}
foreach (QTabBar *tb, findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly))
tb->setParent(parentWidget());
deleteLater();
}
/*! \internal
@ -2075,7 +2087,7 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
item.subinfo->reparentWidgets(parentWidget());
item.subinfo->setTabBarShape(parentInfo->tabBarShape);
}
dwgw->destroyIfEmpty();
dwgw->destroyOrHideIfEmpty();
}
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {

View File

@ -86,7 +86,7 @@ public:
: QWidget(parent, f) {}
QDockAreaLayoutInfo *layoutInfo() const;
QDockWidget *topDockWidget() const;
void destroyIfEmpty();
void destroyOrHideIfEmpty();
void adjustFlags();
protected:
bool event(QEvent *) Q_DECL_OVERRIDE;