refs #693, integrated GUI close dialog

* utility function in CGuiApplication containing the logic (dialog needed, ..)
* closeEvent function
This commit is contained in:
Klaus Basan
2016-06-30 03:12:59 +02:00
parent 6650f18e57
commit 18112a0394
8 changed files with 125 additions and 26 deletions

View File

@@ -217,6 +217,8 @@ namespace BlackCore
CLogMessage::preformatted(m); CLogMessage::preformatted(m);
} }
// Settings are distributed via DBus. So only one application is responsible for saving. `enableLocalSave()` means
// "this is the application responsible for saving". If swiftgui requests a setting to be saved, it is sent to swiftcore and saved by swiftcore.
CSettingsCache::instance()->enableLocalSave(); CSettingsCache::instance()->enableLocalSave();
} }
@@ -344,6 +346,34 @@ namespace BlackCore
return env; return env;
} }
bool CApplication::hasUnsavedSettings() const
{
return !this->getAllUnsavedSettings().isEmpty();
}
void CApplication::setSettingsAutoSave(bool autoSave)
{
this->m_autoSaveSettings = autoSave;
}
QStringList CApplication::getAllUnsavedSettings() const
{
return CSettingsCache::instance()->getAllUnsavedKeys();
}
CStatusMessage CApplication::saveSettingsByKey(const QStringList &keys)
{
if (keys.isEmpty()) { return CStatusMessage(); }
if (this->supportsContexts())
{
return this->getIContextApplication()->saveSettingsByKey(keys);
}
else
{
return CSettingsCache::instance()->saveToStore(keys);
}
}
QString CApplication::getInfoString(const QString &separator) const QString CApplication::getInfoString(const QString &separator) const
{ {
QString str(CVersion::version()); QString str(CVersion::version());
@@ -604,7 +634,7 @@ namespace BlackCore
CStatusMessage m; CStatusMessage m;
if (this->m_parsed) if (this->m_parsed)
{ {
if (this->supportsContexts()) if (this->supportsContexts() && this->m_autoSaveSettings)
{ {
// this will eventually also call saveToStore // this will eventually also call saveToStore
m = this->getIContextApplication()->saveSettings(); m = this->getIContextApplication()->saveSettings();

View File

@@ -161,6 +161,18 @@ namespace BlackCore
//! To string //! To string
QString getInfoString(const QString &separator) const; QString getInfoString(const QString &separator) const;
//! Unsaved settings
bool hasUnsavedSettings() const;
//! Automatically and always save settings
void setSettingsAutoSave(bool autoSave);
//! All unsave settings
QStringList getAllUnsavedSettings() const;
//! Save all settings
BlackMisc::CStatusMessage saveSettingsByKey(const QStringList &keys);
//! Run event loop //! Run event loop
static int exec(); static int exec();
@@ -226,6 +238,8 @@ namespace BlackCore
//! @{ //! @{
//! Supports contexts //! Supports contexts
//! \remark checks the real availability of the contexts, so it can happen that we want to use contexts, and they are not yet initialized (false here)
//! \sa m_useContexts we use or we will use contexts
bool supportsContexts() const; bool supportsContexts() const;
//! Init the contexts part and start core facade //! Init the contexts part and start core facade
@@ -402,6 +416,8 @@ namespace BlackCore
bool m_signalStartup = true; //!< signal startup automatically bool m_signalStartup = true; //!< signal startup automatically
bool m_devEnv = false; //!< dev. environment bool m_devEnv = false; //!< dev. environment
bool m_unitTest = false; //!< is UNIT test bool m_unitTest = false; //!< is UNIT test
bool m_autoSaveSettings = true;//!< automatically saving all settings
}; };
} // namespace } // namespace

View File

@@ -10,6 +10,7 @@
#include "blackconfig/buildconfig.h" #include "blackconfig/buildconfig.h"
#include "blackcore/data/globalsetup.h" #include "blackcore/data/globalsetup.h"
#include "blackcore/data/updateinfo.h" #include "blackcore/data/updateinfo.h"
#include "blackgui/components/applicationclosedialog.h"
#include "blackgui/guiapplication.h" #include "blackgui/guiapplication.h"
#include "blackgui/guiutility.h" #include "blackgui/guiutility.h"
#include "blackgui/registermetadata.h" #include "blackgui/registermetadata.h"
@@ -23,6 +24,7 @@
#include "blackmisc/verify.h" #include "blackmisc/verify.h"
#include <QAction> #include <QAction>
#include <QCloseEvent>
#include <QApplication> #include <QApplication>
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCoreApplication> #include <QCoreApplication>
@@ -40,11 +42,13 @@
#include <QStyle> #include <QStyle>
#include <QUrl> #include <QUrl>
#include <QWidget> #include <QWidget>
#include <QMainWindow>
#include <QtGlobal> #include <QtGlobal>
using namespace BlackConfig; using namespace BlackConfig;
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackMisc::Network; using namespace BlackMisc::Network;
using namespace BlackGui::Components;
using namespace BlackCore::Data; using namespace BlackCore::Data;
BlackGui::CGuiApplication *sGui = nullptr; // set by constructor BlackGui::CGuiApplication *sGui = nullptr; // set by constructor
@@ -486,12 +490,33 @@ namespace BlackGui
return m_styleSheetUtility.updateFonts(fontFamily, fontSize, fontStyle, fontWeight, fontColor); return m_styleSheetUtility.updateFonts(fontFamily, fontSize, fontStyle, fontWeight, fontColor);
} }
QDialog::DialogCode CGuiApplication::showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent)
{
bool needsDialog = this->hasUnsavedSettings();
if (!needsDialog) { return QDialog::Accepted; }
if (!this->m_closeDialog)
{
this->m_closeDialog = new CApplicationCloseDialog(mainWindow);
if (mainWindow && !mainWindow->windowTitle().isEmpty())
{
this->setSettingsAutoSave(false); // will be handled by dialog
this->m_closeDialog->setWindowTitle(mainWindow->windowTitle());
this->m_closeDialog->setModal(true);
}
}
const QDialog::DialogCode c = static_cast<QDialog::DialogCode>(this->m_closeDialog->exec());
if (c == QDialog::Rejected)
{
if (closeEvent) { closeEvent->ignore(); }
}
return c;
}
void CGuiApplication::cmdLineHelpMessage() void CGuiApplication::cmdLineHelpMessage()
{ {
if (CBuildConfig::isRunningOnWindowsNtPlatform()) if (CBuildConfig::isRunningOnWindowsNtPlatform())
{ {
QMessageBox::information(nullptr, QMessageBox::information(nullptr, QGuiApplication::applicationDisplayName(),
QGuiApplication::applicationDisplayName(),
"<html><head/><body><pre>" + this->m_parser.helpText() + "</pre></body></html>"); "<html><head/><body><pre>" + this->m_parser.helpText() + "</pre></body></html>");
} }
else else
@@ -504,8 +529,7 @@ namespace BlackGui
{ {
if (CBuildConfig::isRunningOnWindowsNtPlatform()) if (CBuildConfig::isRunningOnWindowsNtPlatform())
{ {
QMessageBox::information(nullptr, QMessageBox::information(nullptr, QGuiApplication::applicationDisplayName(),
QGuiApplication::applicationDisplayName(),
QGuiApplication::applicationDisplayName() + ' ' + QCoreApplication::applicationVersion()); QGuiApplication::applicationDisplayName() + ' ' + QCoreApplication::applicationVersion());
} }
else else
@@ -518,5 +542,4 @@ namespace BlackGui
{ {
return true; return true;
} }
} // ns } // ns

View File

@@ -21,6 +21,7 @@
#include "blackmisc/statusmessage.h" #include "blackmisc/statusmessage.h"
#include <QCommandLineOption> #include <QCommandLineOption>
#include <QDialog>
#include <QObject> #include <QObject>
#include <QPixmap> #include <QPixmap>
#include <QScopedPointer> #include <QScopedPointer>
@@ -30,9 +31,10 @@
class QMenu; class QMenu;
class QSplashScreen; class QSplashScreen;
class QWidget; class QWidget;
class QMainWindow;
namespace BlackMisc { class CLogCategoryList; } namespace BlackMisc { class CLogCategoryList; }
namespace BlackGui { namespace Components { class CApplicationCloseDialog; }}
namespace BlackGui namespace BlackGui
{ {
/*! /*!
@@ -138,6 +140,9 @@ namespace BlackGui
//! Update the fonts //! Update the fonts
bool updateFonts(const QString &fontFamily, const QString &fontSize, const QString &fontStyle, const QString &fontWeight, const QString &fontColor); bool updateFonts(const QString &fontFamily, const QString &fontSize, const QString &fontStyle, const QString &fontWeight, const QString &fontColor);
//! Show close dialog
QDialog::DialogCode showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent);
//! Set icon //! Set icon
//! \note Pixmap requires a valid QApplication, so it cannot be passed as constructor parameter //! \note Pixmap requires a valid QApplication, so it cannot be passed as constructor parameter
static void setWindowIcon(const QPixmap &icon); static void setWindowIcon(const QPixmap &icon);
@@ -184,8 +189,9 @@ namespace BlackGui
QCommandLineOption m_cmdWindowStateMinimized { "empty" }; //!< window state (minimized) QCommandLineOption m_cmdWindowStateMinimized { "empty" }; //!< window state (minimized)
QCommandLineOption m_cmdWindowMode { "empty" }; //!< window mode (flags: frameless ...) QCommandLineOption m_cmdWindowMode { "empty" }; //!< window mode (flags: frameless ...)
CStyleSheetUtility m_styleSheetUtility{{}, this}; //!< style sheet utility CStyleSheetUtility m_styleSheetUtility{{}, this}; //!< style sheet utility
QScopedPointer<QSplashScreen> m_splashScreen; //!< splash screen
bool m_uiSetupCompleted = false; //!< ui setup completed bool m_uiSetupCompleted = false; //!< ui setup completed
QScopedPointer<QSplashScreen> m_splashScreen; //!< splash screen
BlackGui::Components::CApplicationCloseDialog *m_closeDialog = nullptr; //!< close dialog (no QScopedPointer because I need to set parent)
//! Qt help message to formatted HTML //! Qt help message to formatted HTML
static QString beautifyHelpMessage(const QString &helpText); static QString beautifyHelpMessage(const QString &helpText);

View File

@@ -58,6 +58,16 @@ void CSwiftData::initStyleSheet()
CSwiftData::~CSwiftData() CSwiftData::~CSwiftData()
{ } { }
void CSwiftData::closeEvent(QCloseEvent *event)
{
if (sGui)
{
// save settings
if (sGui->showCloseDialog(this, event) == QDialog::Rejected) { return; }
}
this->performGracefulShutdown();
}
void CSwiftData::ps_appendLogMessage(const CStatusMessage &message) void CSwiftData::ps_appendLogMessage(const CStatusMessage &message)
{ {
CLogComponent *logComponent = ui->comp_MainInfoArea->getLogComponent(); CLogComponent *logComponent = ui->comp_MainInfoArea->getLogComponent();

View File

@@ -46,6 +46,12 @@ public:
//! Destructor //! Destructor
~CSwiftData(); ~CSwiftData();
protected:
//! \name QMainWindow events
//! @[
virtual void closeEvent(QCloseEvent *event) override;
//! @}
private slots: private slots:
//! Append log message //! Append log message
void ps_appendLogMessage(const BlackMisc::CStatusMessage &message); void ps_appendLogMessage(const BlackMisc::CStatusMessage &message);

View File

@@ -131,9 +131,20 @@ void SwiftGuiStd::performGracefulShutdown()
void SwiftGuiStd::closeEvent(QCloseEvent *event) void SwiftGuiStd::closeEvent(QCloseEvent *event)
{ {
Q_UNUSED(event); if (sGui)
{
if (sGui->getIContextNetwork() && sGui->getIContextNetwork()->isConnected())
{
// we do not just logoff, but give the user a chance to respond
event->ignore();
QTimer::singleShot(500, this, &SwiftGuiStd::ps_loginRequested);
return;
}
// save settings
if (sGui->showCloseDialog(this, event) == QDialog::Rejected) { return; }
}
this->performGracefulShutdown(); this->performGracefulShutdown();
CGuiApplication::exit();
} }
void SwiftGuiStd::changeEvent(QEvent *event) void SwiftGuiStd::changeEvent(QEvent *event)

View File

@@ -80,17 +80,14 @@ signals:
void currentMainInfoAreaChanged(const QWidget *currentWidget); void currentMainInfoAreaChanged(const QWidget *currentWidget);
protected: protected:
//! \copydoc QMainWindow::mouseMoveEvent
//! \name QMainWindow events
//! @[
virtual void mouseMoveEvent(QMouseEvent *event) override; virtual void mouseMoveEvent(QMouseEvent *event) override;
//! \copydoc QMainWindow::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event) override; virtual void mousePressEvent(QMouseEvent *event) override;
//! \copydoc QMainWindow::closeEvent
virtual void closeEvent(QCloseEvent *event) override; virtual void closeEvent(QCloseEvent *event) override;
//! \copydoc QMainWindow::changeEvent
virtual void changeEvent(QEvent *event) override; virtual void changeEvent(QEvent *event) override;
//! @}
//! Get a minimize action which minimizes the window //! Get a minimize action which minimizes the window
QAction *getWindowMinimizeAction(QObject *parent); QAction *getWindowMinimizeAction(QObject *parent);