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 <QPlainTextEdit>
#include <QTableWidget>
#include <QMessageBox>
#include <QMap>
#include <QElapsedTimer>
@ -171,6 +172,7 @@ static ads::CDockWidget* createEditorWidget(QMenu* ViewMenu)
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Editor %1").arg(EditorCount++));
DockWidget->setWidget(w);
DockWidget->setIcon(svgIcon(":/adsdemo/images/edit.svg"));
DockWidget->setFeature(ads::CDockWidget::CustomCloseHandling, true);
ViewMenu->addAction(DockWidget->toggleViewAction());
return DockWidget;
}
@ -475,6 +477,21 @@ void CMainWindow::createEditor()
DockWidget->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true);
auto FloatingWidget = d->DockManager->addDockWidgetFloating(DockWidget);
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 createEditor();
void createTable();
void onEditorCloseRequested();
};
#endif // MAINWINDOW_H

View File

@ -478,9 +478,16 @@ void CDockAreaTabBar::onCloseOtherTabsRequested()
int Offset = Tab->dockWidget()->features().testFlag(
CDockWidget::DockWidgetDeleteOnClose) ? 1 : 0;
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;
}
}
}
}
@ -569,7 +576,7 @@ void CDockAreaTabBar::closeTab(int Index)
{
return;
}
Tab->hide();
//Tab->hide();
emit tabCloseRequested(Index);
}

View File

@ -495,7 +495,7 @@ void CDockAreaWidget::onTabCloseRequested(int Index)
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
{
//DockWidget->deleteDockWidget();
DockWidget->closeDockWidget();
DockWidget->closeDockWidgetInternal();
}
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);
for (const auto DockWidget : dockWidgets())
{
Features &= DockWidget->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();
if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
{
OpenDockWidgets[0]->deleteDockWidget();
OpenDockWidgets[0]->closeDockWidgetInternal();
}
else
{

View File

@ -238,10 +238,10 @@ public:
* 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,
* 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.
*/
CDockWidget::DockWidgetFeatures features() const;
CDockWidget::DockWidgetFeatures features(eBitwiseOperator Mode = BitwiseAnd) const;
/**
* 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)
{
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;
QWidget* Widget = nullptr;
CDockWidgetTab* TabWidget = nullptr;
CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures;
CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
CDockManager* DockManager = nullptr;
CDockAreaWidget* DockArea = nullptr;
QAction* ToggleViewAction = nullptr;
@ -744,42 +744,40 @@ void CDockWidget::deleteDockWidget()
{
dockManager()->removeDockWidget(this);
deleteLater();
}
//============================================================================
bool CDockWidget::handleCloseRequest()
{
std::cout << "CDockWidget::handleCloseRequest()" << std::endl;
return true;
d->Closed = true;
}
//============================================================================
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 (handleCloseRequest())
{
deleteDockWidget();
return true;
}
}
else
{
toggleView(false);
return true;
}
return false;
return true;
}

View File

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

View File

@ -28,6 +28,8 @@
//============================================================================
#include "FloatingDockContainer.h"
#include <iostream>
#include <QBoxLayout>
#include <QApplication>
#include <QMouseEvent>
@ -358,9 +360,16 @@ void CFloatingDockContainer::closeEvent(QCloseEvent *event)
auto TopLevelDockWidget = topLevelDockWidget();
if (TopLevelDockWidget && TopLevelDockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
{
TopLevelDockWidget->deleteDockWidget();
if (TopLevelDockWidget->closeDockWidgetInternal())
{
this->deleteLater();
}
else
{
event->ignore();
return;
}
}
// 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

View File

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