Implemented custom close handling

This commit is contained in:
Uwe Kindler 2020-01-06 11:42:36 +01:00
parent 0305d8a221
commit a5e8011222
10 changed files with 449 additions and 376 deletions

View File

@ -53,6 +53,7 @@
#include <QRubberBand> #include <QRubberBand>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QTableWidget> #include <QTableWidget>
#include <QMessageBox>
#include <QMap> #include <QMap>
#include <QElapsedTimer> #include <QElapsedTimer>
@ -171,6 +172,7 @@ static ads::CDockWidget* createEditorWidget(QMenu* ViewMenu)
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Editor %1").arg(EditorCount++)); ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Editor %1").arg(EditorCount++));
DockWidget->setWidget(w); DockWidget->setWidget(w);
DockWidget->setIcon(svgIcon(":/adsdemo/images/edit.svg")); DockWidget->setIcon(svgIcon(":/adsdemo/images/edit.svg"));
DockWidget->setFeature(ads::CDockWidget::CustomCloseHandling, true);
ViewMenu->addAction(DockWidget->toggleViewAction()); ViewMenu->addAction(DockWidget->toggleViewAction());
return DockWidget; return DockWidget;
} }
@ -475,6 +477,21 @@ void CMainWindow::createEditor()
DockWidget->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true); DockWidget->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true);
auto FloatingWidget = d->DockManager->addDockWidgetFloating(DockWidget); auto FloatingWidget = d->DockManager->addDockWidgetFloating(DockWidget);
FloatingWidget->move(QPoint(20, 20)); FloatingWidget->move(QPoint(20, 20));
connect(DockWidget, SIGNAL(closeRequested()), SLOT(onEditorCloseRequested()));
}
//============================================================================
void CMainWindow::onEditorCloseRequested()
{
auto DockWidget = qobject_cast<ads::CDockWidget*>(sender());
int Result = QMessageBox::question(this, "Close Editor", QString("Editor %1 "
"contains unsaved changes? Would you like to close it?")
.arg(DockWidget->windowTitle()));
if (QMessageBox::Yes == Result)
{
DockWidget->closeDockWidget();
}
} }

View File

@ -61,6 +61,7 @@ private slots:
void onViewToggled(bool Open); void onViewToggled(bool Open);
void createEditor(); void createEditor();
void createTable(); void createTable();
void onEditorCloseRequested();
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -478,9 +478,16 @@ void CDockAreaTabBar::onCloseOtherTabsRequested()
int Offset = Tab->dockWidget()->features().testFlag( int Offset = Tab->dockWidget()->features().testFlag(
CDockWidget::DockWidgetDeleteOnClose) ? 1 : 0; CDockWidget::DockWidgetDeleteOnClose) ? 1 : 0;
closeTab(i); closeTab(i);
// If the the dock widget blocks closing, i.e. if the flag
// CustomCloseHandling is set, and the dock widget is still open,
// then we do not need to correct the index
if (Tab->dockWidget()->isClosed())
{
i -= Offset; i -= Offset;
} }
} }
}
} }
@ -569,7 +576,7 @@ void CDockAreaTabBar::closeTab(int Index)
{ {
return; return;
} }
Tab->hide(); //Tab->hide();
emit tabCloseRequested(Index); emit tabCloseRequested(Index);
} }

View File

