diff --git a/examples/deleteonclose/main.cpp b/examples/deleteonclose/main.cpp index 14b0216..f587524 100644 --- a/examples/deleteonclose/main.cpp +++ b/examples/deleteonclose/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) now->widget()->setFocus(); }); - QAction *action = new QAction("New Delete On Close", &w); + QAction *action = new QAction("New Delete Dock Widget On Close", &w); w.menuBar()->addAction(action); int i = 0; @@ -53,7 +53,26 @@ int main(int argc, char *argv[]) auto area = dockManager->addDockWidgetTab(ads::CenterDockWidgetArea, dw); qDebug() << "doc dock widget created!" << dw << area; }); - + + auto dw = new ads::CDockWidget(QStringLiteral("test doc %1").arg(i++), &w); + auto editor = new QTextEdit(QStringLiteral("recreated lorem ipsum......"), dw); + dw->setWidget(editor); + dw->setFeature(ads::CDockWidget::RecreateContentsWidgetOnCloseAndOpen, true); + dw->setWidgetFactory([](QWidget* dw){ + static int timesRecreated = 0; + return new QTextEdit(QStringLiteral("recreated lorem ipsum... times %1").arg(++timesRecreated), dw); + }); + auto area = dockManager->addDockWidgetTab(ads::CenterDockWidgetArea, dw); + qDebug() << "RecreateContentsWidgetOnCloseAndOpen dock widget created!" << dw << area; + + action = new QAction("Toggle Recreate Contents Widget On Close and Open", &w); + w.menuBar()->addAction(action); + + QObject::connect(action, &QAction::triggered, [dw]() { + dw->toggleView(dw->isClosed()); + qDebug() << QString("dock widget %1! contents widget %2!").arg(dw->isClosed() ? "closed" : "open", dw->widget() ? "created" : "deleted"); + }); + action = new QAction("New", &w); w.menuBar()->addAction(action); QObject::connect(action, &QAction::triggered, [&]() { diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 059f5a2..3c15789 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -66,6 +66,12 @@ namespace ads */ struct DockWidgetPrivate { + struct WidgetFactory + { + CDockWidget::FactoryFunc createWidget; + CDockWidget::eInsertMode insertMode; + }; + CDockWidget* _this = nullptr; QBoxLayout* Layout = nullptr; QWidget* Widget = nullptr; @@ -84,7 +90,8 @@ struct DockWidgetPrivate bool IsFloatingTopLevel = false; QList TitleBarActions; CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget; - + WidgetFactory* Factory = nullptr; + /** * Private data constructor */ @@ -116,6 +123,12 @@ struct DockWidgetPrivate * Setup the main scroll area */ void setupScrollArea(); + + /** + * Sets the widget factory that will be used to recreate and set the contents widget. + */ + void setWidgetFactory(CDockWidget::FactoryFunc createWidget, CDockWidget::eInsertMode insertMode); + bool createWidgetFromFactory(); }; // struct DockWidgetPrivate @@ -130,6 +143,14 @@ DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) : //============================================================================ void DockWidgetPrivate::showDockWidget() { + if (!Widget) { + if(!createWidgetFromFactory()) { + Q_ASSERT(!Features.testFlag(CDockWidget::RecreateContentsWidgetOnCloseAndOpen) + && "RecreateContentsWidgetOnCloseAndOpen flag was set, but the widget factory is missing or it doesn't return a valid QWidget."); + return; + } + } + if (!DockArea) { CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); @@ -167,6 +188,12 @@ void DockWidgetPrivate::hideDockWidget() { TabWidget->hide(); updateParentDockArea(); + + if (Features.testFlag(CDockWidget::RecreateContentsWidgetOnCloseAndOpen)) + { + Widget->deleteLater(); + Widget = nullptr; + } } @@ -219,6 +246,38 @@ void DockWidgetPrivate::setupScrollArea() Layout->addWidget(ScrollArea); } +void DockWidgetPrivate::setWidgetFactory(CDockWidget::FactoryFunc createWidget, CDockWidget::eInsertMode insertMode) +{ + if (Factory) + { + delete Factory; + } + + Factory = new WidgetFactory { createWidget, insertMode }; +} + +bool DockWidgetPrivate::createWidgetFromFactory() +{ + if (!Features.testFlag(CDockWidget::RecreateContentsWidgetOnCloseAndOpen)) + { + return false; + } + + if (!Factory) + { + return false; + } + + QWidget* w = Factory->createWidget(_this); + if (!w) + { + return false; + } + + _this->setWidget(w, Factory->insertMode); + return true; +} + //============================================================================ CDockWidget::CDockWidget(const QString &title, QWidget *parent) : @@ -290,6 +349,11 @@ void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode) d->Widget->setProperty("dockWidgetContent", true); } +//============================================================================ +void CDockWidget::setWidgetFactory(FactoryFunc createWidget, eInsertMode insertMode) { + d->setWidgetFactory(createWidget, insertMode); +} + //============================================================================ QWidget* CDockWidget::takeWidget() diff --git a/src/DockWidget.h b/src/DockWidget.h index bc36a90..22de8fb 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -147,18 +147,19 @@ public: enum DockWidgetFeature { - DockWidgetClosable = 0x01,///< dock widget has a close button - DockWidgetMovable = 0x02,///< dock widget is movable and can be moved to a new position in the current dock container - DockWidgetFloatable = 0x04,///< dock widget can be dragged into a floating window - DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed - CustomCloseHandling = 0x10, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead - DockWidgetFocusable = 0x20, ///< if this is enabled, a dock widget can get focus highlighting - DockWidgetForceCloseWithArea = 0x40, ///< dock widget will be closed when the dock area hosting it is closed - NoTab = 0x80, ///< dock widget tab will never be shown if this flag is set + DockWidgetClosable = 0x001,///< dock widget has a close button + DockWidgetMovable = 0x002,///< dock widget is movable and can be moved to a new position in the current dock container + DockWidgetFloatable = 0x004,///< dock widget can be dragged into a floating window + DockWidgetDeleteOnClose = 0x008, ///< deletes the dock widget when it is closed + CustomCloseHandling = 0x010, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead + DockWidgetFocusable = 0x020, ///< if this is enabled, a dock widget can get focus highlighting + DockWidgetForceCloseWithArea = 0x040, ///< dock widget will be closed when the dock area hosting it is closed + NoTab = 0x080, ///< dock widget tab will never be shown if this flag is set + RecreateContentsWidgetOnCloseAndOpen = 0x100, ///< deletes only the contained widget on close, keeping the dock widget intact and in place. Attempts to rebuild the contents widget on show if there is a widget factory set. DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable, AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling, DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose, - NoDockWidgetFeatures = 0x00 + NoDockWidgetFeatures = 0x000 }; Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) @@ -269,7 +270,18 @@ public: * provide the InsertMode ForceNoScrollArea */ void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea); - + + /** + * Only used when the flag RecreateContentsWidgetOnCloseAndOpen is set. + * Using the flag and setting a widget factory allows to free the resources of + * the widget of your application while retaining the position the next time you want to + * show your widget, unlike the flag DockWidgetDeleteOnClose which deletes the dock widget itself. + * Since we keep the dock widget, all regular features of ADS should work as normal, including + * saving and restoring the state of the docking system and using perspectives. + */ + using FactoryFunc = std::function; + void setWidgetFactory(FactoryFunc createWidget, eInsertMode InsertMode = AutoScrollArea); + /** * Remove the widget from the dock and give ownership back to the caller */