diff --git a/Changelog b/Changelog index 82cd1180..a724c2be 100644 --- a/Changelog +++ b/Changelog @@ -2,7 +2,7 @@ - [TODO] QtQuick support * v1.2.1 (unreleased) - - + - Support for resizing dock widgets when they are in overlay/popup mode (autohide/sidebar feature) * v1.2.0 (17 December 2020) - Wayland support diff --git a/src/DockWidgetBase.cpp b/src/DockWidgetBase.cpp index f3f6db07..30b49d37 100644 --- a/src/DockWidgetBase.cpp +++ b/src/DockWidgetBase.cpp @@ -132,6 +132,7 @@ public: bool m_updatingToggleAction = false; bool m_updatingFloatAction = false; bool m_isForceClosing = false; + QSize m_lastOverlayedSize = QSize(0, 0); }; DockWidgetBase::DockWidgetBase(const QString &name, Options options) @@ -516,6 +517,11 @@ bool DockWidgetBase::hasPreviousDockedLocation() const return d->m_lastPositions.isValid(); } +QSize DockWidgetBase::lastOverlayedSize() const +{ + return d->m_lastOverlayedSize; +} + FloatingWindow *DockWidgetBase::morphIntoFloatingWindow() { qCDebug(creation) << "DockWidget::morphIntoFloatingWindow() this=" << this @@ -795,6 +801,19 @@ void DockWidgetBase::onHidden(bool spontaneous) } } +bool DockWidgetBase::onResize(QSize newSize) +{ + if (isOverlayed()) { + if (auto frame = this->frame()) { + d->m_lastOverlayedSize = frame->QWidgetAdapter::size(); + } else { + qWarning() << Q_FUNC_INFO << "Overlayed dock widget without frame shouldn't happen"; + } + } + + return QWidgetAdapter::onResize(newSize); +} + void DockWidgetBase::onCloseEvent(QCloseEvent *e) { e->accept(); // By default we accept, means DockWidget closes diff --git a/src/DockWidgetBase.h b/src/DockWidgetBase.h index f151134e..8bdaa33b 100644 --- a/src/DockWidgetBase.h +++ b/src/DockWidgetBase.h @@ -440,6 +440,10 @@ public: /// When you call dockWidget->setFloating(false) it will only dock if it knows where to. bool hasPreviousDockedLocation() const; + /// @brief returns the last size the widget has when overlayed + /// Empty otherwise + QSize lastOverlayedSize() const; + Q_SIGNALS: ///@brief signal emitted when the parent changed void parentChanged(); @@ -491,6 +495,8 @@ protected: void onParentChanged(); void onShown(bool spontaneous); void onHidden(bool spontaneous); + bool onResize(QSize newSize) override; + #ifndef PYTHON_BINDINGS //Pyside bug: https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1327 void onCloseEvent(QCloseEvent *e) override; #endif diff --git a/src/MainWindowBase.cpp b/src/MainWindowBase.cpp index afda1b40..b0f78adb 100644 --- a/src/MainWindowBase.cpp +++ b/src/MainWindowBase.cpp @@ -48,7 +48,7 @@ public: QRect rectForOverlay(Frame *, SideBarLocation) const; SideBarLocation preferredSideBar(DockWidgetBase *) const; - void updateOverlayGeometry(); + void updateOverlayGeometry(bool reusePreviousSize = false); void clearSideBars(); QString name; @@ -346,7 +346,7 @@ SideBarLocation MainWindowBase::Private::preferredSideBar(DockWidgetBase *dw) co : SideBarLocation::West; } -void MainWindowBase::Private::updateOverlayGeometry() +void MainWindowBase::Private::updateOverlayGeometry(bool reusePreviousSize) { if (!m_overlayedDockWidget) return; @@ -357,7 +357,46 @@ void MainWindowBase::Private::updateOverlayGeometry() return; } - m_overlayedDockWidget->frame()->QWidgetAdapter::setGeometry(rectForOverlay(m_overlayedDockWidget->frame(), sb->location())); + const QRect defaultGeometry = rectForOverlay(m_overlayedDockWidget->frame(), sb->location()); + QRect newGeometry = defaultGeometry; + + Frame *frame = m_overlayedDockWidget->frame(); + + if (reusePreviousSize) { + // Let's try to honour the previous overlay size + switch (sb->location()) { + case SideBarLocation::North: { + const int maxHeight = q->height() - frame->pos().y() - 10; // gap + newGeometry.setHeight(qMin(frame->height(), maxHeight)); + break; + } + case SideBarLocation::South: { + const int maxHeight = sb->pos().y() - m_dropArea->pos().y() - 10; // gap + const int bottom = newGeometry.bottom(); + newGeometry.setHeight(qMin(frame->height(), maxHeight)); + newGeometry.moveBottom(bottom); + break; + } + case SideBarLocation::East: { + const int maxWidth = sb->pos().x() - m_dropArea->pos().x() - 10; // gap + const int right = newGeometry.right(); + newGeometry.setWidth(qMin(frame->width(), maxWidth)); + newGeometry.moveRight(right); + break; + } + case SideBarLocation::West: { + const int maxWidth = q->width() - frame->pos().x() - 10; // gap + newGeometry.setWidth(qMin(frame->height(), maxWidth)); + break; + } + case SideBarLocation::None: + qWarning() << Q_FUNC_INFO << "Unexpected sidebar value"; + break; + } + + } + + m_overlayedDockWidget->frame()->QWidgetAdapter::setGeometry(newGeometry); } void MainWindowBase::Private::clearSideBars() @@ -424,7 +463,7 @@ void MainWindowBase::overlayOnSideBar(DockWidgetBase *dw) auto frame = Config::self().frameworkWidgetFactory()->createFrame(this, FrameOption_IsOverlayed); d->m_overlayedDockWidget = dw; frame->addWidget(dw); - d->updateOverlayGeometry(); + d->updateOverlayGeometry(/*reusePreviousSize=*/ false); // Uncomment once I'm happy with the resizing auto resizeHandler = new WidgetResizeHandler(true, frame); @@ -512,7 +551,7 @@ void MainWindowBase::setUniqueName(const QString &uniqueName) void MainWindowBase::onResized(QResizeEvent *) { if (d->m_overlayedDockWidget) - d->updateOverlayGeometry(); + d->updateOverlayGeometry(/*reusePreviousSize=*/ true); } bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)