mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-25 07:31:33 +08:00
Added new signals restoringState(), stateRestored(), openingPerspective(), perspectiveOpened(), improved restore state function to protect against multiple calls and to prevent show() events for all CDockWidgets and content if the widgets are removed from internal stack layout
This commit is contained in:
parent
b9b72df9d4
commit
496aec211e
@ -40,7 +40,6 @@
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QApplication>
|
||||
#include <QAction>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QXmlStreamReader>
|
||||
@ -72,6 +71,7 @@ struct DockManagerPrivate
|
||||
QMap<QString, QMenu*> ViewMenuGroups;
|
||||
QMenu* ViewMenu;
|
||||
CDockManager::eViewMenuInsertionOrder MenuInsertionOrder = CDockManager::MenuAlphabeticallySorted;
|
||||
bool RestoringState = false;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@ -87,7 +87,12 @@ struct DockManagerPrivate
|
||||
/**
|
||||
* Restores the state
|
||||
*/
|
||||
bool restoreState(const QByteArray &state, int version, bool Testing = internal::Restore);
|
||||
bool restoreStateFromXml(const QByteArray &state, int version, bool Testing = internal::Restore);
|
||||
|
||||
/**
|
||||
* Restore state
|
||||
*/
|
||||
bool restoreState(const QByteArray &state, int version);
|
||||
|
||||
/**
|
||||
* Restores the container with the given index
|
||||
@ -151,12 +156,12 @@ bool DockManagerPrivate::restoreContainer(int Index, QXmlStreamReader& stream, b
|
||||
//============================================================================
|
||||
bool DockManagerPrivate::checkFormat(const QByteArray &state, int version)
|
||||
{
|
||||
return restoreState(state, version, internal::RestoreTesting);
|
||||
return restoreStateFromXml(state, version, internal::RestoreTesting);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockManagerPrivate::restoreState(const QByteArray &state, int version,
|
||||
bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int version,
|
||||
bool Testing)
|
||||
{
|
||||
if (state.isEmpty())
|
||||
@ -209,6 +214,89 @@ bool DockManagerPrivate::restoreState(const QByteArray &state, int version,
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
|
||||
{
|
||||
if (!checkFormat(state, version))
|
||||
{
|
||||
qDebug() << "checkFormat: Error checking format!!!!!!!";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto DockWidget : DockWidgetsMap)
|
||||
{
|
||||
DockWidget->setProperty("dirty", true);
|
||||
}
|
||||
|
||||
if (!restoreStateFromXml(state, version))
|
||||
{
|
||||
qDebug() << "restoreState: Error restoring state!!!!!!!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// All dock widgets, that have not been processed in the restore state
|
||||
// function are invisible to the user now and have no assigned dock area
|
||||
// They do not belong to any dock container, until the user toggles the
|
||||
// toggle view action the next time
|
||||
for (auto DockWidget : DockWidgetsMap)
|
||||
{
|
||||
if (DockWidget->property("dirty").toBool())
|
||||
{
|
||||
DockWidget->flagAsUnassigned();
|
||||
}
|
||||
else
|
||||
{
|
||||
DockWidget->toggleViewInternal(!DockWidget->property("closed").toBool());
|
||||
}
|
||||
}
|
||||
|
||||
// Now all dock areas are properly restored and we setup the index of
|
||||
// The dock areas because the previous toggleView() action has changed
|
||||
// the dock area index
|
||||
for (auto DockContainer : Containers)
|
||||
{
|
||||
for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
|
||||
{
|
||||
CDockAreaWidget* DockArea = DockContainer->dockArea(i);
|
||||
int CurrentIndex = DockArea->property("currentIndex").toInt();
|
||||
int DockWidgetCount = DockArea->dockWidgetsCount();
|
||||
if (CurrentIndex < DockWidgetCount && DockWidgetCount > 1 && CurrentIndex > -1)
|
||||
{
|
||||
auto DockWidget = DockArea->dockWidget(CurrentIndex);
|
||||
if (!DockWidget->isClosed())
|
||||
{
|
||||
DockArea->setCurrentIndex(CurrentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally we need to send the topLevelChanged() signals for all dock
|
||||
// widgets if top level changed
|
||||
for (auto DockContainer : Containers)
|
||||
{
|
||||
CDockWidget* TopLevelDockWidget = DockContainer->topLevelDockWidget();
|
||||
if (TopLevelDockWidget)
|
||||
{
|
||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
|
||||
{
|
||||
auto DockArea = DockContainer->dockArea(i);
|
||||
for (auto DockWidget : DockArea->dockWidgets())
|
||||
{
|
||||
DockWidget->emitTopLevelChanged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockManagerPrivate::addActionToMenu(QAction* Action, QMenu* Menu, bool InsertSorted)
|
||||
{
|
||||
@ -360,84 +448,37 @@ QByteArray CDockManager::saveState(eXmlMode XmlMode, int version) const
|
||||
//============================================================================
|
||||
bool CDockManager::restoreState(const QByteArray &state, int version)
|
||||
{
|
||||
if (!d->checkFormat(state, version))
|
||||
{
|
||||
qDebug() << "checkFormat: Error checking format!!!!!!!";
|
||||
return false;
|
||||
}
|
||||
// Prevent multiple calls as long as state is not restore. This may
|
||||
// happen, if QApplication::processEvents() is called somewhere
|
||||
if (d->RestoringState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto DockWidget : d->DockWidgetsMap)
|
||||
{
|
||||
DockWidget->setProperty("dirty", true);
|
||||
}
|
||||
// We hide the complete dock manager here. Restoring the state means
|
||||
// that DockWidgets are removed from the DockArea internal stack layout
|
||||
// which in turn means, that each time a widget is removed the stack
|
||||
// will show and raise the next available widget which in turn
|
||||
// triggers show events for the dock widgets. To avoid this we hide the
|
||||
// dock manager. Because there will be no processing of application
|
||||
// events until this function is finished, the user will not see this
|
||||
// hiding
|
||||
bool IsVisible = this->isVisibleTo(parentWidget());
|
||||
if (IsVisible)
|
||||
{
|
||||
hide();
|
||||
}
|
||||
d->RestoringState = true;
|
||||
emit restoringState();
|
||||
bool Result = d->restoreState(state, version);
|
||||
d->RestoringState = false;
|
||||
emit stateRestored();
|
||||
if (IsVisible)
|
||||
{
|
||||
show();
|
||||
}
|
||||
|
||||
if (!d->restoreState(state, version))
|
||||
{
|
||||
qDebug() << "restoreState: Error restoring state!!!!!!!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// All dock widgets, that have not been processed in the restore state
|
||||
// function are invisible to the user now and have no assigned dock area
|
||||
// They do not belong to any dock container, until the user toggles the
|
||||
// toggle view action the next time
|
||||
for (auto DockWidget : d->DockWidgetsMap)
|
||||
{
|
||||
if (DockWidget->property("dirty").toBool())
|
||||
{
|
||||
DockWidget->flagAsUnassigned();
|
||||
}
|
||||
else
|
||||
{
|
||||
DockWidget->toggleViewInternal(!DockWidget->property("closed").toBool());
|
||||
}
|
||||
}
|
||||
|
||||
// Now all dock areas are properly restored and we setup the index of
|
||||
// The dock areas because the previous toggleView() action has changed
|
||||
// the dock area index
|
||||
for (auto DockContainer : d->Containers)
|
||||
{
|
||||
for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
|
||||
{
|
||||
CDockAreaWidget* DockArea = DockContainer->dockArea(i);
|
||||
int CurrentIndex = DockArea->property("currentIndex").toInt();
|
||||
int DockWidgetCount = DockArea->dockWidgetsCount();
|
||||
if (CurrentIndex < DockWidgetCount && DockWidgetCount > 1 && CurrentIndex > -1)
|
||||
{
|
||||
auto DockWidget = DockArea->dockWidget(CurrentIndex);
|
||||
if (!DockWidget->isClosed())
|
||||
{
|
||||
DockArea->setCurrentIndex(CurrentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally we need to send the topLevelChanged() signals for all dock
|
||||
// widgets if top level changed
|
||||
for (auto DockContainer : d->Containers)
|
||||
{
|
||||
CDockWidget* TopLevelDockWidget = DockContainer->topLevelDockWidget();
|
||||
if (TopLevelDockWidget)
|
||||
{
|
||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
|
||||
{
|
||||
auto DockArea = DockContainer->dockArea(i);
|
||||
for (auto DockWidget : DockArea->dockWidgets())
|
||||
{
|
||||
DockWidget->emitTopLevelChanged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit stateChanged();
|
||||
return true;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
@ -505,7 +546,9 @@ void CDockManager::openPerspective(const QString& PerspectiveName)
|
||||
return;
|
||||
}
|
||||
|
||||
emit openingPerspective(PerspectiveName);
|
||||
restoreState(Iterator.value());
|
||||
emit perspectiveOpened(PerspectiveName);
|
||||
}
|
||||
|
||||
|
||||
|
@ -276,12 +276,35 @@ signals:
|
||||
*/
|
||||
void perspectiveListChanged();
|
||||
|
||||
/**
|
||||
* This signal is emitted, if the restore function is called, just before
|
||||
* the dock manager starts restoring the state.
|
||||
* If this function is called, nothing has changed yet
|
||||
*/
|
||||
void restoringState();
|
||||
|
||||
/**
|
||||
* This signal is emitted if the state changed in restoreState.
|
||||
* The signal is emitted if the restoreState() function is called or
|
||||
* if the openPerspective() function is called
|
||||
*/
|
||||
void stateChanged();
|
||||
void stateRestored();
|
||||
|
||||
/**
|
||||
* This signal is emitted, if the dock manager starts opening a
|
||||
* perspective.
|
||||
* Opening a perspective may take more than a second if there are
|
||||
* many complex widgets. The application may use this signal
|
||||
* to show some progress indicator or to change the mouse cursor
|
||||
* into a busy cursor.
|
||||
*/
|
||||
void openingPerspective(const QString& PerspectiveName);
|
||||
|
||||
/**
|
||||
* This signal is emitted if the dock manager finished opening a
|
||||
* perspective
|
||||
*/
|
||||
void perspectiveOpened(const QString& PerspectiveName);
|
||||
}; // class DockManager
|
||||
} // namespace ads
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -68,6 +68,7 @@ protected:
|
||||
friend class CDockAreaWidget;
|
||||
friend class CFloatingDockContainer;
|
||||
friend class CDockManager;
|
||||
friend struct DockManagerPrivate;
|
||||
friend struct DockContainerWidgetPrivate;
|
||||
friend class CDockAreaTabBar;
|
||||
friend class CDockWidgetTab;
|
||||
|
Loading…
Reference in New Issue
Block a user