Merge branch 'ff/editor/dev/widget_factory' of https://github.com/rolivav/Qt-Advanced-Docking-System into rolivav-ff/editor/dev/widget_factory

This commit is contained in:
Uwe Kindler 2021-10-14 13:18:54 +02:00
commit 03a8eaa44f
3 changed files with 108 additions and 13 deletions

View File

@ -41,7 +41,7 @@ int main(int argc, char *argv[])
now->widget()->setFocus(); 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); w.menuBar()->addAction(action);
int i = 0; int i = 0;
@ -53,7 +53,26 @@ int main(int argc, char *argv[])
auto area = dockManager->addDockWidgetTab(ads::CenterDockWidgetArea, dw); auto area = dockManager->addDockWidgetTab(ads::CenterDockWidgetArea, dw);
qDebug() << "doc dock widget created!" << dw << area; 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); action = new QAction("New", &w);
w.menuBar()->addAction(action); w.menuBar()->addAction(action);
QObject::connect(action, &QAction::triggered, [&]() { QObject::connect(action, &QAction::triggered, [&]() {

View File

@ -66,6 +66,12 @@ namespace ads
*/ */
struct DockWidgetPrivate struct DockWidgetPrivate
{ {
struct WidgetFactory
{
CDockWidget::FactoryFunc createWidget;
CDockWidget::eInsertMode insertMode;
};
CDockWidget* _this = nullptr; CDockWidget* _this = nullptr;
QBoxLayout* Layout = nullptr; QBoxLayout* Layout = nullptr;
QWidget* Widget = nullptr; QWidget* Widget = nullptr;
@ -84,7 +90,8 @@ struct DockWidgetPrivate
bool IsFloatingTopLevel = false; bool IsFloatingTopLevel = false;
QList<QAction*> TitleBarActions; QList<QAction*> TitleBarActions;
CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget; CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
WidgetFactory* Factory = nullptr;
/** /**
* Private data constructor * Private data constructor
*/ */
@ -116,6 +123,12 @@ struct DockWidgetPrivate
* Setup the main scroll area * Setup the main scroll area
*/ */
void setupScrollArea(); 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 // struct DockWidgetPrivate
@ -130,6 +143,14 @@ DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
//============================================================================ //============================================================================
void DockWidgetPrivate::showDockWidget() 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) if (!DockArea)
{ {
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
@ -167,6 +188,12 @@ void DockWidgetPrivate::hideDockWidget()
{ {
TabWidget->hide(); TabWidget->hide();
updateParentDockArea(); updateParentDockArea();
if (Features.testFlag(CDockWidget::RecreateContentsWidgetOnCloseAndOpen))
{
Widget->deleteLater();
Widget = nullptr;
}
} }
@ -219,6 +246,38 @@ void DockWidgetPrivate::setupScrollArea()
Layout->addWidget(ScrollArea); 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) : CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
@ -290,6 +349,11 @@ void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
d->Widget->setProperty("dockWidgetContent", true); d->Widget->setProperty("dockWidgetContent", true);
} }
//============================================================================
void CDockWidget::setWidgetFactory(FactoryFunc createWidget, eInsertMode insertMode) {
d->setWidgetFactory(createWidget, insertMode);
}
//============================================================================ //============================================================================
QWidget* CDockWidget::takeWidget() QWidget* CDockWidget::takeWidget()

View File

@ -147,18 +147,19 @@ public:
enum DockWidgetFeature enum DockWidgetFeature
{ {
DockWidgetClosable = 0x01,///< dock widget has a close button DockWidgetClosable = 0x001,///< 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 DockWidgetMovable = 0x002,///< 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 DockWidgetFloatable = 0x004,///< dock widget can be dragged into a floating window
DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed DockWidgetDeleteOnClose = 0x008, ///< 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 CustomCloseHandling = 0x010, ///< 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 DockWidgetFocusable = 0x020, ///< 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 DockWidgetForceCloseWithArea = 0x040, ///< 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 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, DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable,
AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling, AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling,
DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose, DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose,
NoDockWidgetFeatures = 0x00 NoDockWidgetFeatures = 0x000
}; };
Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
@ -269,7 +270,18 @@ public:
* provide the InsertMode ForceNoScrollArea * provide the InsertMode ForceNoScrollArea
*/ */
void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea); 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<QWidget*(QWidget*)>;
void setWidgetFactory(FactoryFunc createWidget, eInsertMode InsertMode = AutoScrollArea);
/** /**
* Remove the widget from the dock and give ownership back to the caller * Remove the widget from the dock and give ownership back to the caller
*/ */