@ -495,7 +495,7 @@ void CDockAreaWidget::onTabCloseRequested(int Index)
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
{ {
//DockWidget->deleteDockWidget(); //DockWidget->deleteDockWidget();
DockWidget->closeDockWidget(); DockWidget->closeDockWidgetInternal();
} }
else else
{ {
@ -758,15 +758,26 @@ CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
//============================================================================ //============================================================================
CDockWidget::DockWidgetFeatures CDockAreaWidget::features() const CDockWidget::DockWidgetFeatures CDockAreaWidget::features(eBitwiseOperator Mode) const
{ {
if (BitwiseAnd == Mode)
{
CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures); CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
for (const auto DockWidget : dockWidgets()) for (const auto DockWidget : dockWidgets())
{ {
Features &= DockWidget->features(); Features &= DockWidget->features();
} }
return Features; return Features;
}
else
{
CDockWidget::DockWidgetFeatures Features(CDockWidget::NoDockWidgetFeatures);
for (const auto DockWidget : dockWidgets())
{
Features |= DockWidget->features();
}
return Features;
}
} }
@ -805,7 +816,7 @@ void CDockAreaWidget::closeArea()
auto OpenDockWidgets = openedDockWidgets(); auto OpenDockWidgets = openedDockWidgets();
if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
{ {
OpenDockWidgets[0]->deleteDockWidget(); OpenDockWidgets[0]->closeDockWidgetInternal();
} }
else else
{ {

View File

@ -238,10 +238,10 @@ public:
* A bitwise and is used to combine the flags of all dock widgets. That * A bitwise and is used to combine the flags of all dock widgets. That
* means, if only one single dock widget does not support a certain flag, * means, if only one single dock widget does not support a certain flag,
* the whole dock are does not support the flag. I.e. if one single * the whole dock are does not support the flag. I.e. if one single
* dock widget in this area is not closabe, the whole dock are is not * dock widget in this area is not closable, the whole dock are is not
* closable. * closable.
*/ */
CDockWidget::DockWidgetFeatures features() const; CDockWidget::DockWidgetFeatures features(eBitwiseOperator Mode = BitwiseAnd) const;
/** /**
* Returns the title bar button corresponding to the given title bar * Returns the title bar button corresponding to the given title bar

View File

@ -1713,10 +1713,24 @@ void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
{ {
for (const auto DockArea : d->DockAreas) for (const auto DockArea : d->DockAreas)
{ {
if (DockArea != KeepOpenArea && DockArea->features().testFlag(CDockWidget::DockWidgetClosable)) if (DockArea == KeepOpenArea)
{ {
DockArea->closeArea(); continue;
} }
if (!DockArea->features(BitwiseAnd).testFlag(CDockWidget::DockWidgetClosable))
{
continue;
}
// We do not close areas with widgets with custom close handling
if (DockArea->features(BitwiseOr).testFlag(CDockWidget::CustomCloseHandling))
{
std::cout << "CDockWidget::CustomCloseHandling" << std::endl;
continue;
}
DockArea->closeArea();
} }
} }

View File

@ -64,7 +64,7 @@ struct DockWidgetPrivate
QBoxLayout* Layout = nullptr; QBoxLayout* Layout = nullptr;
QWidget* Widget = nullptr; QWidget* Widget = nullptr;
CDockWidgetTab* TabWidget = nullptr; CDockWidgetTab* TabWidget = nullptr;
CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures; CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
CDockManager* DockManager = nullptr; CDockManager* DockManager = nullptr;
CDockAreaWidget* DockArea = nullptr; CDockAreaWidget* DockArea = nullptr;
QAction* ToggleViewAction = nullptr; QAction* ToggleViewAction = nullptr;
@ -744,42 +744,40 @@ void CDockWidget::deleteDockWidget()
{ {
dockManager()->removeDockWidget(this); dockManager()->removeDockWidget(this);
deleteLater(); deleteLater();
} d->Closed = true;
//============================================================================
bool CDockWidget::handleCloseRequest()
{
std::cout << "CDockWidget::handleCloseRequest()" << std::endl;
return true;
} }
//============================================================================ //============================================================================
void CDockWidget::closeDockWidget() void CDockWidget::closeDockWidget()
{ {
closeDockWidgetInternal(); closeDockWidgetInternal(true);
} }
//============================================================================ //============================================================================
bool CDockWidget::closeDockWidgetInternal() bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
{ {
if (!ForceClose)
{
emit closeRequested();
}
if (!ForceClose && features().testFlag(CDockWidget::CustomCloseHandling))
{
return false;
}
if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
{
if (handleCloseRequest())
{ {
deleteDockWidget(); deleteDockWidget();
return true;
}
} }
else else
{ {
toggleView(false); toggleView(false);
return true;
} }
return false; return true;
} }

View File

@ -139,7 +139,7 @@ protected:
* Internal close dock widget implementation. * Internal close dock widget implementation.
* The function returns true if the dock widget has been closed or hidden * The function returns true if the dock widget has been closed or hidden
*/ */
bool closeDockWidgetInternal(); bool closeDockWidgetInternal(bool ForceClose = false);
public: public:
using Super = QFrame; using Super = QFrame;
@ -150,7 +150,9 @@ public:
DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored
DockWidgetFloatable = 0x04, DockWidgetFloatable = 0x04,
DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed
AllDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable, CustomCloseHandling = 0x10,
DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable,
AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling,
NoDockWidgetFeatures = 0x00 NoDockWidgetFeatures = 0x00
}; };
Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
@ -461,6 +463,11 @@ signals:
* otherwise it is false. * otherwise it is false.
*/ */
void topLevelChanged(bool topLevel); void topLevelChanged(bool topLevel);
/**
* This signal is emitted, if close is requested
*/
void closeRequested();
}; // class DockWidget }; // class DockWidget
} }
// namespace ads // namespace ads

View File

@ -28,6 +28,8 @@
//============================================================================ //============================================================================
#include "FloatingDockContainer.h" #include "FloatingDockContainer.h"
#include <iostream>
#include <QBoxLayout> #include <QBoxLayout>
#include <QApplication> #include <QApplication>
#include <QMouseEvent> #include <QMouseEvent>
@ -358,9 +360,16 @@ void CFloatingDockContainer::closeEvent(QCloseEvent *event)
auto TopLevelDockWidget = topLevelDockWidget(); auto TopLevelDockWidget = topLevelDockWidget();
if (TopLevelDockWidget && TopLevelDockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) if (TopLevelDockWidget && TopLevelDockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
{ {
TopLevelDockWidget->deleteDockWidget(); if (TopLevelDockWidget->closeDockWidgetInternal())
{
this->deleteLater(); this->deleteLater();
} }
else
{
event->ignore();
return;
}
}
// In Qt version after 5.9.2 there seems to be a bug that causes the // In Qt version after 5.9.2 there seems to be a bug that causes the
// QWidget::event() function to not receive any NonClientArea mouse // QWidget::event() function to not receive any NonClientArea mouse

View File

@ -117,6 +117,15 @@ enum eIcon
IconCount, //!< just a delimiter for range checks IconCount, //!< just a delimiter for range checks
}; };
/**
* For bitwise combination of dock wdget features
*/
enum eBitwiseOperator
{
BitwiseAnd,
BitwiseOr
};
namespace internal namespace internal
{ {
static const bool RestoreTesting = true; static const bool RestoreTesting = true;